chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicCompanySearchParams,
LeadMagicCompanySearchResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const companySearchTool: ToolConfig<
LeadMagicCompanySearchParams,
LeadMagicCompanySearchResponse
> = {
id: 'leadmagic_company_search',
name: 'LeadMagic Company Search',
description:
'Enrich company data including firmographics, headcount, funding, and social profiles by domain, LinkedIn URL, or name. Charges 1 credit when a company is found; free when no result.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicCompanySearchParams>((_params, output) => {
// 1 credit when company found, 0 otherwise.
// Source: https://leadmagic.io/docs/v1/reference/company-search
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.companyName ? 1 : 0
}),
params: {
company_domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company website domain (e.g., stripe.com). Provide at least one identifier.',
},
profile_url: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'LinkedIn company profile URL (e.g., https://linkedin.com/company/stripe). Provide at least one identifier.',
},
company_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Company name (fallback if domain/URL unavailable). Provide at least one identifier.',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/companies/company-search',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, string> = {}
if (params.company_domain) body.company_domain = params.company_domain
if (params.profile_url) body.profile_url = params.profile_url
if (params.company_name) body.company_name = params.company_name
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
companyName: data.companyName ?? null,
companyId: data.companyId ?? null,
industry: data.industry ?? null,
employeeCount: data.employeeCount ?? null,
employeeRange: data.employeeRange ?? null,
founded: data.founded ?? null,
headquarters: data.headquarters ?? null,
revenue: data.revenue ?? null,
funding: data.funding ?? null,
description: data.description ?? null,
specialties: data.specialties ?? [],
competitors: data.competitors ?? [],
followerCount: data.followerCount ?? null,
twitter_url: data.twitter_url ?? null,
facebook_url: data.facebook_url ?? null,
b2b_profile_url: data.b2b_profile_url ?? null,
logo_url: data.logo_url ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
companyName: { type: 'string', description: 'Company name', optional: true },
companyId: { type: 'number', description: 'Internal company identifier', optional: true },
industry: { type: 'string', description: 'Industry classification', optional: true },
employeeCount: { type: 'number', description: 'Number of employees', optional: true },
employeeRange: {
type: 'string',
description: 'Headcount range (e.g., 1001-5000)',
optional: true,
},
founded: { type: 'number', description: 'Year the company was founded', optional: true },
headquarters: { type: 'json', description: 'Headquarters location object', optional: true },
revenue: { type: 'string', description: 'Revenue range', optional: true },
funding: { type: 'string', description: 'Total funding amount', optional: true },
description: { type: 'string', description: 'Company description', optional: true },
specialties: { type: 'array', description: 'Company specialties and focus areas' },
competitors: { type: 'array', description: 'Competitor companies' },
followerCount: { type: 'number', description: 'LinkedIn follower count', optional: true },
twitter_url: { type: 'string', description: 'Twitter/X profile URL', optional: true },
facebook_url: { type: 'string', description: 'Facebook page URL', optional: true },
b2b_profile_url: {
type: 'string',
description: 'LinkedIn company profile URL',
optional: true,
},
logo_url: { type: 'string', description: 'Company logo URL', optional: true },
credits_consumed: { type: 'number', description: 'Credits charged (1 when company found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
},
}
@@ -0,0 +1,89 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicEmailToProfileParams,
LeadMagicEmailToProfileResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const emailToProfileTool: ToolConfig<
LeadMagicEmailToProfileParams,
LeadMagicEmailToProfileResponse
> = {
id: 'leadmagic_email_to_profile',
name: 'LeadMagic Email to Profile',
description:
'Retrieve a LinkedIn profile URL from a work or personal email address. Charges 10 credits when a profile is found; free when no result.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicEmailToProfileParams>((_params, output) => {
// 10 credits when profile found, 0 otherwise.
// Source: https://leadmagic.io/docs/v1/reference/email-to-profile
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.profile_url ? 10 : 0
}),
params: {
work_email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Work email address (provide at least one of work_email or personal_email)',
},
personal_email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Personal email address (provide at least one of work_email or personal_email)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/b2b-profile',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, string> = {}
if (params.work_email) body.work_email = params.work_email
if (params.personal_email) body.personal_email = params.personal_email
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
profile_url: data.profile_url ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
profile_url: {
type: 'string',
description: 'LinkedIn profile URL for the provided email',
optional: true,
},
credits_consumed: { type: 'number', description: 'Credits charged (10 when profile found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
},
}
+130
View File
@@ -0,0 +1,130 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type { LeadMagicFindEmailParams, LeadMagicFindEmailResponse } from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const findEmailTool: ToolConfig<LeadMagicFindEmailParams, LeadMagicFindEmailResponse> = {
id: 'leadmagic_find_email',
name: 'LeadMagic Find Email',
description:
"Find someone's verified work email from their name and company domain. Charges 1 credit when a valid email is found; free when no result.",
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicFindEmailParams>((_params, output) => {
// 1 credit per valid email found, 0 credits when not found.
// Source: https://leadmagic.io/docs/v1/reference/email-finder
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.email ? 1 : 0
}),
params: {
first_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "Person's first name (use with last_name, or use full_name instead)",
},
last_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "Person's last name (use with first_name, or use full_name instead)",
},
full_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: "Person's full name (alternative to first_name + last_name)",
},
domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company domain (preferred, e.g. stripe.com)',
},
company_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name (fallback if domain is unavailable)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/email-finder',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, string> = {}
if (params.first_name) body.first_name = params.first_name
if (params.last_name) body.last_name = params.last_name
if (params.full_name) body.full_name = params.full_name
if (params.domain) body.domain = params.domain
if (params.company_name) body.company_name = params.company_name
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
email: data.email ?? null,
status: data.status ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
employment_verified: data.employment_verified ?? null,
has_mx: data.has_mx ?? null,
mx_record: data.mx_record ?? null,
mx_provider: data.mx_provider ?? null,
company_name: data.company_name ?? null,
company_industry: data.company_industry ?? null,
company_size: data.company_size ?? null,
company_profile_url: data.company_profile_url ?? null,
},
}
},
outputs: {
email: { type: 'string', description: 'Found work email address', optional: true },
status: { type: 'string', description: 'Result status (valid, invalid, etc.)', optional: true },
credits_consumed: { type: 'number', description: 'Credits charged (1 when email found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
employment_verified: {
type: 'boolean',
description: 'Whether employment at the company was verified',
optional: true,
},
has_mx: {
type: 'boolean',
description: 'Whether the domain has a valid MX record',
optional: true,
},
mx_record: { type: 'string', description: 'MX record for the email domain', optional: true },
mx_provider: { type: 'string', description: 'Email provider', optional: true },
company_name: { type: 'string', description: 'Company name', optional: true },
company_industry: { type: 'string', description: 'Company industry', optional: true },
company_size: { type: 'string', description: 'Company size range', optional: true },
company_profile_url: {
type: 'string',
description: 'Company LinkedIn/B2B profile URL',
optional: true,
},
},
}
+101
View File
@@ -0,0 +1,101 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicFindMobileParams,
LeadMagicFindMobileResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const findMobileTool: ToolConfig<LeadMagicFindMobileParams, LeadMagicFindMobileResponse> = {
id: 'leadmagic_find_mobile',
name: 'LeadMagic Find Mobile',
description:
"Find a person's direct mobile number from their LinkedIn profile URL or email. Charges 5 credits when a number is found; free when no result.",
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicFindMobileParams>((_params, output) => {
// 5 credits per mobile number found, 0 when not found.
// Source: https://leadmagic.io/docs/v1/reference/mobile-finder
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.mobile_number ? 5 : 0
}),
params: {
profile_url: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL (provide at least one identifier)',
},
work_email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Work email address (provide at least one identifier)',
},
personal_email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Personal email address (provide at least one identifier)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/mobile-finder',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, string> = {}
if (params.profile_url) body.profile_url = params.profile_url
if (params.work_email) body.work_email = params.work_email
if (params.personal_email) body.personal_email = params.personal_email
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
profile_url: data.profile_url ?? null,
email: data.email ?? null,
mobile_number: data.mobile_number ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
profile_url: {
type: 'string',
description: 'LinkedIn profile URL used for lookup',
optional: true,
},
email: {
type: 'string',
description: 'Email address associated with the profile',
optional: true,
},
mobile_number: { type: 'string', description: 'Direct mobile phone number', optional: true },
credits_consumed: { type: 'number', description: 'Credits charged (5 when mobile found)' },
message: { type: 'string', description: 'Status message from the API', optional: true },
},
}
+51
View File
@@ -0,0 +1,51 @@
import type {
LeadMagicGetCreditsParams,
LeadMagicGetCreditsResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const getCreditsTool: ToolConfig<LeadMagicGetCreditsParams, LeadMagicGetCreditsResponse> = {
id: 'leadmagic_get_credits',
name: 'LeadMagic Get Credits',
description:
'Retrieve the current credit balance for the authenticated LeadMagic account. This endpoint is free and consumes no credits.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/credits',
method: 'GET',
headers: (params) => ({
'X-API-Key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
credits: data.credits ?? 0,
},
}
},
outputs: {
credits: { type: 'number', description: 'Current credit balance' },
},
}
+48
View File
@@ -0,0 +1,48 @@
import type { ToolHostingConfig } from '@/tools/types'
/**
* Env var prefix for LeadMagic hosted keys. Provide keys as
* `LEADMAGIC_API_KEY_COUNT` plus `LEADMAGIC_API_KEY_1..N`.
*/
export const LEADMAGIC_API_KEY_PREFIX = 'LEADMAGIC_API_KEY'
/**
* Dollar cost of a single LeadMagic credit.
*
* LeadMagic charges only when data is found (not_found results are free).
* Based on the entry Basic plan ($49/month, 2,000 credits ≈ $0.0245/credit);
* per-credit drops at higher tiers (Essential/Growth). Email finder: 1 credit.
* Mobile finder: 5 credits. Company search: 1 credit.
*
* Source: https://leadmagic.io/pricing
*/
export const LEADMAGIC_CREDIT_USD = 0.0245
/**
* Build a LeadMagic `hosting` config. `getCredits` returns the number of
* LeadMagic credits the call consumed, derived from the tool's output (per the
* documented per-endpoint credit model at https://leadmagic.io/docs).
*
* LeadMagic responses include a `credits_consumed` field on every endpoint.
* When no result is found, `credits_consumed` is 0.
*/
export function leadmagicHosting<P>(
getCredits: (params: P, output: Record<string, unknown>) => number
): ToolHostingConfig<P> {
return {
envKeyPrefix: LEADMAGIC_API_KEY_PREFIX,
apiKeyParam: 'apiKey',
byokProviderId: 'leadmagic',
pricing: {
type: 'custom',
getCost: (params, output) => {
const credits = getCredits(params, output)
return { cost: credits * LEADMAGIC_CREDIT_USD, metadata: { credits } }
},
},
rateLimit: {
mode: 'per_request',
requestsPerMinute: 60,
},
}
}
+21
View File
@@ -0,0 +1,21 @@
export * from './types'
import { companySearchTool } from '@/tools/leadmagic/company_search'
import { emailToProfileTool } from '@/tools/leadmagic/email_to_profile'
import { findEmailTool } from '@/tools/leadmagic/find_email'
import { findMobileTool } from '@/tools/leadmagic/find_mobile'
import { getCreditsTool } from '@/tools/leadmagic/get_credits'
import { profileSearchTool } from '@/tools/leadmagic/profile_search'
import { profileToEmailTool } from '@/tools/leadmagic/profile_to_email'
import { roleFinderTool } from '@/tools/leadmagic/role_finder'
import { validateEmailTool } from '@/tools/leadmagic/validate_email'
export const leadmagicValidateEmailTool = validateEmailTool
export const leadmagicFindEmailTool = findEmailTool
export const leadmagicFindMobileTool = findMobileTool
export const leadmagicProfileSearchTool = profileSearchTool
export const leadmagicProfileToEmailTool = profileToEmailTool
export const leadmagicEmailToProfileTool = emailToProfileTool
export const leadmagicCompanySearchTool = companySearchTool
export const leadmagicRoleFinderTool = roleFinderTool
export const leadmagicGetCreditsTool = getCreditsTool
+128
View File
@@ -0,0 +1,128 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicProfileSearchParams,
LeadMagicProfileSearchResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const profileSearchTool: ToolConfig<
LeadMagicProfileSearchParams,
LeadMagicProfileSearchResponse
> = {
id: 'leadmagic_profile_search',
name: 'LeadMagic Profile Search',
description:
'Enrich a LinkedIn profile with work history, education, skills, and contact data. Charges 1 credit per successful enrichment; free when profile not found.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicProfileSearchParams>((_params, output) => {
// 1 credit per successful enrichment, 0 when not found.
// Source: https://leadmagic.io/docs/v1/reference/profile-search
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.full_name ? 1 : 0
}),
params: {
profile_url: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL or username (e.g., https://linkedin.com/in/johndoe)',
},
extended_response: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Include additional profile image URL in the response (default: false)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/profile-search',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = { profile_url: params.profile_url }
if (params.extended_response !== undefined) body.extended_response = params.extended_response
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
profile_url: data.profile_url ?? null,
first_name: data.first_name ?? null,
last_name: data.last_name ?? null,
full_name: data.full_name ?? null,
professional_title: data.professional_title ?? null,
bio: data.bio ?? null,
location: data.location ?? null,
country: data.country ?? null,
followers_range: data.followers_range ?? null,
company_name: data.company_name ?? null,
company_industry: data.company_industry ?? null,
company_website: data.company_website ?? null,
total_tenure_years: data.total_tenure_years ?? null,
total_tenure_months: data.total_tenure_months ?? null,
work_experience: data.work_experience ?? [],
education: data.education ?? [],
certifications: data.certifications ?? [],
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
profile_url: { type: 'string', description: 'LinkedIn profile URL', optional: true },
first_name: { type: 'string', description: 'First name', optional: true },
last_name: { type: 'string', description: 'Last name', optional: true },
full_name: { type: 'string', description: 'Full name', optional: true },
professional_title: { type: 'string', description: 'Current job title', optional: true },
bio: { type: 'string', description: 'Profile bio / summary', optional: true },
location: { type: 'string', description: 'Location string', optional: true },
country: { type: 'string', description: 'Country', optional: true },
followers_range: { type: 'string', description: 'LinkedIn follower range', optional: true },
company_name: { type: 'string', description: 'Current employer', optional: true },
company_industry: {
type: 'string',
description: 'Industry of current employer',
optional: true,
},
company_website: { type: 'string', description: 'Company website', optional: true },
total_tenure_years: {
type: 'string',
description: 'Total professional tenure in years',
optional: true,
},
total_tenure_months: {
type: 'string',
description: 'Total professional tenure in months',
optional: true,
},
work_experience: { type: 'array', description: 'Work history entries' },
education: { type: 'array', description: 'Education history entries' },
certifications: { type: 'array', description: 'Professional certifications' },
credits_consumed: { type: 'number', description: 'Credits charged (1 when profile found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
},
}
@@ -0,0 +1,84 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicProfileToEmailParams,
LeadMagicProfileToEmailResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const profileToEmailTool: ToolConfig<
LeadMagicProfileToEmailParams,
LeadMagicProfileToEmailResponse
> = {
id: 'leadmagic_profile_to_email',
name: 'LeadMagic Profile to Email',
description:
'Extract a verified work email from a LinkedIn profile URL. Charges 5 credits when an email is found; free when no result.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicProfileToEmailParams>((_params, output) => {
// 5 credits when email found, 0 otherwise.
// Source: https://leadmagic.io/docs/v1/reference/profile-to-email
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.email ? 5 : 0
}),
params: {
profile_url: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL or username (e.g., https://linkedin.com/in/johndoe)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/b2b-profile-email',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => ({ profile_url: params.profile_url }),
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
email: data.email ?? null,
profile_url: data.profile_url ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
email: {
type: 'string',
description: 'Work email address found for this profile',
optional: true,
},
profile_url: {
type: 'string',
description: 'LinkedIn profile URL used for lookup',
optional: true,
},
credits_consumed: { type: 'number', description: 'Credits charged (5 when email found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
},
}
+100
View File
@@ -0,0 +1,100 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicRoleFinderParams,
LeadMagicRoleFinderResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const roleFinderTool: ToolConfig<LeadMagicRoleFinderParams, LeadMagicRoleFinderResponse> = {
id: 'leadmagic_role_finder',
name: 'LeadMagic Role Finder',
description:
'Find the person holding a specific job role at a company. Charges 2 credits when a matching person is found; free when no result.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicRoleFinderParams>((_params, output) => {
// 2 credits when a person is found, 0 otherwise.
// Source: https://leadmagic.io/docs/v1/reference/role-finder
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : output.full_name ? 2 : 0
}),
params: {
job_title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Job role to search for (e.g., Head of Sales, CTO). Supports partial matching.',
},
company_domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company website domain (e.g., stripe.com). Provide domain or company_name.',
},
company_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name (fallback if domain unavailable). Provide domain or company_name.',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/role-finder',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, string> = { job_title: params.job_title }
if (params.company_domain) body.company_domain = params.company_domain
if (params.company_name) body.company_name = params.company_name
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
first_name: data.first_name ?? null,
last_name: data.last_name ?? null,
full_name: data.full_name ?? null,
profile_url: data.profile_url ?? null,
job_title: data.job_title ?? null,
company_name: data.company_name ?? null,
company_website: data.company_website ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
},
}
},
outputs: {
first_name: { type: 'string', description: 'First name of the person found', optional: true },
last_name: { type: 'string', description: 'Last name of the person found', optional: true },
full_name: { type: 'string', description: 'Full name of the person found', optional: true },
profile_url: { type: 'string', description: 'LinkedIn profile URL', optional: true },
job_title: { type: 'string', description: 'Verified job title at the company', optional: true },
company_name: { type: 'string', description: 'Company name', optional: true },
company_website: { type: 'string', description: 'Company website', optional: true },
credits_consumed: { type: 'number', description: 'Credits charged (2 when person found)' },
message: { type: 'string', description: 'Human-readable status message', optional: true },
},
}
+249
View File
@@ -0,0 +1,249 @@
import type { OutputProperty, ToolResponse } from '@/tools/types'
interface LeadMagicBaseParams {
apiKey: string
}
// ---------------------------------------------------------------------------
// Shared output property constants
// ---------------------------------------------------------------------------
export const LEADMAGIC_PROFILE_OUTPUT_PROPERTIES = {
profile_url: { type: 'string', description: 'LinkedIn profile URL' },
first_name: { type: 'string', description: 'First name' },
last_name: { type: 'string', description: 'Last name' },
full_name: { type: 'string', description: 'Full name' },
professional_title: { type: 'string', description: 'Current job title', optional: true },
bio: { type: 'string', description: 'Profile bio / summary', optional: true },
location: { type: 'string', description: 'Location string', optional: true },
country: { type: 'string', description: 'Country', optional: true },
company_name: { type: 'string', description: 'Current employer', optional: true },
company_industry: { type: 'string', description: 'Industry of current employer', optional: true },
company_website: { type: 'string', description: 'Company website', optional: true },
} as const satisfies Record<string, OutputProperty>
// ---------------------------------------------------------------------------
// Email Validation
// ---------------------------------------------------------------------------
export interface LeadMagicValidateEmailParams extends LeadMagicBaseParams {
email: string
}
export interface LeadMagicValidateEmailResponse extends ToolResponse {
output: {
email: string
email_status: string
is_domain_catch_all: boolean | null
credits_consumed: number
message: string | null
mx_record: string | null
mx_provider: string | null
mx_gateway: string | null
mx_security_gateway: boolean | null
company_name: string | null
company_industry: string | null
company_size: string | null
}
}
// ---------------------------------------------------------------------------
// Email Finder
// ---------------------------------------------------------------------------
export interface LeadMagicFindEmailParams extends LeadMagicBaseParams {
first_name?: string
last_name?: string
full_name?: string
domain?: string
company_name?: string
}
export interface LeadMagicFindEmailResponse extends ToolResponse {
output: {
email: string | null
status: string | null
credits_consumed: number
message: string | null
employment_verified: boolean | null
has_mx: boolean | null
mx_record: string | null
mx_provider: string | null
company_name: string | null
company_industry: string | null
company_size: string | null
company_profile_url: string | null
}
}
// ---------------------------------------------------------------------------
// Mobile Finder
// ---------------------------------------------------------------------------
export interface LeadMagicFindMobileParams extends LeadMagicBaseParams {
profile_url?: string
work_email?: string
personal_email?: string
}
export interface LeadMagicFindMobileResponse extends ToolResponse {
output: {
profile_url: string | null
email: string | null
mobile_number: string | null
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Profile Search (LinkedIn enrichment by profile URL)
// ---------------------------------------------------------------------------
export interface LeadMagicProfileSearchParams extends LeadMagicBaseParams {
profile_url: string
extended_response?: boolean
}
export interface LeadMagicProfileSearchResponse extends ToolResponse {
output: {
profile_url: string | null
first_name: string | null
last_name: string | null
full_name: string | null
professional_title: string | null
bio: string | null
location: string | null
country: string | null
followers_range: string | null
company_name: string | null
company_industry: string | null
company_website: string | null
total_tenure_years: string | null
total_tenure_months: string | null
work_experience: unknown[]
education: unknown[]
certifications: unknown[]
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Profile to Email (LinkedIn URL → work email)
// ---------------------------------------------------------------------------
export interface LeadMagicProfileToEmailParams extends LeadMagicBaseParams {
profile_url: string
}
export interface LeadMagicProfileToEmailResponse extends ToolResponse {
output: {
email: string | null
profile_url: string | null
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Email to Profile (work/personal email → LinkedIn profile URL)
// ---------------------------------------------------------------------------
export interface LeadMagicEmailToProfileParams extends LeadMagicBaseParams {
work_email?: string
personal_email?: string
}
export interface LeadMagicEmailToProfileResponse extends ToolResponse {
output: {
profile_url: string | null
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Company Search
// ---------------------------------------------------------------------------
export interface LeadMagicCompanySearchParams extends LeadMagicBaseParams {
company_domain?: string
profile_url?: string
company_name?: string
}
export interface LeadMagicCompanySearchResponse extends ToolResponse {
output: {
companyName: string | null
companyId: number | null
industry: string | null
employeeCount: number | null
employeeRange: string | null
founded: number | null
headquarters: Record<string, string> | null
revenue: string | null
funding: string | null
description: string | null
specialties: unknown[]
competitors: unknown[]
followerCount: number | null
twitter_url: string | null
facebook_url: string | null
b2b_profile_url: string | null
logo_url: string | null
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Role Finder
// ---------------------------------------------------------------------------
export interface LeadMagicRoleFinderParams extends LeadMagicBaseParams {
job_title: string
company_domain?: string
company_name?: string
}
export interface LeadMagicRoleFinderResponse extends ToolResponse {
output: {
first_name: string | null
last_name: string | null
full_name: string | null
profile_url: string | null
job_title: string | null
company_name: string | null
company_website: string | null
credits_consumed: number
message: string | null
}
}
// ---------------------------------------------------------------------------
// Get Credits (balance check — free, no hosting)
// ---------------------------------------------------------------------------
export interface LeadMagicGetCreditsParams extends LeadMagicBaseParams {}
export interface LeadMagicGetCreditsResponse extends ToolResponse {
output: {
credits: number
}
}
// ---------------------------------------------------------------------------
// Union response type
// ---------------------------------------------------------------------------
export type LeadMagicResponse =
| LeadMagicValidateEmailResponse
| LeadMagicFindEmailResponse
| LeadMagicFindMobileResponse
| LeadMagicProfileSearchResponse
| LeadMagicProfileToEmailResponse
| LeadMagicEmailToProfileResponse
| LeadMagicCompanySearchResponse
| LeadMagicRoleFinderResponse
| LeadMagicGetCreditsResponse
+119
View File
@@ -0,0 +1,119 @@
import { leadmagicHosting } from '@/tools/leadmagic/hosting'
import type {
LeadMagicValidateEmailParams,
LeadMagicValidateEmailResponse,
} from '@/tools/leadmagic/types'
import type { ToolConfig } from '@/tools/types'
export const validateEmailTool: ToolConfig<
LeadMagicValidateEmailParams,
LeadMagicValidateEmailResponse
> = {
id: 'leadmagic_validate_email',
name: 'LeadMagic Validate Email',
description:
'Verify an email address for deliverability. Charges 0.25 credits for definitive SMTP results (valid/invalid); unknown and RFC-invalid results are free.',
version: '1.0.0',
hosting: leadmagicHosting<LeadMagicValidateEmailParams>((_params, output) => {
// 0.25 credits for valid or SMTP-verified-invalid; free for unknown/syntax failures.
// We use the API-reported credits_consumed field.
// Source: https://leadmagic.io/docs/v1/reference/email-validation
const consumed = output.credits_consumed
return typeof consumed === 'number' ? consumed : 0
}),
params: {
email: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Email address to validate (e.g., john@example.com)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'LeadMagic API Key',
},
},
request: {
url: 'https://api.leadmagic.io/v1/people/email-validation',
method: 'POST',
headers: (params) => ({
'X-API-Key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => ({ email: params.email }),
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(
(errorData as Record<string, string>).message ||
`LeadMagic API error: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
return {
success: true,
output: {
email: data.email ?? '',
email_status: data.email_status ?? '',
is_domain_catch_all: data.is_domain_catch_all ?? null,
credits_consumed: data.credits_consumed ?? 0,
message: data.message ?? null,
mx_record: data.mx_record ?? null,
mx_provider: data.mx_provider ?? null,
mx_gateway: data.mx_gateway ?? null,
mx_security_gateway: data.mx_security_gateway ?? null,
company_name: data.company_name ?? null,
company_industry: data.company_industry ?? null,
company_size: data.company_size ?? null,
},
}
},
outputs: {
email: { type: 'string', description: 'The validated email address' },
email_status: {
type: 'string',
description: 'Validation result: valid, invalid, or unknown',
},
is_domain_catch_all: {
type: 'boolean',
description: 'Whether the domain accepts all emails (catch-all)',
optional: true,
},
credits_consumed: {
type: 'number',
description: 'Credits charged for this request (0.25 for definitive results)',
},
message: { type: 'string', description: 'Human-readable status message', optional: true },
mx_record: { type: 'string', description: 'MX record for the domain', optional: true },
mx_provider: {
type: 'string',
description: 'Email provider (e.g., Google, Microsoft)',
optional: true,
},
mx_gateway: {
type: 'string',
description: 'MX gateway for the domain',
optional: true,
},
mx_security_gateway: {
type: 'boolean',
description: 'Whether the domain uses a security gateway',
optional: true,
},
company_name: {
type: 'string',
description: 'Company name associated with the email domain',
optional: true,
},
company_industry: { type: 'string', description: 'Industry of the company', optional: true },
company_size: { type: 'string', description: 'Company size range', optional: true },
},
}