feat(integrations): add Sixtyfour AI integration (#3981)

* feat(integrations): add Sixtyfour AI integration

Add Sixtyfour AI integration with 4 tools: find_phone, find_email, enrich_lead, enrich_company. Includes block with operation dropdown, API key auth, conditional fields per operation, brand icon, and generated docs.

* fix(integrations): add error handling to sixtyfour tools

Wrap JSON.parse calls in try/catch for enrich_lead and enrich_company.
Add response.ok checks to all 4 tools' transformResponse.

* fix(integrations): use typed Record for leadStruct to fix spread type error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs

* airweave docslink

* turbo update

* more inp/outputs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Waleed
2026-04-06 11:25:37 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent c9b45f4f28
commit 62a7700eb9
18 changed files with 1121 additions and 5 deletions
+36 -1
View File
@@ -2132,7 +2132,15 @@ export function Mem0Icon(props: SVGProps<SVGSVGElement>) {
export function ExtendIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 33 18' fill='none'>
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 33 24' fill='none'>
<path
d='M6.3782 13.7746L4.28874 14.8056C4.11382 14.8899 4.11382 15.1367 4.28874 15.2211L15.8924 20.9462C16.1423 21.068 16.433 21.068 16.6797 20.9462L28.2864 15.2211C28.4582 15.1367 28.4582 14.8899 28.2864 14.8056L26.2 13.7746C27.3838 13.1937 28.5145 12.6378 29.4578 12.1787C30.2605 12.5722 31.0666 12.9689 31.8693 13.3625C32.3003 13.5749 32.5721 14.0123 32.5721 14.4932V15.5426C32.5721 16.0204 32.3003 16.4609 31.8693 16.6733C31.8693 16.6733 19.5816 22.7016 17.5542 23.6887C16.7296 24.0916 15.8955 24.1103 15.0615 23.7043C12.8123 22.6078 1.9646 17.2857 0.705842 16.6672C0.274806 16.4579 0 16.0174 0 15.5395V14.4899C4.1552e-05 14.012 0.271779 13.5715 0.702792 13.3591C1.43993 12.9968 2.2584 12.5973 3.12047 12.1756C4.06685 12.641 5.19446 13.1937 6.3782 13.7746Z'
fill='currentColor'
/>
<path
d='M15.1021 6.30652C15.9017 5.92234 16.717 5.9348 17.5103 6.32207C20.1715 7.62145 22.8297 8.92398 25.4878 10.2265L22.249 11.8257L16.6797 9.07681C16.433 8.955 16.1423 8.955 15.8924 9.07681L10.3262 11.8257L7.0874 10.2265C11.2142 8.20664 15.0743 6.3201 15.1021 6.30652Z'
fill='currentColor'
/>
<path
clipRule='evenodd'
d='M16.2893 0C16.6984 1.91708e-05 17.1074 0.0970011 17.5103 0.293745C22.3018 2.63326 27.0841 4.98521 31.8693 7.33722C32.3003 7.54649 32.5721 7.9868 32.5721 8.46461V9.51422C32.5721 9.99522 32.3004 10.4357 31.8693 10.645C31.8693 10.645 19.5816 16.6732 17.5542 17.6634C17.1357 17.8696 16.692 17.9727 16.2859 17.9727C15.8799 17.9727 15.4707 17.8758 15.0615 17.6759C12.8124 16.5795 1.9646 11.2604 0.705842 10.6419C0.274826 10.4295 2.31482e-05 9.99216 0 9.51117V8.46461C4.59913e-05 7.98366 0.271816 7.54656 0.702792 7.33417C5.8977 4.7819 15.0599 0.301869 15.1021 0.281239C15.4957 0.0938275 15.8801 0 16.2893 0ZM16.2859 2.96124C16.1516 2.96126 16.0173 2.98909 15.8924 3.05153L4.28874 8.77696C4.11382 8.86442 4.11382 9.10831 4.28874 9.19577L15.8924 14.9209C16.0173 14.9802 16.1516 15.0115 16.2859 15.0115C16.4202 15.0115 16.5548 14.9802 16.6797 14.9209L28.2864 9.19577C28.4582 9.10831 28.4582 8.86442 28.2864 8.77696L16.6797 3.05153C16.5548 2.98906 16.4202 2.96124 16.2859 2.96124Z'
@@ -5930,6 +5938,33 @@ export function PulseIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function SixtyfourIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 158 143' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M32.3952 141.17L31.637 140.73V142.481L31.8417 142.603L32.3952 142.921L32.9487 142.603L33.1534 142.481V140.73L32.3952 141.17Z'
fill='currentColor'
/>
<path
d='M33.1534 140.73V142.603H31.637V140.73L32.3952 141.17L33.1534 140.73Z'
fill='currentColor'
/>
<path
d='M93.3271 105.608V106.564L94.0854 106.996L94.8436 106.564V105.608H93.3271Z'
fill='currentColor'
/>
<path
d='M94.8436 105.608V106.564L94.0854 106.996L93.3271 106.564V105.608H94.8436Z'
fill='currentColor'
/>
<path
d='M125.681 12.9895L94.836 30.755L63.9909 12.9895L32.3951 31.1872H32.3875V68.8565L0.79933 87.0542H0.791748V124.723L31.6369 142.481V140.73L2.30822 123.844V89.6701L31.6369 106.564V140.73L32.3951 141.17L33.1533 140.73V106.564L62.482 89.6701V123.844L33.1533 140.73V142.481L63.2402 125.163L93.3271 142.481L93.5318 142.603L94.0853 142.921L94.6388 142.603L94.8436 142.481L125.689 124.723V87.0542L126.235 86.7357L126.439 86.6144L157.284 68.8565V31.1872L125.681 12.9895ZM63.2326 84.8629L33.904 67.9769V33.8031L63.2326 50.6967V84.8629ZM64.7491 50.6967L94.0777 33.8031V67.9769L64.7491 84.8629V50.6967ZM124.172 123.844L94.8436 140.73V106.564L94.0853 106.996L93.3271 106.564V140.73L63.9985 123.844V89.6701L93.3271 106.564V105.608H94.8436V106.564L124.172 89.6701V123.844ZM124.923 84.8629L95.5942 67.9769V33.8031L124.923 50.6891V84.8629ZM155.768 67.9769L126.439 84.8629V50.6967L155.768 33.8031V67.9769Z'
fill='currentColor'
/>
</svg>
)
}
export function SimilarwebIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
+2
View File
@@ -154,6 +154,7 @@ import {
SftpIcon,
ShopifyIcon,
SimilarwebIcon,
SixtyfourIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
@@ -340,6 +341,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
sharepoint: MicrosoftSharepointIcon,
shopify: ShopifyIcon,
similarweb: SimilarwebIcon,
sixtyfour: SixtyfourIcon,
slack: SlackIcon,
smtp: SmtpIcon,
sqs: SQSIcon,
@@ -150,6 +150,7 @@
"sharepoint",
"shopify",
"similarweb",
"sixtyfour",
"slack",
"smtp",
"sqs",
@@ -0,0 +1,128 @@
---
title: Sixtyfour AI
description: Enrich leads and companies with AI-powered research
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="sixtyfour"
color="#000000"
/>
## Usage Instructions
Find emails, phone numbers, and enrich lead or company data with contact information, social profiles, and detailed research using Sixtyfour AI.
## Tools
### `sixtyfour_find_phone`
Find phone numbers for a lead using Sixtyfour AI.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sixtyfour API key |
| `name` | string | Yes | Full name of the person |
| `company` | string | No | Company name |
| `linkedinUrl` | string | No | LinkedIn profile URL |
| `domain` | string | No | Company website domain |
| `email` | string | No | Email address |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `name` | string | Name of the person |
| `company` | string | Company name |
| `phone` | string | Phone number\(s\) found |
| `linkedinUrl` | string | LinkedIn profile URL |
### `sixtyfour_find_email`
Find email addresses for a lead using Sixtyfour AI.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sixtyfour API key |
| `name` | string | Yes | Full name of the person |
| `company` | string | No | Company name |
| `linkedinUrl` | string | No | LinkedIn profile URL |
| `domain` | string | No | Company website domain |
| `phone` | string | No | Phone number |
| `title` | string | No | Job title |
| `mode` | string | No | Email discovery mode: PROFESSIONAL \(default\) or PERSONAL |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `name` | string | Name of the person |
| `company` | string | Company name |
| `title` | string | Job title |
| `phone` | string | Phone number |
| `linkedinUrl` | string | LinkedIn profile URL |
| `emails` | json | Professional email addresses found |
| ↳ `address` | string | Email address |
| ↳ `status` | string | Validation status \(OK or UNKNOWN\) |
| ↳ `type` | string | Email type \(COMPANY or PERSONAL\) |
| `personalEmails` | json | Personal email addresses found \(only in PERSONAL mode\) |
| ↳ `address` | string | Email address |
| ↳ `status` | string | Validation status \(OK or UNKNOWN\) |
| ↳ `type` | string | Email type \(COMPANY or PERSONAL\) |
### `sixtyfour_enrich_lead`
Enrich lead information with contact details, social profiles, and company data using Sixtyfour AI.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sixtyfour API key |
| `leadInfo` | string | Yes | Lead information as JSON object with key-value pairs \(e.g. name, company, title, linkedin\) |
| `struct` | string | Yes | Fields to collect as JSON object. Keys are field names, values are descriptions \(e.g. \{"email": "The individual\'s email address", "phone": "Phone number"\}\) |
| `researchPlan` | string | No | Optional research plan to guide enrichment strategy |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `notes` | string | Research notes about the lead |
| `structuredData` | json | Enriched lead data matching the requested struct fields |
| `references` | json | Source URLs and descriptions used for enrichment |
| `confidenceScore` | number | Quality score for the returned data \(0-10\) |
### `sixtyfour_enrich_company`
Enrich company data with additional information and find associated people using Sixtyfour AI.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `apiKey` | string | Yes | Sixtyfour API key |
| `targetCompany` | string | Yes | Company data as JSON object \(e.g. \{"name": "Acme Inc", "domain": "acme.com"\}\) |
| `struct` | string | Yes | Fields to collect as JSON object. Keys are field names, values are descriptions \(e.g. \{"website": "Company website URL", "num_employees": "Employee count"\}\) |
| `findPeople` | boolean | No | Whether to find people associated with the company |
| `fullOrgChart` | boolean | No | Whether to retrieve the full organizational chart |
| `researchPlan` | string | No | Optional strategy describing how the agent should search for information |
| `peopleFocusPrompt` | string | No | Description of people to find \(roles, responsibilities\) |
| `leadStruct` | string | No | Custom schema for returned lead data as JSON object |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `notes` | string | Research notes about the company |
| `structuredData` | json | Enriched company data matching the requested struct fields |
| `references` | json | Source URLs and descriptions used for enrichment |
| `confidenceScore` | number | Quality score for the returned data \(0-10\) |
@@ -154,6 +154,7 @@ import {
SftpIcon,
ShopifyIcon,
SimilarwebIcon,
SixtyfourIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
@@ -340,6 +341,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
sharepoint: MicrosoftSharepointIcon,
shopify: ShopifyIcon,
similarweb: SimilarwebIcon,
sixtyfour: SixtyfourIcon,
slack: SlackIcon,
smtp: SmtpIcon,
sqs: SQSIcon,
@@ -324,7 +324,7 @@
"longDescription": "Search across your synced data sources using Airweave. Supports semantic search with hybrid, neural, or keyword retrieval strategies. Optionally generate AI-powered answers from search results.",
"bgColor": "#6366F1",
"iconName": "AirweaveIcon",
"docsUrl": "https://docs.airweave.ai",
"docsUrl": "https://docs.sim.ai/tools/airweave",
"operations": [],
"operationCount": 0,
"triggers": [],
@@ -10639,6 +10639,41 @@
"integrationType": "analytics",
"tags": ["marketing", "data-analytics", "seo"]
},
{
"type": "sixtyfour",
"slug": "sixtyfour-ai",
"name": "Sixtyfour AI",
"description": "Enrich leads and companies with AI-powered research",
"longDescription": "Find emails, phone numbers, and enrich lead or company data with contact information, social profiles, and detailed research using Sixtyfour AI.",
"bgColor": "#000000",
"iconName": "SixtyfourIcon",
"docsUrl": "https://docs.sim.ai/tools/sixtyfour",
"operations": [
{
"name": "Find Phone",
"description": "Find phone numbers for a lead using Sixtyfour AI."
},
{
"name": "Find Email",
"description": "Find email addresses for a lead using Sixtyfour AI."
},
{
"name": "Enrich Lead",
"description": "Enrich lead information with contact details, social profiles, and company data using Sixtyfour AI."
},
{
"name": "Enrich Company",
"description": "Enrich company data with additional information and find associated people using Sixtyfour AI."
}
],
"operationCount": 4,
"triggers": [],
"triggerCount": 0,
"authType": "api-key",
"category": "tools",
"integrationType": "sales-intelligence",
"tags": ["enrichment", "sales-engagement"]
},
{
"type": "slack",
"slug": "slack",
+1 -1
View File
@@ -10,7 +10,7 @@ export const AirweaveBlock: BlockConfig<AirweaveSearchResponse> = {
authMode: AuthMode.ApiKey,
longDescription:
'Search across your synced data sources using Airweave. Supports semantic search with hybrid, neural, or keyword retrieval strategies. Optionally generate AI-powered answers from search results.',
docsLink: 'https://docs.airweave.ai',
docsLink: 'https://docs.sim.ai/tools/airweave',
category: 'tools',
integrationType: IntegrationType.Search,
tags: ['vector-search', 'knowledge-base'],
+292
View File
@@ -0,0 +1,292 @@
import { SixtyfourIcon } from '@/components/icons'
import { AuthMode, type BlockConfig, IntegrationType } from '@/blocks/types'
export const SixtyfourBlock: BlockConfig = {
type: 'sixtyfour',
name: 'Sixtyfour AI',
description: 'Enrich leads and companies with AI-powered research',
longDescription:
'Find emails, phone numbers, and enrich lead or company data with contact information, social profiles, and detailed research using Sixtyfour AI.',
docsLink: 'https://docs.sim.ai/tools/sixtyfour',
category: 'tools',
integrationType: IntegrationType.SalesIntelligence,
tags: ['enrichment', 'sales-engagement'],
bgColor: '#000000',
icon: SixtyfourIcon,
authMode: AuthMode.ApiKey,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'Find Phone', id: 'find_phone' },
{ label: 'Find Email', id: 'find_email' },
{ label: 'Enrich Lead', id: 'enrich_lead' },
{ label: 'Enrich Company', id: 'enrich_company' },
],
value: () => 'find_phone',
},
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
required: true,
placeholder: 'Enter your Sixtyfour API key',
password: true,
},
{
id: 'name',
title: 'Name',
type: 'short-input',
placeholder: 'Full name of the person',
required: { field: 'operation', value: ['find_phone', 'find_email'] },
condition: { field: 'operation', value: ['find_phone', 'find_email'] },
},
{
id: 'company',
title: 'Company',
type: 'short-input',
placeholder: 'Company name',
condition: { field: 'operation', value: ['find_phone', 'find_email'] },
},
{
id: 'linkedinUrl',
title: 'LinkedIn URL',
type: 'short-input',
placeholder: 'https://linkedin.com/in/johndoe',
condition: { field: 'operation', value: ['find_phone', 'find_email'] },
mode: 'advanced',
},
{
id: 'domain',
title: 'Domain',
type: 'short-input',
placeholder: 'example.com',
condition: { field: 'operation', value: ['find_phone', 'find_email'] },
mode: 'advanced',
},
{
id: 'emailInput',
title: 'Email',
type: 'short-input',
placeholder: 'Email address',
condition: { field: 'operation', value: 'find_phone' },
mode: 'advanced',
},
{
id: 'phoneInput',
title: 'Phone',
type: 'short-input',
placeholder: 'Phone number',
condition: { field: 'operation', value: 'find_email' },
mode: 'advanced',
},
{
id: 'title',
title: 'Job Title',
type: 'short-input',
placeholder: 'Job title',
condition: { field: 'operation', value: 'find_email' },
mode: 'advanced',
},
{
id: 'mode',
title: 'Mode',
type: 'dropdown',
options: [
{ label: 'Professional', id: 'PROFESSIONAL' },
{ label: 'Personal', id: 'PERSONAL' },
],
value: () => 'PROFESSIONAL',
condition: { field: 'operation', value: 'find_email' },
},
{
id: 'leadInfo',
title: 'Lead Info',
type: 'long-input',
placeholder:
'{"name": "John Doe", "company": "Acme Inc", "title": "CEO", "linkedin": "https://linkedin.com/in/johndoe"}',
required: { field: 'operation', value: 'enrich_lead' },
condition: { field: 'operation', value: 'enrich_lead' },
},
{
id: 'leadStruct',
title: 'Fields to Collect',
type: 'long-input',
placeholder:
'{"email": "Email address", "phone": "Phone number", "company": "Company name", "title": "Job title"}',
required: { field: 'operation', value: 'enrich_lead' },
condition: { field: 'operation', value: 'enrich_lead' },
},
{
id: 'leadResearchPlan',
title: 'Research Plan',
type: 'long-input',
placeholder: 'Optional guidance for the enrichment agent',
condition: { field: 'operation', value: 'enrich_lead' },
mode: 'advanced',
},
{
id: 'targetCompany',
title: 'Company Info',
type: 'long-input',
placeholder: '{"name": "Acme Inc", "domain": "acme.com", "industry": "Technology"}',
required: { field: 'operation', value: 'enrich_company' },
condition: { field: 'operation', value: 'enrich_company' },
},
{
id: 'companyStruct',
title: 'Fields to Collect',
type: 'long-input',
placeholder:
'{"website": "Company website URL", "num_employees": "Employee count", "address": "Company address"}',
required: { field: 'operation', value: 'enrich_company' },
condition: { field: 'operation', value: 'enrich_company' },
},
{
id: 'findPeople',
title: 'Find People',
type: 'switch',
condition: { field: 'operation', value: 'enrich_company' },
},
{
id: 'peopleFocusPrompt',
title: 'People Focus',
type: 'short-input',
placeholder: 'e.g. Find the VP of Marketing and the CTO',
condition: { field: 'operation', value: 'enrich_company' },
mode: 'advanced',
},
{
id: 'fullOrgChart',
title: 'Full Org Chart',
type: 'switch',
condition: { field: 'operation', value: 'enrich_company' },
mode: 'advanced',
},
{
id: 'companyLeadStruct',
title: 'Lead Schema',
type: 'long-input',
placeholder: '{"name": "Full name", "email": "Email", "title": "Job title"}',
condition: { field: 'operation', value: 'enrich_company' },
mode: 'advanced',
},
{
id: 'companyResearchPlan',
title: 'Research Plan',
type: 'long-input',
placeholder: 'Optional guidance for the enrichment agent',
condition: { field: 'operation', value: 'enrich_company' },
mode: 'advanced',
},
],
tools: {
access: [
'sixtyfour_find_phone',
'sixtyfour_find_email',
'sixtyfour_enrich_lead',
'sixtyfour_enrich_company',
],
config: {
tool: (params) => `sixtyfour_${params.operation}`,
params: (params) => {
const result: Record<string, unknown> = {}
if (params.operation === 'find_phone') {
if (params.emailInput) result.email = params.emailInput
} else if (params.operation === 'find_email') {
if (params.phoneInput) result.phone = params.phoneInput
} else if (params.operation === 'enrich_lead') {
result.leadInfo = params.leadInfo
result.struct = params.leadStruct
if (params.leadResearchPlan) result.researchPlan = params.leadResearchPlan
} else if (params.operation === 'enrich_company') {
result.targetCompany = params.targetCompany
result.struct = params.companyStruct
if (params.findPeople !== undefined) result.findPeople = Boolean(params.findPeople)
if (params.fullOrgChart !== undefined) result.fullOrgChart = Boolean(params.fullOrgChart)
if (params.peopleFocusPrompt) result.peopleFocusPrompt = params.peopleFocusPrompt
if (params.companyLeadStruct) result.leadStruct = params.companyLeadStruct
if (params.companyResearchPlan) result.researchPlan = params.companyResearchPlan
}
return result
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
apiKey: { type: 'string', description: 'Sixtyfour API key' },
name: { type: 'string', description: 'Person name' },
company: { type: 'string', description: 'Company name' },
linkedinUrl: { type: 'string', description: 'LinkedIn URL' },
domain: { type: 'string', description: 'Company domain' },
emailInput: { type: 'string', description: 'Email address (find phone)' },
phoneInput: { type: 'string', description: 'Phone number (find email)' },
title: { type: 'string', description: 'Job title' },
mode: { type: 'string', description: 'Email mode (PROFESSIONAL or PERSONAL)' },
leadInfo: { type: 'string', description: 'Lead information JSON' },
leadStruct: { type: 'string', description: 'Fields to collect for lead' },
leadResearchPlan: { type: 'string', description: 'Research plan for lead enrichment' },
targetCompany: { type: 'string', description: 'Company information JSON' },
companyStruct: { type: 'string', description: 'Fields to collect for company' },
findPeople: { type: 'boolean', description: 'Find associated people' },
fullOrgChart: { type: 'boolean', description: 'Retrieve full org chart' },
peopleFocusPrompt: { type: 'string', description: 'People focus description' },
companyLeadStruct: { type: 'string', description: 'Lead schema for company enrichment' },
companyResearchPlan: { type: 'string', description: 'Research plan for company enrichment' },
},
outputs: {
name: {
type: 'string',
description: 'Name of the person (find_phone, find_email)',
},
company: {
type: 'string',
description: 'Company name (find_phone, find_email)',
},
phone: {
type: 'string',
description: 'Phone number(s) found (find_phone)',
},
linkedinUrl: {
type: 'string',
description: 'LinkedIn profile URL (find_phone, find_email)',
},
title: {
type: 'string',
description: 'Job title (find_email)',
},
emails: {
type: 'json',
description: 'Email addresses found with validation status and type (find_email)',
},
personalEmails: {
type: 'json',
description: 'Personal email addresses found in PERSONAL mode (find_email)',
},
notes: {
type: 'string',
description: 'Research notes (enrich_lead, enrich_company)',
},
structuredData: {
type: 'json',
description:
'Enriched data matching the requested struct fields (enrich_lead, enrich_company)',
},
references: {
type: 'json',
description: 'Source URLs and descriptions used for enrichment (enrich_lead, enrich_company)',
},
confidenceScore: {
type: 'number',
description: 'Quality score for the returned data, 0-10 (enrich_lead, enrich_company)',
},
},
}
+2
View File
@@ -171,6 +171,7 @@ import { SftpBlock } from '@/blocks/blocks/sftp'
import { SharepointBlock } from '@/blocks/blocks/sharepoint'
import { ShopifyBlock } from '@/blocks/blocks/shopify'
import { SimilarwebBlock } from '@/blocks/blocks/similarweb'
import { SixtyfourBlock } from '@/blocks/blocks/sixtyfour'
import { SlackBlock } from '@/blocks/blocks/slack'
import { SmtpBlock } from '@/blocks/blocks/smtp'
import { SpotifyBlock } from '@/blocks/blocks/spotify'
@@ -407,6 +408,7 @@ export const registry: Record<string, BlockConfig> = {
sharepoint: SharepointBlock,
shopify: ShopifyBlock,
similarweb: SimilarwebBlock,
sixtyfour: SixtyfourBlock,
slack: SlackBlock,
smtp: SmtpBlock,
spotify: SpotifyBlock,
+36 -1
View File
@@ -2132,7 +2132,15 @@ export function Mem0Icon(props: SVGProps<SVGSVGElement>) {
export function ExtendIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 33 18' fill='none'>
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 33 24' fill='none'>
<path
d='M6.3782 13.7746L4.28874 14.8056C4.11382 14.8899 4.11382 15.1367 4.28874 15.2211L15.8924 20.9462C16.1423 21.068 16.433 21.068 16.6797 20.9462L28.2864 15.2211C28.4582 15.1367 28.4582 14.8899 28.2864 14.8056L26.2 13.7746C27.3838 13.1937 28.5145 12.6378 29.4578 12.1787C30.2605 12.5722 31.0666 12.9689 31.8693 13.3625C32.3003 13.5749 32.5721 14.0123 32.5721 14.4932V15.5426C32.5721 16.0204 32.3003 16.4609 31.8693 16.6733C31.8693 16.6733 19.5816 22.7016 17.5542 23.6887C16.7296 24.0916 15.8955 24.1103 15.0615 23.7043C12.8123 22.6078 1.9646 17.2857 0.705842 16.6672C0.274806 16.4579 0 16.0174 0 15.5395V14.4899C4.1552e-05 14.012 0.271779 13.5715 0.702792 13.3591C1.43993 12.9968 2.2584 12.5973 3.12047 12.1756C4.06685 12.641 5.19446 13.1937 6.3782 13.7746Z'
fill='currentColor'
/>
<path
d='M15.1021 6.30652C15.9017 5.92234 16.717 5.9348 17.5103 6.32207C20.1715 7.62145 22.8297 8.92398 25.4878 10.2265L22.249 11.8257L16.6797 9.07681C16.433 8.955 16.1423 8.955 15.8924 9.07681L10.3262 11.8257L7.0874 10.2265C11.2142 8.20664 15.0743 6.3201 15.1021 6.30652Z'
fill='currentColor'
/>
<path
clipRule='evenodd'
d='M16.2893 0C16.6984 1.91708e-05 17.1074 0.0970011 17.5103 0.293745C22.3018 2.63326 27.0841 4.98521 31.8693 7.33722C32.3003 7.54649 32.5721 7.9868 32.5721 8.46461V9.51422C32.5721 9.99522 32.3004 10.4357 31.8693 10.645C31.8693 10.645 19.5816 16.6732 17.5542 17.6634C17.1357 17.8696 16.692 17.9727 16.2859 17.9727C15.8799 17.9727 15.4707 17.8758 15.0615 17.6759C12.8124 16.5795 1.9646 11.2604 0.705842 10.6419C0.274826 10.4295 2.31482e-05 9.99216 0 9.51117V8.46461C4.59913e-05 7.98366 0.271816 7.54656 0.702792 7.33417C5.8977 4.7819 15.0599 0.301869 15.1021 0.281239C15.4957 0.0938275 15.8801 0 16.2893 0ZM16.2859 2.96124C16.1516 2.96126 16.0173 2.98909 15.8924 3.05153L4.28874 8.77696C4.11382 8.86442 4.11382 9.10831 4.28874 9.19577L15.8924 14.9209C16.0173 14.9802 16.1516 15.0115 16.2859 15.0115C16.4202 15.0115 16.5548 14.9802 16.6797 14.9209L28.2864 9.19577C28.4582 9.10831 28.4582 8.86442 28.2864 8.77696L16.6797 3.05153C16.5548 2.98906 16.4202 2.96124 16.2859 2.96124Z'
@@ -5930,6 +5938,33 @@ export function PulseIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function SixtyfourIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 158 143' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M32.3952 141.17L31.637 140.73V142.481L31.8417 142.603L32.3952 142.921L32.9487 142.603L33.1534 142.481V140.73L32.3952 141.17Z'
fill='currentColor'
/>
<path
d='M33.1534 140.73V142.603H31.637V140.73L32.3952 141.17L33.1534 140.73Z'
fill='currentColor'
/>
<path
d='M93.3271 105.608V106.564L94.0854 106.996L94.8436 106.564V105.608H93.3271Z'
fill='currentColor'
/>
<path
d='M94.8436 105.608V106.564L94.0854 106.996L93.3271 106.564V105.608H94.8436Z'
fill='currentColor'
/>
<path
d='M125.681 12.9895L94.836 30.755L63.9909 12.9895L32.3951 31.1872H32.3875V68.8565L0.79933 87.0542H0.791748V124.723L31.6369 142.481V140.73L2.30822 123.844V89.6701L31.6369 106.564V140.73L32.3951 141.17L33.1533 140.73V106.564L62.482 89.6701V123.844L33.1533 140.73V142.481L63.2402 125.163L93.3271 142.481L93.5318 142.603L94.0853 142.921L94.6388 142.603L94.8436 142.481L125.689 124.723V87.0542L126.235 86.7357L126.439 86.6144L157.284 68.8565V31.1872L125.681 12.9895ZM63.2326 84.8629L33.904 67.9769V33.8031L63.2326 50.6967V84.8629ZM64.7491 50.6967L94.0777 33.8031V67.9769L64.7491 84.8629V50.6967ZM124.172 123.844L94.8436 140.73V106.564L94.0853 106.996L93.3271 106.564V140.73L63.9985 123.844V89.6701L93.3271 106.564V105.608H94.8436V106.564L124.172 89.6701V123.844ZM124.923 84.8629L95.5942 67.9769V33.8031L124.923 50.6891V84.8629ZM155.768 67.9769L126.439 84.8629V50.6967L155.768 33.8031V67.9769Z'
fill='currentColor'
/>
</svg>
)
}
export function SimilarwebIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
+10
View File
@@ -2197,6 +2197,12 @@ import {
similarwebVisitDurationTool,
similarwebWebsiteOverviewTool,
} from '@/tools/similarweb'
import {
sixtyfourEnrichCompanyTool,
sixtyfourEnrichLeadTool,
sixtyfourFindEmailTool,
sixtyfourFindPhoneTool,
} from '@/tools/sixtyfour'
import {
slackAddReactionTool,
slackCanvasTool,
@@ -3145,6 +3151,10 @@ export const tools: Record<string, ToolConfig> = {
servicenow_read_record: servicenowReadRecordTool,
servicenow_update_record: servicenowUpdateRecordTool,
servicenow_delete_record: servicenowDeleteRecordTool,
sixtyfour_find_phone: sixtyfourFindPhoneTool,
sixtyfour_find_email: sixtyfourFindEmailTool,
sixtyfour_enrich_lead: sixtyfourEnrichLeadTool,
sixtyfour_enrich_company: sixtyfourEnrichCompanyTool,
tavily_search: tavilySearchTool,
tavily_extract: tavilyExtractTool,
tavily_crawl: tavilyCrawlTool,
+143
View File
@@ -0,0 +1,143 @@
import type {
SixtyfourEnrichCompanyParams,
SixtyfourEnrichCompanyResponse,
} from '@/tools/sixtyfour/types'
import type { ToolConfig } from '@/tools/types'
export const sixtyfourEnrichCompanyTool: ToolConfig<
SixtyfourEnrichCompanyParams,
SixtyfourEnrichCompanyResponse
> = {
id: 'sixtyfour_enrich_company',
name: 'Sixtyfour Enrich Company',
description:
'Enrich company data with additional information and find associated people using Sixtyfour AI.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sixtyfour API key',
},
targetCompany: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Company data as JSON object (e.g. {"name": "Acme Inc", "domain": "acme.com"})',
},
struct: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Fields to collect as JSON object. Keys are field names, values are descriptions (e.g. {"website": "Company website URL", "num_employees": "Employee count"})',
},
findPeople: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to find people associated with the company',
},
fullOrgChart: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to retrieve the full organizational chart',
},
researchPlan: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional strategy describing how the agent should search for information',
},
peopleFocusPrompt: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of people to find (roles, responsibilities)',
},
leadStruct: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Custom schema for returned lead data as JSON object',
},
},
request: {
url: 'https://api.sixtyfour.ai/enrich-company',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
'x-api-key': params.apiKey,
}),
body: (params) => {
let targetCompany: unknown
try {
targetCompany =
typeof params.targetCompany === 'string'
? JSON.parse(params.targetCompany)
: params.targetCompany
} catch {
throw new Error('targetCompany must be valid JSON')
}
let struct: unknown
try {
struct = typeof params.struct === 'string' ? JSON.parse(params.struct) : params.struct
} catch {
throw new Error('struct must be valid JSON')
}
let leadStruct: Record<string, unknown> | undefined
try {
leadStruct =
params.leadStruct && typeof params.leadStruct === 'string'
? (JSON.parse(params.leadStruct) as Record<string, unknown>)
: (params.leadStruct as Record<string, unknown> | undefined)
} catch {
throw new Error('leadStruct must be valid JSON')
}
return {
target_company: targetCompany,
struct,
...(params.findPeople !== undefined && { find_people: params.findPeople }),
...(params.fullOrgChart !== undefined && { full_org_chart: params.fullOrgChart }),
...(params.researchPlan && { research_plan: params.researchPlan }),
...(params.peopleFocusPrompt && { people_focus_prompt: params.peopleFocusPrompt }),
...(leadStruct && { lead_struct: leadStruct }),
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || data.message || data.detail || `API error: ${response.status}`)
}
return {
success: true,
output: {
notes: data.notes ?? null,
structuredData: data.structured_data ?? {},
references: data.references ?? {},
confidenceScore: data.confidence_score ?? null,
},
}
},
outputs: {
notes: { type: 'string', description: 'Research notes about the company', optional: true },
structuredData: {
type: 'json',
description: 'Enriched company data matching the requested struct fields',
},
references: { type: 'json', description: 'Source URLs and descriptions used for enrichment' },
confidenceScore: {
type: 'number',
description: 'Quality score for the returned data (0-10)',
optional: true,
},
},
}
+105
View File
@@ -0,0 +1,105 @@
import type {
SixtyfourEnrichLeadParams,
SixtyfourEnrichLeadResponse,
} from '@/tools/sixtyfour/types'
import type { ToolConfig } from '@/tools/types'
export const sixtyfourEnrichLeadTool: ToolConfig<
SixtyfourEnrichLeadParams,
SixtyfourEnrichLeadResponse
> = {
id: 'sixtyfour_enrich_lead',
name: 'Sixtyfour Enrich Lead',
description:
'Enrich lead information with contact details, social profiles, and company data using Sixtyfour AI.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sixtyfour API key',
},
leadInfo: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Lead information as JSON object with key-value pairs (e.g. name, company, title, linkedin)',
},
struct: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Fields to collect as JSON object. Keys are field names, values are descriptions (e.g. {"email": "The individual\'s email address", "phone": "Phone number"})',
},
researchPlan: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional research plan to guide enrichment strategy',
},
},
request: {
url: 'https://api.sixtyfour.ai/enrich-lead',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
'x-api-key': params.apiKey,
}),
body: (params) => {
let leadInfo: unknown
try {
leadInfo =
typeof params.leadInfo === 'string' ? JSON.parse(params.leadInfo) : params.leadInfo
} catch {
throw new Error('leadInfo must be valid JSON')
}
let struct: unknown
try {
struct = typeof params.struct === 'string' ? JSON.parse(params.struct) : params.struct
} catch {
throw new Error('struct must be valid JSON')
}
return {
lead_info: leadInfo,
struct,
...(params.researchPlan && { research_plan: params.researchPlan }),
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || data.message || data.detail || `API error: ${response.status}`)
}
return {
success: true,
output: {
notes: data.notes ?? null,
structuredData: data.structured_data ?? {},
references: data.references ?? {},
confidenceScore: data.confidence_score ?? null,
},
}
},
outputs: {
notes: { type: 'string', description: 'Research notes about the lead', optional: true },
structuredData: {
type: 'json',
description: 'Enriched lead data matching the requested struct fields',
},
references: { type: 'json', description: 'Source URLs and descriptions used for enrichment' },
confidenceScore: {
type: 'number',
description: 'Quality score for the returned data (0-10)',
optional: true,
},
},
}
+144
View File
@@ -0,0 +1,144 @@
import type { SixtyfourFindEmailParams, SixtyfourFindEmailResponse } from '@/tools/sixtyfour/types'
import type { ToolConfig } from '@/tools/types'
function parseEmails(emailField: unknown): { address: string; status: string; type: string }[] {
if (!Array.isArray(emailField)) return []
return emailField.map((entry: unknown) => {
if (Array.isArray(entry)) {
return {
address: entry[0] ?? '',
status: entry[1] ?? 'UNKNOWN',
type: entry[2] ?? 'UNKNOWN',
}
}
return { address: String(entry), status: 'UNKNOWN', type: 'UNKNOWN' }
})
}
export const sixtyfourFindEmailTool: ToolConfig<
SixtyfourFindEmailParams,
SixtyfourFindEmailResponse
> = {
id: 'sixtyfour_find_email',
name: 'Sixtyfour Find Email',
description: 'Find email addresses for a lead using Sixtyfour AI.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sixtyfour API key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full name of the person',
},
company: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name',
},
linkedinUrl: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL',
},
domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company website domain',
},
phone: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Phone number',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Job title',
},
mode: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Email discovery mode: PROFESSIONAL (default) or PERSONAL',
},
},
request: {
url: 'https://api.sixtyfour.ai/find-email',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
'x-api-key': params.apiKey,
}),
body: (params) => ({
lead: {
name: params.name,
...(params.company && { company: params.company }),
...(params.linkedinUrl && { linkedin: params.linkedinUrl }),
...(params.domain && { domain: params.domain }),
...(params.phone && { phone: params.phone }),
...(params.title && { title: params.title }),
},
...(params.mode && { mode: params.mode }),
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || data.message || data.detail || `API error: ${response.status}`)
}
return {
success: true,
output: {
name: data.name ?? null,
company: data.company ?? null,
title: data.title ?? null,
phone: data.phone ?? null,
linkedinUrl: data.linkedin ?? null,
emails: parseEmails(data.email),
personalEmails: parseEmails(data.personal_email),
},
}
},
outputs: {
name: { type: 'string', description: 'Name of the person', optional: true },
company: { type: 'string', description: 'Company name', optional: true },
title: { type: 'string', description: 'Job title', optional: true },
phone: { type: 'string', description: 'Phone number', optional: true },
linkedinUrl: { type: 'string', description: 'LinkedIn profile URL', optional: true },
emails: {
type: 'json',
description: 'Professional email addresses found',
properties: {
address: { type: 'string', description: 'Email address' },
status: { type: 'string', description: 'Validation status (OK or UNKNOWN)' },
type: { type: 'string', description: 'Email type (COMPANY or PERSONAL)' },
},
},
personalEmails: {
type: 'json',
description: 'Personal email addresses found (only in PERSONAL mode)',
optional: true,
properties: {
address: { type: 'string', description: 'Email address' },
status: { type: 'string', description: 'Validation status (OK or UNKNOWN)' },
type: { type: 'string', description: 'Email type (COMPANY or PERSONAL)' },
},
},
},
}
+100
View File
@@ -0,0 +1,100 @@
import type { SixtyfourFindPhoneParams, SixtyfourFindPhoneResponse } from '@/tools/sixtyfour/types'
import type { ToolConfig } from '@/tools/types'
export const sixtyfourFindPhoneTool: ToolConfig<
SixtyfourFindPhoneParams,
SixtyfourFindPhoneResponse
> = {
id: 'sixtyfour_find_phone',
name: 'Sixtyfour Find Phone',
description: 'Find phone numbers for a lead using Sixtyfour AI.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sixtyfour API key',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full name of the person',
},
company: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name',
},
linkedinUrl: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL',
},
domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company website domain',
},
email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Email address',
},
},
request: {
url: 'https://api.sixtyfour.ai/find-phone',
method: 'POST',
headers: (params) => ({
'Content-Type': 'application/json',
'x-api-key': params.apiKey,
}),
body: (params) => ({
lead: {
name: params.name,
...(params.company && { company: params.company }),
...(params.linkedinUrl && { linkedin_url: params.linkedinUrl }),
...(params.domain && { domain: params.domain }),
...(params.email && { email: params.email }),
},
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || data.message || data.detail || `API error: ${response.status}`)
}
let phone: string | null = null
if (typeof data.phone === 'string') {
phone = data.phone || null
} else if (Array.isArray(data.phone)) {
phone = data.phone.map((p: { number: string; region?: string }) => p.number).join(', ')
}
return {
success: true,
output: {
name: data.name ?? null,
company: data.company ?? null,
phone,
linkedinUrl: data.linkedin_url ?? null,
},
}
},
outputs: {
name: { type: 'string', description: 'Name of the person', optional: true },
company: { type: 'string', description: 'Company name', optional: true },
phone: { type: 'string', description: 'Phone number(s) found', optional: true },
linkedinUrl: { type: 'string', description: 'LinkedIn profile URL', optional: true },
},
}
+4
View File
@@ -0,0 +1,4 @@
export { sixtyfourEnrichCompanyTool } from '@/tools/sixtyfour/enrich_company'
export { sixtyfourEnrichLeadTool } from '@/tools/sixtyfour/enrich_lead'
export { sixtyfourFindEmailTool } from '@/tools/sixtyfour/find_email'
export { sixtyfourFindPhoneTool } from '@/tools/sixtyfour/find_phone'
+78
View File
@@ -0,0 +1,78 @@
import type { ToolResponse } from '@/tools/types'
export interface SixtyfourFindPhoneParams {
apiKey: string
name: string
company?: string
linkedinUrl?: string
domain?: string
email?: string
}
export interface SixtyfourFindEmailParams {
apiKey: string
name: string
company?: string
linkedinUrl?: string
domain?: string
phone?: string
title?: string
mode?: string
}
export interface SixtyfourEnrichLeadParams {
apiKey: string
leadInfo: string
struct: string
researchPlan?: string
}
export interface SixtyfourEnrichCompanyParams {
apiKey: string
targetCompany: string
struct: string
findPeople?: boolean
fullOrgChart?: boolean
researchPlan?: string
peopleFocusPrompt?: string
leadStruct?: string
}
export interface SixtyfourFindPhoneResponse extends ToolResponse {
output: {
name: string | null
company: string | null
phone: string | null
linkedinUrl: string | null
}
}
export interface SixtyfourFindEmailResponse extends ToolResponse {
output: {
name: string | null
company: string | null
title: string | null
phone: string | null
linkedinUrl: string | null
emails: { address: string; status: string; type: string }[]
personalEmails: { address: string; status: string; type: string }[]
}
}
export interface SixtyfourEnrichLeadResponse extends ToolResponse {
output: {
notes: string | null
structuredData: Record<string, unknown>
references: Record<string, string>
confidenceScore: number | null
}
}
export interface SixtyfourEnrichCompanyResponse extends ToolResponse {
output: {
notes: string | null
structuredData: Record<string, unknown>
references: Record<string, string>
confidenceScore: number | null
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"$schema": "https://turbo.build/schema.json",
"$schema": "https://v2-9-4.turborepo.dev/schema.json",
"envMode": "loose",
"tasks": {
"transit": {