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
+152
View File
@@ -0,0 +1,152 @@
import type { ToolConfig } from '@/tools/types'
import { wizaHosting } from '@/tools/wiza/hosting'
import type { WizaCompanyEnrichmentParams, WizaCompanyEnrichmentResponse } from '@/tools/wiza/types'
export const wizaCompanyEnrichmentTool: ToolConfig<
WizaCompanyEnrichmentParams,
WizaCompanyEnrichmentResponse
> = {
id: 'wiza_company_enrichment',
name: 'Wiza Company Enrichment',
description:
'Enrich a company by name, domain, LinkedIn ID, or LinkedIn slug with detailed firmographic data',
version: '1.0.0',
hosting: wizaHosting<WizaCompanyEnrichmentParams>((_params, output) => {
// 2 API credits per successful company match; no charge on a no-match.
return output.company_name || output.company_domain || output.domain ? 2 : 0
}),
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Wiza API key',
},
company_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name (e.g., "Wiza")',
},
company_domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company domain (e.g., "wiza.co")',
},
company_linkedin_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company LinkedIn ID',
},
company_linkedin_slug: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company LinkedIn slug from the URL',
},
},
request: {
url: 'https://wiza.co/api/company_enrichments',
method: 'POST',
headers: (params: WizaCompanyEnrichmentParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params: WizaCompanyEnrichmentParams) => {
const body: Record<string, unknown> = {}
if (params.company_name) body.company_name = params.company_name
if (params.company_domain) body.company_domain = params.company_domain
if (params.company_linkedin_id) body.company_linkedin_id = params.company_linkedin_id
if (params.company_linkedin_slug) body.company_linkedin_slug = params.company_linkedin_slug
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Wiza API error: ${response.status} - ${errorText}`)
}
const json = await response.json()
const d = json.data ?? {}
return {
success: true,
output: {
company_name: d.company_name ?? null,
company_domain: d.company_domain ?? null,
domain: d.domain ?? null,
company_industry: d.company_industry ?? null,
company_size: d.company_size ?? null,
company_size_range: d.company_size_range ?? null,
company_founded: d.company_founded ?? null,
company_revenue_range: d.company_revenue_range ?? null,
company_funding: d.company_funding ?? null,
company_type: d.company_type ?? null,
company_description: d.company_description ?? null,
company_ticker: d.company_ticker ?? null,
company_last_funding_round: d.company_last_funding_round ?? null,
company_last_funding_amount: d.company_last_funding_amount ?? null,
company_last_funding_at: d.company_last_funding_at ?? null,
company_location: d.company_location ?? null,
company_twitter: d.company_twitter ?? null,
company_facebook: d.company_facebook ?? null,
company_linkedin: d.company_linkedin ?? null,
company_linkedin_id: d.company_linkedin_id ?? null,
company_street: d.company_street ?? null,
company_locality: d.company_locality ?? null,
company_region: d.company_region ?? null,
company_postal_code: d.company_postal_code ?? null,
company_country: d.company_country ?? null,
credits: d.credits ?? null,
},
}
},
outputs: {
company_name: { type: 'string', description: 'Company name', optional: true },
company_domain: { type: 'string', description: 'Company domain', optional: true },
domain: { type: 'string', description: 'Domain', optional: true },
company_industry: { type: 'string', description: 'Industry', optional: true },
company_size: { type: 'number', description: 'Employee count', optional: true },
company_size_range: { type: 'string', description: 'Headcount range', optional: true },
company_founded: { type: 'number', description: 'Year founded', optional: true },
company_revenue_range: { type: 'string', description: 'Revenue range', optional: true },
company_funding: { type: 'string', description: 'Total funding', optional: true },
company_type: { type: 'string', description: 'Company type', optional: true },
company_description: { type: 'string', description: 'Description', optional: true },
company_ticker: { type: 'string', description: 'Stock ticker', optional: true },
company_last_funding_round: {
type: 'string',
description: 'Last funding round',
optional: true,
},
company_last_funding_amount: {
type: 'string',
description: 'Last funding amount',
optional: true,
},
company_last_funding_at: { type: 'string', description: 'Last funding date', optional: true },
company_location: { type: 'string', description: 'Full location string', optional: true },
company_twitter: { type: 'string', description: 'Twitter URL', optional: true },
company_facebook: { type: 'string', description: 'Facebook URL', optional: true },
company_linkedin: { type: 'string', description: 'LinkedIn URL', optional: true },
company_linkedin_id: { type: 'string', description: 'LinkedIn ID', optional: true },
company_street: { type: 'string', description: 'Street address', optional: true },
company_locality: { type: 'string', description: 'City', optional: true },
company_region: { type: 'string', description: 'State/region', optional: true },
company_postal_code: { type: 'string', description: 'Postal code', optional: true },
company_country: { type: 'string', description: 'Country', optional: true },
credits: {
type: 'json',
description: 'Credits deducted for this enrichment (api_credits: { total, company_credits })',
optional: true,
},
},
}
+62
View File
@@ -0,0 +1,62 @@
import type { ToolConfig } from '@/tools/types'
import type { WizaGetCreditsParams, WizaGetCreditsResponse } from '@/tools/wiza/types'
export const wizaGetCreditsTool: ToolConfig<WizaGetCreditsParams, WizaGetCreditsResponse> = {
id: 'wiza_get_credits',
name: 'Wiza Get Credits',
description: 'Retrieve the remaining credits on your Wiza account',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Wiza API key',
},
},
request: {
url: 'https://wiza.co/api/meta/credits',
method: 'GET',
headers: (params: WizaGetCreditsParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Wiza API error: ${response.status} - ${errorText}`)
}
const data = await response.json()
const credits = data.credits ?? {}
return {
success: true,
output: {
email_credits: credits.email_credits ?? null,
phone_credits: credits.phone_credits ?? null,
export_credits: credits.export_credits ?? null,
api_credits: credits.api_credits ?? null,
},
}
},
outputs: {
email_credits: {
type: 'json',
description: 'Remaining email credits (number or "unlimited")',
optional: true,
},
phone_credits: {
type: 'json',
description: 'Remaining phone credits (number or "unlimited")',
optional: true,
},
export_credits: { type: 'number', description: 'Remaining export credits', optional: true },
api_credits: { type: 'number', description: 'Remaining API credits', optional: true },
},
}
+42
View File
@@ -0,0 +1,42 @@
import type { ToolHostingConfig } from '@/tools/types'
/**
* Env var prefix for Wiza hosted keys. Provide keys as `WIZA_API_KEY_COUNT`
* plus `WIZA_API_KEY_1..N`.
*/
export const WIZA_API_KEY_PREFIX = 'WIZA_API_KEY'
/**
* Dollar cost of a single Wiza API credit.
*
* Wiza meters API usage in credits at a documented $0.025/credit (2,000-credit
* minimum) — https://help.wiza.co/en/articles/13551713-how-to-purchase-api-credits.
* Credits are deducted only when data is successfully returned: 2 credits per
* valid email, 5 credits per phone, 2 credits per company enrichment.
*/
export const WIZA_CREDIT_USD = 0.025
/**
* Build a Wiza `hosting` config. `getCredits` returns the number of Wiza API
* credits the call consumed, derived from the tool's output.
*/
export function wizaHosting<P>(
getCredits: (params: P, output: Record<string, unknown>) => number
): ToolHostingConfig<P> {
return {
envKeyPrefix: WIZA_API_KEY_PREFIX,
apiKeyParam: 'apiKey',
byokProviderId: 'wiza',
pricing: {
type: 'custom',
getCost: (params, output) => {
const credits = getCredits(params, output)
return { cost: credits * WIZA_CREDIT_USD, metadata: { credits } }
},
},
rateLimit: {
mode: 'per_request',
requestsPerMinute: 60,
},
}
}
+5
View File
@@ -0,0 +1,5 @@
export { wizaCompanyEnrichmentTool } from './company_enrichment'
export { wizaGetCreditsTool } from './get_credits'
export { wizaIndividualRevealTool } from './individual_reveal'
export { wizaProspectSearchTool } from './prospect_search'
export type * from './types'
+330
View File
@@ -0,0 +1,330 @@
import { sleep } from '@sim/utils/helpers'
import type { ToolConfig } from '@/tools/types'
import { wizaHosting } from '@/tools/wiza/hosting'
import type {
WizaIndividualRevealData,
WizaIndividualRevealParams,
WizaIndividualRevealResponse,
} from '@/tools/wiza/types'
const POLL_INTERVAL_MS = 2000
const MAX_POLL_TIME_MS = 120000
/** Tolerate brief Wiza outages while polling before giving up on an already-started reveal. */
const MAX_CONSECUTIVE_POLL_ERRORS = 3
/** Whether a reveal payload has reached a terminal state and no longer needs polling. */
function isTerminalReveal(d: { status?: string | null; is_complete?: boolean | null }): boolean {
return d.status === 'finished' || d.status === 'failed' || d.is_complete === true
}
/** Map a Wiza individual-reveal payload (`data` object) to the tool output shape. */
function mapRevealData(d: Record<string, unknown>): WizaIndividualRevealData {
const emails = Array.isArray(d.emails) ? (d.emails as Record<string, unknown>[]) : []
const phones = Array.isArray(d.phones) ? (d.phones as Record<string, unknown>[]) : []
return {
id: (d.id as number) ?? null,
status: (d.status as string) ?? null,
is_complete: (d.is_complete as boolean) ?? null,
name: (d.name as string) ?? null,
company: (d.company as string) ?? null,
enrichment_level: (d.enrichment_level as string) ?? null,
linkedin_profile_url: (d.linkedin_profile_url as string) ?? null,
title: (d.title as string) ?? null,
location: (d.location as string) ?? null,
email: (d.email as string) ?? null,
email_type: (d.email_type as string) ?? null,
email_status: (d.email_status as string) ?? null,
emails: emails.map((e) => ({
email: (e.email as string) ?? null,
email_type: (e.email_type as string) ?? null,
email_status: (e.email_status as string) ?? null,
})),
mobile_phone: (d.mobile_phone as string) ?? null,
phone_number: (d.phone_number as string) ?? null,
phone_status: (d.phone_status as string) ?? null,
phones: phones.map((p) => ({
number: (p.number as string) ?? null,
pretty_number: (p.pretty_number as string) ?? null,
type: (p.type as string) ?? null,
})),
company_size: (d.company_size as number) ?? null,
company_size_range: (d.company_size_range as string) ?? null,
company_type: (d.company_type as string) ?? null,
company_domain: (d.company_domain as string) ?? null,
company_locality: (d.company_locality as string) ?? null,
company_region: (d.company_region as string) ?? null,
company_country: (d.company_country as string) ?? null,
company_street: (d.company_street as string) ?? null,
company_postal_code: (d.company_postal_code as string) ?? null,
company_founded: (d.company_founded as number) ?? null,
company_funding: (d.company_funding as string) ?? null,
company_revenue: (d.company_revenue as string) ?? null,
company_industry: (d.company_industry as string) ?? null,
company_subindustry: (d.company_subindustry as string) ?? null,
company_linkedin: (d.company_linkedin as string) ?? null,
company_location: (d.company_location as string) ?? null,
company_description: (d.company_description as string) ?? null,
credits: (d.credits as Record<string, unknown>) ?? null,
}
}
export const wizaIndividualRevealTool: ToolConfig<
WizaIndividualRevealParams,
WizaIndividualRevealResponse
> = {
id: 'wiza_individual_reveal',
name: 'Wiza Individual Reveal',
description:
'Reveal a contact via LinkedIn URL, name + company/domain, or email. Starts the reveal and polls until it resolves. Uses 2 credits per valid email and 5 credits per phone, charged only on success.',
version: '1.0.0',
hosting: wizaHosting<WizaIndividualRevealParams>((_params, output) => {
let credits = 0
const emails = Array.isArray(output.emails)
? (output.emails as { email_status?: string }[])
: []
const emailValid =
output.email_status === 'valid' || emails.some((e) => e.email_status === 'valid')
// 2 credits when at least one valid email is returned.
if (emailValid) credits += 2
const phones = Array.isArray(output.phones) ? output.phones : []
const phoneFound = Boolean(output.mobile_phone || output.phone_number || phones.length > 0)
// 5 credits when at least one phone is returned.
if (phoneFound) credits += 5
return credits
}),
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Wiza API key',
},
enrichment_level: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Enrichment depth: none, partial, phone, or full',
},
profile_url: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'LinkedIn profile URL (e.g., https://linkedin.com/in/johndoe)',
},
full_name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Full name (used with company or domain)',
},
company: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company name (used with full_name)',
},
domain: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Company domain (used with full_name)',
},
email: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Email address (use alone or with other identifiers)',
},
accept_work: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to accept work emails (email_options)',
},
accept_personal: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to accept personal emails (email_options)',
},
},
request: {
url: 'https://wiza.co/api/individual_reveals',
method: 'POST',
headers: (params: WizaIndividualRevealParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params: WizaIndividualRevealParams) => {
const individual: Record<string, unknown> = {}
if (params.profile_url) individual.profile_url = params.profile_url
if (params.full_name) individual.full_name = params.full_name
if (params.company) individual.company = params.company
if (params.domain) individual.domain = params.domain
if (params.email) individual.email = params.email
const body: Record<string, unknown> = {
individual_reveal: individual,
enrichment_level: params.enrichment_level,
}
if (params.accept_work !== undefined || params.accept_personal !== undefined) {
const emailOptions: Record<string, unknown> = {}
if (params.accept_work !== undefined) emailOptions.accept_work = params.accept_work
if (params.accept_personal !== undefined) {
emailOptions.accept_personal = params.accept_personal
}
body.email_options = emailOptions
}
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Wiza API error: ${response.status} - ${errorText}`)
}
const json = await response.json()
return {
success: true,
output: mapRevealData(json.data ?? {}),
}
},
postProcess: async (result, params) => {
if (!result.success) return result
// Wiza can resolve synchronously (e.g. a cache hit) — the initial POST payload is
// already mapped, so skip polling when it is terminal.
if (isTerminalReveal(result.output)) {
return { success: result.output.status !== 'failed', output: result.output }
}
const revealId = result.output.id
if (revealId == null) {
// Return an explicit failure rather than throwing: a thrown error here is swallowed
// by the executor and masked as the queued (incomplete) success result.
return {
success: false,
error: 'Wiza individual reveal did not return an id',
output: result.output,
}
}
let elapsedTime = 0
let consecutiveErrors = 0
while (elapsedTime < MAX_POLL_TIME_MS) {
await sleep(POLL_INTERVAL_MS)
elapsedTime += POLL_INTERVAL_MS
const statusResponse = await fetch(
`https://wiza.co/api/individual_reveals/${encodeURIComponent(String(revealId))}`,
{
headers: {
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
},
}
)
if (!statusResponse.ok) {
// The reveal is already started (and billed by Wiza), so tolerate brief outages and
// retry rather than aborting the whole window on a single transient 5xx/429.
consecutiveErrors += 1
if (consecutiveErrors >= MAX_CONSECUTIVE_POLL_ERRORS) {
const errorText = await statusResponse.text().catch(() => '')
return {
success: false,
error: `Wiza API error: ${statusResponse.status} - ${errorText}`,
output: result.output,
}
}
continue
}
consecutiveErrors = 0
const json = await statusResponse.json()
const data = json.data ?? {}
if (isTerminalReveal(data)) {
return {
success: data.status !== 'failed',
output: mapRevealData(data),
}
}
}
return {
success: false,
error: 'Wiza individual reveal did not complete within the polling window',
output: result.output,
}
},
outputs: {
id: { type: 'number', description: 'Reveal ID' },
status: { type: 'string', description: 'queued | resolving | finished | failed' },
is_complete: { type: 'boolean', description: 'Whether the reveal has completed' },
name: { type: 'string', description: 'Full name', optional: true },
company: { type: 'string', description: 'Company name', optional: true },
enrichment_level: { type: 'string', description: 'Enrichment level used', optional: true },
linkedin_profile_url: { type: 'string', description: 'LinkedIn URL', optional: true },
title: { type: 'string', description: 'Job title', optional: true },
location: { type: 'string', description: 'Location', optional: true },
email: { type: 'string', description: 'Primary email', optional: true },
email_type: { type: 'string', description: 'Email type', optional: true },
email_status: { type: 'string', description: 'valid | risky | unfound', optional: true },
emails: {
type: 'array',
description: 'All emails found',
optional: true,
items: {
type: 'object',
properties: {
email: { type: 'string' },
email_type: { type: 'string' },
email_status: { type: 'string' },
},
},
},
mobile_phone: { type: 'string', description: 'Mobile phone', optional: true },
phone_number: { type: 'string', description: 'Direct/office phone', optional: true },
phone_status: { type: 'string', description: 'found | unfound', optional: true },
phones: {
type: 'array',
description: 'All phones found',
optional: true,
items: {
type: 'object',
properties: {
number: { type: 'string' },
pretty_number: { type: 'string' },
type: { type: 'string' },
},
},
},
company_size: { type: 'number', description: 'Employee count', optional: true },
company_size_range: { type: 'string', description: 'Headcount range', optional: true },
company_type: { type: 'string', description: 'Company type', optional: true },
company_domain: { type: 'string', description: 'Company domain', optional: true },
company_locality: { type: 'string', description: 'City', optional: true },
company_region: { type: 'string', description: 'State/region', optional: true },
company_country: { type: 'string', description: 'Country', optional: true },
company_street: { type: 'string', description: 'Street', optional: true },
company_postal_code: { type: 'string', description: 'Postal code', optional: true },
company_founded: { type: 'number', description: 'Year founded', optional: true },
company_funding: { type: 'string', description: 'Funding total', optional: true },
company_revenue: { type: 'string', description: 'Revenue', optional: true },
company_industry: { type: 'string', description: 'Industry', optional: true },
company_subindustry: { type: 'string', description: 'Subindustry', optional: true },
company_linkedin: { type: 'string', description: 'Company LinkedIn URL', optional: true },
company_location: { type: 'string', description: 'Full company location', optional: true },
company_description: { type: 'string', description: 'Company description', optional: true },
credits: { type: 'json', description: 'Credits consumed by the reveal', optional: true },
},
}
+253
View File
@@ -0,0 +1,253 @@
import type { ToolConfig } from '@/tools/types'
import { wizaHosting } from '@/tools/wiza/hosting'
import type { WizaProspectSearchParams, WizaProspectSearchResponse } from '@/tools/wiza/types'
export const wizaProspectSearchTool: ToolConfig<
WizaProspectSearchParams,
WizaProspectSearchResponse
> = {
id: 'wiza_prospect_search',
name: 'Wiza Prospect Search',
description: "Search Wiza's database of prospects using person, company, and financial filters",
version: '1.0.0',
hosting: wizaHosting<WizaProspectSearchParams>(() => {
// Prospect search returns profiles without contact data and consumes no credits;
// Wiza charges only on reveal/enrichment.
return 0
}),
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Wiza API key',
},
size: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of sample profiles to return (0-30, default 0)',
},
filters: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description: 'Full filters object (overrides individual filter params if provided)',
},
first_name: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Exact first names to match (e.g., ["John", "Jane"])',
},
last_name: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Exact last names to match',
},
job_title: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description:
'Job titles to include/exclude (e.g., [{"v":"CEO","s":"i"},{"v":"CTO","s":"e"}])',
},
job_title_level: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Seniority levels (e.g., ["cxo", "director", "manager"])',
},
job_role: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Job role categories (e.g., ["sales", "engineering", "marketing"])',
},
job_sub_role: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Detailed role categories (e.g., ["software", "product"])',
},
location: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: "Person's location filters (city/state/country with include/exclude)",
},
skill: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Professional skills (e.g., ["python", "marketing"])',
},
school: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Educational institutions',
},
major: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Field of study',
},
linkedin_slug: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'LinkedIn profile slugs',
},
job_company: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Current company filters (include/exclude)',
},
past_company: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Past company filters',
},
company_location: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Company HQ location filters',
},
company_industry: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Company industry filters (include/exclude)',
},
company_size: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Company headcount brackets (e.g., ["1-10", "11-50", "51-200"])',
},
company_type: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Company type (e.g., ["private", "public", "educational"])',
},
},
request: {
url: 'https://wiza.co/api/prospects/search',
method: 'POST',
headers: (params: WizaProspectSearchParams) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params: WizaProspectSearchParams) => {
const body: Record<string, unknown> = {}
if (typeof params.size === 'number') {
body.size = Math.max(0, Math.min(params.size, 30))
}
if (
params.filters &&
typeof params.filters === 'object' &&
!Array.isArray(params.filters) &&
Object.keys(params.filters).length > 0
) {
body.filters = params.filters
return body
}
const filters: Record<string, unknown> = {}
const arrayKeys: Array<keyof WizaProspectSearchParams> = [
'first_name',
'last_name',
'job_title',
'job_title_level',
'job_role',
'job_sub_role',
'location',
'skill',
'school',
'major',
'linkedin_slug',
'job_company',
'past_company',
'company_location',
'company_industry',
'company_size',
'company_type',
]
for (const key of arrayKeys) {
const value = params[key]
if (Array.isArray(value) && value.length > 0) {
filters[key as string] = value
}
}
if (Object.keys(filters).length > 0) {
body.filters = filters
}
return body
},
},
transformResponse: async (response: Response) => {
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Wiza API error: ${response.status} - ${errorText}`)
}
const data = await response.json()
const payload = data.data ?? {}
const profiles = Array.isArray(payload.profiles) ? payload.profiles : []
return {
success: true,
output: {
total: payload.total ?? 0,
profiles: profiles.map((p: Record<string, unknown>) => ({
full_name: (p.full_name as string) ?? null,
linkedin_url: (p.linkedin_url as string) ?? null,
industry: (p.industry as string) ?? null,
job_title: (p.job_title as string) ?? null,
job_title_role: (p.job_title_role as string) ?? null,
job_title_sub_role: (p.job_title_sub_role as string) ?? null,
job_company_name: (p.job_company_name as string) ?? null,
job_company_website: (p.job_company_website as string) ?? null,
location_name: (p.location_name as string) ?? null,
})),
},
}
},
outputs: {
total: { type: 'number', description: 'Total number of matching prospects' },
profiles: {
type: 'array',
description: 'Sample profiles matching the filter criteria',
items: {
type: 'object',
properties: {
full_name: { type: 'string' },
linkedin_url: { type: 'string' },
industry: { type: 'string' },
job_title: { type: 'string' },
job_title_role: { type: 'string' },
job_title_sub_role: { type: 'string' },
job_company_name: { type: 'string' },
job_company_website: { type: 'string' },
location_name: { type: 'string' },
},
},
},
},
}
+174
View File
@@ -0,0 +1,174 @@
import type { ToolResponse } from '@/tools/types'
export interface WizaGetCreditsParams {
apiKey: string
}
export interface WizaGetCreditsResponse extends ToolResponse {
output: {
email_credits: number | string | null
phone_credits: number | string | null
export_credits: number | null
api_credits: number | null
}
}
export interface WizaIncludeExcludeFilter {
v: string
s: 'i' | 'e'
}
export interface WizaLocationFilter {
v: string | { country?: string; state?: string; city?: string }
b: 'country' | 'state' | 'city'
s: 'i' | 'e'
}
export interface WizaProspectSearchParams {
apiKey: string
size?: number
filters?: Record<string, unknown>
first_name?: string[]
last_name?: string[]
job_title?: WizaIncludeExcludeFilter[]
job_title_level?: string[]
job_role?: string[]
job_sub_role?: string[]
location?: WizaLocationFilter[]
skill?: string[]
school?: string[]
major?: string[]
linkedin_slug?: string[]
job_company?: WizaIncludeExcludeFilter[]
past_company?: WizaIncludeExcludeFilter[]
company_location?: WizaLocationFilter[]
company_industry?: WizaIncludeExcludeFilter[]
company_size?: string[]
company_type?: string[]
}
interface WizaProspectProfile {
full_name: string | null
linkedin_url: string | null
industry: string | null
job_title: string | null
job_title_role: string | null
job_title_sub_role: string | null
job_company_name: string | null
job_company_website: string | null
location_name: string | null
}
export interface WizaProspectSearchResponse extends ToolResponse {
output: {
total: number
profiles: WizaProspectProfile[]
}
}
export interface WizaCompanyEnrichmentParams {
apiKey: string
company_name?: string
company_domain?: string
company_linkedin_id?: string
company_linkedin_slug?: string
}
export interface WizaCompanyEnrichmentResponse extends ToolResponse {
output: {
company_name: string | null
company_domain: string | null
domain: string | null
company_industry: string | null
company_size: number | null
company_size_range: string | null
company_founded: number | null
company_revenue_range: string | null
company_funding: string | null
company_type: string | null
company_description: string | null
company_ticker: string | null
company_last_funding_round: string | null
company_last_funding_amount: string | null
company_last_funding_at: string | null
company_location: string | null
company_twitter: string | null
company_facebook: string | null
company_linkedin: string | null
company_linkedin_id: string | null
company_street: string | null
company_locality: string | null
company_region: string | null
company_postal_code: string | null
company_country: string | null
credits: Record<string, unknown> | null
}
}
export interface WizaIndividualRevealParams {
apiKey: string
enrichment_level: 'none' | 'partial' | 'phone' | 'full'
profile_url?: string
full_name?: string
company?: string
domain?: string
email?: string
accept_work?: boolean
accept_personal?: boolean
}
export interface WizaIndividualRevealData {
id: number | null
status: string | null
is_complete: boolean | null
name: string | null
company: string | null
enrichment_level: string | null
linkedin_profile_url: string | null
title: string | null
location: string | null
email: string | null
email_type: string | null
email_status: string | null
emails: Array<{
email: string | null
email_type: string | null
email_status: string | null
}>
mobile_phone: string | null
phone_number: string | null
phone_status: string | null
phones: Array<{
number: string | null
pretty_number: string | null
type: string | null
}>
company_size: number | null
company_size_range: string | null
company_type: string | null
company_domain: string | null
company_locality: string | null
company_region: string | null
company_country: string | null
company_street: string | null
company_postal_code: string | null
company_founded: number | null
company_funding: string | null
company_revenue: string | null
company_industry: string | null
company_subindustry: string | null
company_linkedin: string | null
company_location: string | null
company_description: string | null
credits: Record<string, unknown> | null
}
export interface WizaIndividualRevealResponse extends ToolResponse {
output: WizaIndividualRevealData
}
export type WizaResponse =
| WizaGetCreditsResponse
| WizaProspectSearchResponse
| WizaCompanyEnrichmentResponse
| WizaIndividualRevealResponse