@maestrogtm/maestro-gtm 0.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-RNHSWSNV.js +158 -0
- package/dist/ai-RNHSWSNV.js.map +1 -0
- package/dist/app-PSZH2J56.js +54 -0
- package/dist/app-PSZH2J56.js.map +1 -0
- package/dist/batch-ZCHN54YJ.js +28 -0
- package/dist/batch-ZCHN54YJ.js.map +1 -0
- package/dist/campaign-XDXQA7KX.js +119 -0
- package/dist/campaign-XDXQA7KX.js.map +1 -0
- package/dist/chunk-365Q36GF.js +54 -0
- package/dist/chunk-365Q36GF.js.map +1 -0
- package/dist/chunk-4IV6QS4U.js +122 -0
- package/dist/chunk-4IV6QS4U.js.map +1 -0
- package/dist/chunk-6GLLK5KO.js +64 -0
- package/dist/chunk-6GLLK5KO.js.map +1 -0
- package/dist/chunk-6UNBW5SN.js +686 -0
- package/dist/chunk-6UNBW5SN.js.map +1 -0
- package/dist/chunk-A7JD6EYV.js +92 -0
- package/dist/chunk-A7JD6EYV.js.map +1 -0
- package/dist/chunk-ARNVJPFM.js +139 -0
- package/dist/chunk-ARNVJPFM.js.map +1 -0
- package/dist/chunk-AX6BOEF2.js +345 -0
- package/dist/chunk-AX6BOEF2.js.map +1 -0
- package/dist/chunk-C3T7QPSO.js +507 -0
- package/dist/chunk-C3T7QPSO.js.map +1 -0
- package/dist/chunk-FG43GILY.js +46 -0
- package/dist/chunk-FG43GILY.js.map +1 -0
- package/dist/chunk-FS6DCNCA.js +139 -0
- package/dist/chunk-FS6DCNCA.js.map +1 -0
- package/dist/chunk-I6GRD4X7.js +1144 -0
- package/dist/chunk-I6GRD4X7.js.map +1 -0
- package/dist/chunk-IP34URKR.js +621 -0
- package/dist/chunk-IP34URKR.js.map +1 -0
- package/dist/chunk-JFSKOY7Z.js +252 -0
- package/dist/chunk-JFSKOY7Z.js.map +1 -0
- package/dist/chunk-M25KLO7T.js +3272 -0
- package/dist/chunk-M25KLO7T.js.map +1 -0
- package/dist/chunk-M3G2WREL.js +57 -0
- package/dist/chunk-M3G2WREL.js.map +1 -0
- package/dist/chunk-MFFACSBE.js +4266 -0
- package/dist/chunk-MFFACSBE.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-QZH3XFOQ.js +2636 -0
- package/dist/chunk-QZH3XFOQ.js.map +1 -0
- package/dist/chunk-SPWDMOEU.js +1940 -0
- package/dist/chunk-SPWDMOEU.js.map +1 -0
- package/dist/chunk-TP3BZDVV.js +28 -0
- package/dist/chunk-TP3BZDVV.js.map +1 -0
- package/dist/chunk-UBJUBYSQ.js +18 -0
- package/dist/chunk-UBJUBYSQ.js.map +1 -0
- package/dist/chunk-VNKXGHWY.js +20 -0
- package/dist/chunk-VNKXGHWY.js.map +1 -0
- package/dist/chunk-WKLCPIFB.js +9862 -0
- package/dist/chunk-WKLCPIFB.js.map +1 -0
- package/dist/chunk-YV5XOXRQ.js +7 -0
- package/dist/chunk-YV5XOXRQ.js.map +1 -0
- package/dist/cli-Z3BNNJYQ.js +852 -0
- package/dist/cli-Z3BNNJYQ.js.map +1 -0
- package/dist/client-Y34LNEWN.js +8 -0
- package/dist/client-Y34LNEWN.js.map +1 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/configure-XSENK4X5.js +64 -0
- package/dist/configure-XSENK4X5.js.map +1 -0
- package/dist/context.js +10 -0
- package/dist/context.js.map +1 -0
- package/dist/crm-QBNHVBYV.js +86 -0
- package/dist/crm-QBNHVBYV.js.map +1 -0
- package/dist/dfy-X3OXIYRA.js +356 -0
- package/dist/dfy-X3OXIYRA.js.map +1 -0
- package/dist/dist-LGCJKGBS.js +121 -0
- package/dist/dist-LGCJKGBS.js.map +1 -0
- package/dist/engagement-C4U7LPJH.js +463 -0
- package/dist/engagement-C4U7LPJH.js.map +1 -0
- package/dist/enrich-F5GPVZFE.js +226 -0
- package/dist/enrich-F5GPVZFE.js.map +1 -0
- package/dist/extract-DS5N6SSJ.js +155 -0
- package/dist/extract-DS5N6SSJ.js.map +1 -0
- package/dist/feedback-AIXKXNM5.js +51 -0
- package/dist/feedback-AIXKXNM5.js.map +1 -0
- package/dist/fetch-QJDSPI63.js +87 -0
- package/dist/fetch-QJDSPI63.js.map +1 -0
- package/dist/handlers.js +13 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/list-HL7NQQJX.js +236 -0
- package/dist/list-HL7NQQJX.js.map +1 -0
- package/dist/maestro-N7Q2JX22.js +903 -0
- package/dist/maestro-N7Q2JX22.js.map +1 -0
- package/dist/prospect-RUOT43H6.js +532 -0
- package/dist/prospect-RUOT43H6.js.map +1 -0
- package/dist/providers/factory.js +10 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/registry.js +8 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/provision-FT5NWN77.js +394 -0
- package/dist/provision-FT5NWN77.js.map +1 -0
- package/dist/recipe-JU3SXMZF.js +137 -0
- package/dist/recipe-JU3SXMZF.js.map +1 -0
- package/dist/review-5SB6DYDZ.js +70 -0
- package/dist/review-5SB6DYDZ.js.map +1 -0
- package/dist/sdk-LVBHNQ6T.js +3852 -0
- package/dist/sdk-LVBHNQ6T.js.map +1 -0
- package/dist/server-REKYQZ2E.js +22 -0
- package/dist/server-REKYQZ2E.js.map +1 -0
- package/dist/status-V3EEFS7S.js +114 -0
- package/dist/status-V3EEFS7S.js.map +1 -0
- package/dist/tam-J6NDBP5W.js +682 -0
- package/dist/tam-J6NDBP5W.js.map +1 -0
- package/dist/tools.js +80 -0
- package/dist/tools.js.map +1 -0
- package/dist/validation.js +12 -0
- package/dist/validation.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/adapters/bettercontact.ts","../src/providers/adapters/blitz.ts","../src/providers/adapters/disco.ts","../src/providers/adapters/prospeo.ts","../src/providers/adapters/plusvibe.ts","../src/providers/adapters/heyreach.ts","../src/providers/adapters/attio.ts","../src/providers/adapters/apollo.ts","../src/providers/adapters/instantly.ts","../src/providers/adapters/smartlead.ts","../src/providers/adapters/storeleads.ts","../src/providers/adapters/harvest.ts","../src/providers/adapters/exa.ts","../src/providers/adapters/leadmagic.ts","../src/providers/adapters/twenty.ts","../src/providers/adapters/hunter.ts","../src/providers/adapters/zerobounce.ts","../src/providers/adapters/bounceban.ts","../src/providers/adapters/mailin.ts","../src/providers/adapters/apify.ts","../src/providers/factory.ts"],"sourcesContent":["/** BetterContact adapter. Bridges BetterContactClient to MCP Provider interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * Verified: curl 2026-03-15 — status \"in progress\" (with space), credits_left is string. */\n\nimport { logError } from '@maestro/logging';\nimport { BetterContactClient } from '@maestro/integrations';\n\nimport type { BetterContactEnrichStatusResponse } from '@maestro/integrations';\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CreditBalance,\n EmailEnricher,\n PhoneEnricher,\n EmailVerifier,\n PeopleFinder,\n ContactInput,\n EnrichEmailResult,\n EnrichPhoneResult,\n VerificationResult,\n PeopleQuery,\n PersonResult,\n} from '../types.js';\n\n// ─── Constants ───────────────────────────────────────────\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // 60 * 2s = 120s max wait (enrichment takes ~2min)\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class BetterContactAdapter\n implements Provider, EmailEnricher, PhoneEnricher, EmailVerifier, PeopleFinder\n{\n readonly name = 'bettercontact';\n readonly capabilities: Capability[] = [\n 'enrich_email',\n 'enrich_phone',\n 'verify_email',\n 'find_people',\n ];\n readonly notes = 'Best for: email + phone waterfall. Charges only on successful find.';\n private readonly client: BetterContactClient;\n\n constructor(apiKey: string) {\n this.client = new BetterContactClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.getAccount();\n return true;\n } catch (error) {\n logError(\n 'bettercontact:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n try {\n const account = await this.client.getAccount();\n return {\n remaining: parseFloat(String(account.credits_left)),\n unit: 'credits',\n provider: this.name,\n };\n } catch (error) {\n logError(\n 'bettercontact:checkCredits',\n error instanceof Error ? error : new Error(String(error))\n );\n return null;\n }\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n const createResponse = await this.client.enrich({\n data: [\n {\n first_name: contact.first_name,\n last_name: contact.last_name,\n company: contact.company,\n company_domain: contact.company_domain,\n linkedin_url: contact.linkedin_url,\n },\n ],\n enrich_email_address: true,\n enrich_phone_number: false,\n });\n\n const result = await this.pollEnrichment(createResponse.id);\n const enriched = result.data?.[0];\n if (!enriched?.contact_email_address) return null;\n\n return {\n email: enriched.contact_email_address,\n quality: enriched.contact_email_address_status,\n provider: this.name,\n };\n }\n\n // ─── PhoneEnricher ──────────────────────────────────────\n\n async enrichPhone(contact: ContactInput): Promise<EnrichPhoneResult | null> {\n const createResponse = await this.client.enrich({\n data: [\n {\n first_name: contact.first_name,\n last_name: contact.last_name,\n company: contact.company,\n company_domain: contact.company_domain,\n linkedin_url: contact.linkedin_url,\n },\n ],\n enrich_email_address: false,\n enrich_phone_number: true,\n });\n\n const result = await this.pollEnrichment(createResponse.id);\n const enriched = result.data?.[0];\n if (!enriched?.contact_phone_number) return null;\n\n return {\n phone: enriched.contact_phone_number,\n provider: this.name,\n };\n }\n\n // ─── EmailVerifier ──────────────────────────────────────\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n const createResponse = await this.client.enrich({\n data: [{ first_name: '', last_name: '', company_domain: email.split('@')[1] }],\n enrich_email_address: true,\n enrich_phone_number: false,\n });\n\n const result = await this.pollEnrichment(createResponse.id);\n const enriched = result.data?.[0];\n const status = enriched?.contact_email_address_status ?? 'unknown';\n const statusMap: Record<string, VerificationResult['status']> = {\n deliverable: 'deliverable',\n catch_all_safe: 'catch_all_safe',\n catch_all_not_safe: 'catch_all_not_safe',\n undeliverable: 'undeliverable',\n };\n\n return {\n email,\n valid: status === 'deliverable',\n status: statusMap[status] ?? 'unknown',\n provider: this.name,\n };\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n const companyTerms = [query.company_domain, query.company_name].filter(Boolean) as string[];\n\n const createResponse = await this.client.findPeople({\n filters: {\n ...(companyTerms.length > 0 && { company: { include: companyTerms } }),\n ...(query.job_title && {\n lead_job_title: { include: query.job_titles ?? [query.job_title] },\n }),\n ...(query.location && { lead_location: { include: [query.location] } }),\n },\n max_leads: query.limit,\n });\n\n let result = await this.client.getLeadFinderStatus(createResponse.request_id);\n let attempts = 0;\n while (!isTerminalStatus(result.status) && attempts < MAX_POLL_ATTEMPTS) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));\n result = await this.client.getLeadFinderStatus(createResponse.request_id);\n attempts++;\n }\n\n if (!isTerminalStatus(result.status)) {\n throw new Error(\n `BetterContact lead finder timed out after ${(MAX_POLL_ATTEMPTS * POLL_INTERVAL_MS) / 1000}s`\n );\n }\n\n if (result.status === 'failed') {\n throw new Error('BetterContact lead finder request failed');\n }\n\n return (result.leads ?? []).map((lead) => ({\n first_name: lead.contact_first_name ?? '',\n last_name: lead.contact_last_name ?? '',\n job_title: lead.contact_job_title,\n company: lead.company_name,\n linkedin_url: lead.contact_linkedin_profile_url,\n email: lead.contact_email_address,\n phone: lead.contact_phone_number,\n seniority: lead.contact_seniority,\n department: lead.contact_industry,\n }));\n }\n\n // ─── Helpers ────────────────────────────────────────────\n\n private async pollEnrichment(requestId: string): Promise<BetterContactEnrichStatusResponse> {\n let result = await this.client.getEnrichmentStatus(requestId);\n let attempts = 0;\n\n while (!isTerminalStatus(result.status) && attempts < MAX_POLL_ATTEMPTS) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));\n result = await this.client.getEnrichmentStatus(requestId);\n attempts++;\n }\n\n if (!isTerminalStatus(result.status)) {\n throw new Error(\n `BetterContact enrichment timed out after ${(MAX_POLL_ATTEMPTS * POLL_INTERVAL_MS) / 1000}s`\n );\n }\n\n if (result.status === 'failed') {\n throw new Error('BetterContact enrichment request failed');\n }\n\n return result;\n }\n}\n\n// ─── Helpers ────────────────────────────────────────────\n\n/** Check for terminal (done) statuses rather than matching in-progress values.\n * API returns \"in progress\" (with space), not \"processing\". */\nfunction isTerminalStatus(status: string): boolean {\n return status === 'terminated' || status === 'failed';\n}\n","/** BlitzAPI adapter. Bridges BlitzApiClient to MCP Provider interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * Key: Email/phone enrichment requires LinkedIn URL — returns null without one.\n * Flat-rate pricing — should be FIRST in waterfall. */\n\nimport { logError } from '@maestro/logging';\nimport { BlitzApiClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CreditBalance,\n EmailEnricher,\n PhoneEnricher,\n PeopleFinder,\n CompanyFinder,\n ContactInput,\n EnrichEmailResult,\n EnrichPhoneResult,\n PeopleQuery,\n PersonResult,\n CompanyQuery,\n CompanyResult,\n} from '../types.js';\n\n// ─── Seniority Mapping ──────────────────────────────────\n\n/** Map MCP seniority values to Blitz job_level enum.\n * Verified values: C-Team, Director, Manager, Other, Staff, VP */\nconst SENIORITY_TO_BLITZ: Record<string, string> = {\n c_suite: 'C-Team',\n executive: 'C-Team',\n founder: 'C-Team',\n owner: 'C-Team',\n partner: 'C-Team',\n vp: 'VP',\n head: 'VP',\n director: 'Director',\n manager: 'Manager',\n senior_ic: 'Staff',\n senior: 'Staff',\n mid_level: 'Staff',\n entry_level: 'Other',\n entry: 'Other',\n intern: 'Other',\n};\n\nfunction mapJobLevel(\n seniority: string[] | undefined\n): ('C-Team' | 'Director' | 'Manager' | 'Other' | 'Staff' | 'VP')[] | undefined {\n if (!seniority?.length) return undefined;\n const mapped = seniority.map(\n (s) =>\n (SENIORITY_TO_BLITZ[s] ?? s) as 'C-Team' | 'Director' | 'Manager' | 'Other' | 'Staff' | 'VP'\n );\n return [...new Set(mapped)];\n}\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class BlitzApiAdapter\n implements Provider, EmailEnricher, PhoneEnricher, PeopleFinder, CompanyFinder\n{\n readonly name = 'blitz';\n readonly capabilities: Capability[] = [\n 'enrich_email',\n 'enrich_phone',\n 'find_people',\n 'find_companies',\n ];\n readonly notes =\n 'Best for: flat-rate enrichment when LinkedIn URL is available. ' +\n 'Unlimited lookups on paid plans. Requires LinkedIn URL for email/phone. ' +\n 'Should be FIRST in waterfall before credit-based providers.';\n private readonly client: BlitzApiClient;\n\n constructor(apiKey: string) {\n this.client = new BlitzApiClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n const info = await this.client.getKeyInfo();\n return info.valid;\n } catch (error) {\n logError('blitz:checkCredentials', error instanceof Error ? error : new Error(String(error)));\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n try {\n const info = await this.client.getKeyInfo();\n return {\n remaining: info.remaining_credits === 'unlimited' ? Infinity : info.remaining_credits,\n unit: info.remaining_credits === 'unlimited' ? 'unlimited' : 'credits',\n provider: this.name,\n };\n } catch (error) {\n logError('blitz:checkCredits', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n if (!contact.linkedin_url) return null; // Blitz requires LinkedIn URL\n\n try {\n const response = await this.client.findEmail({\n person_linkedin_url: contact.linkedin_url,\n });\n\n if (!response.found || !response.email) return null;\n\n return {\n email: response.email,\n quality: 'verified',\n provider: this.name,\n };\n } catch (error) {\n logError('blitz:enrichEmail', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── PhoneEnricher ──────────────────────────────────────\n\n async enrichPhone(contact: ContactInput): Promise<EnrichPhoneResult | null> {\n if (!contact.linkedin_url) return null; // Blitz requires LinkedIn URL\n\n try {\n const response = await this.client.findPhone({\n person_linkedin_url: contact.linkedin_url,\n });\n\n if (!response.found || !response.phone) return null;\n\n return {\n phone: response.phone,\n provider: this.name,\n };\n } catch (error) {\n logError('blitz:enrichPhone', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n // Blitz employee finder requires company LinkedIn URL\n // If we have a domain, we could resolve it, but for now require LinkedIn URL\n const companyLinkedIn =\n query.company_linkedin_url ??\n (query.company_domain\n ? `https://www.linkedin.com/company/${query.company_domain.replace(/\\.(com|io|co|org|net|ai)$/, '')}`\n : undefined);\n\n if (!companyLinkedIn) return [];\n\n try {\n const response = await this.client.findEmployees({\n company_linkedin_url: companyLinkedIn,\n job_level: mapJobLevel(query.seniority),\n max_results: query.limit ?? 25,\n page: query.offset ? Math.floor(query.offset / (query.limit ?? 25)) + 1 : 1,\n });\n\n return response.results.map((person) => {\n const currentJob = person.experiences?.find((e) => e.job_is_current);\n return {\n first_name: person.first_name ?? '',\n last_name: person.last_name ?? '',\n job_title: currentJob?.job_title ?? person.headline ?? undefined,\n company: undefined, // Blitz doesn't include company name in person results\n linkedin_url: person.linkedin_url,\n seniority: undefined,\n department: undefined,\n location: person.location\n ? [person.location.city, person.location.state_code, person.location.country_code]\n .filter(Boolean)\n .join(', ')\n : undefined,\n };\n });\n } catch (error) {\n logError('blitz:findPeople', error instanceof Error ? error : new Error(String(error)));\n return [];\n }\n }\n\n // ─── CompanyFinder ──────────────────────────────────────\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n try {\n const response = await this.client.searchCompanies({\n company: {\n ...(query.icp_text && { keywords: { include: [query.icp_text] } }),\n ...(query.category && { industry: { include: [query.category] } }),\n ...(query.min_employees != null || query.max_employees != null\n ? {\n employee_count: {\n ...(query.min_employees != null && { min: query.min_employees }),\n ...(query.max_employees != null && { max: query.max_employees }),\n },\n }\n : {}),\n ...(query.country && {\n hq: { country_code: [query.country] },\n }),\n },\n max_results: query.limit ?? 10,\n });\n\n return response.results\n .filter(\n (company): company is typeof company & { domain: string; name: string } =>\n !!company.domain && !!company.name\n )\n .map((company) => ({\n domain: company.domain,\n name: company.name,\n description: company.about ?? undefined,\n industry: company.industry ?? undefined,\n employees: company.employees_on_linkedin ?? undefined,\n country: company.hq?.country_code ?? undefined,\n linkedin_url: company.linkedin_url ?? undefined,\n }));\n } catch (error) {\n logError('blitz:findCompanies', error instanceof Error ? error : new Error(String(error)));\n return [];\n }\n }\n}\n","/** Disco adapter. Bridges DiscoClient to MCP Provider CompanyFinder + PeopleFinder interfaces.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * Note: Disco's /discover tech_stack param is broken (treats values as domains). Use vendors endpoint instead. */\n\nimport { logError } from '@maestro/logging';\nimport { DiscoClient } from '@maestro/integrations';\n\nimport type { DiscoSeniority } from '@maestro/integrations';\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CompanyFinder,\n PeopleFinder,\n CompanyQuery,\n CompanyResult,\n PeopleQuery,\n PersonResult,\n} from '../types.js';\n\n// ─── Valid Categories ──────────────────────────────────────\n\n/** Disco's /discover endpoint accepts only these exact category values. */\nconst VALID_CATEGORIES = new Set([\n 'ACCOUNTING',\n 'ADVERTISING_AND_MARKETING',\n 'AGRICULTURE_AND_NATURAL_RESOURCES',\n 'ALCOHOL_AND_TOBACCO',\n 'AUTOMOTIVE',\n 'BIG_DATA_AND_ANALYTICS',\n 'BIOTECHNOLOGY',\n 'BLOCKCHAIN_AND_CRYPTOCURRENCY',\n 'BUSINESS_PRODUCTS_AND_SERVICES',\n 'CLOUD_COMPUTING',\n 'COMPUTER_HARDWARE_AND_SEMICONDUCTORS',\n 'CONGLOMERATES_SHELL_AND_HOLDING_COMPANIES',\n 'CONSTRUCTION',\n 'CONSUMER_PRODUCTS',\n 'CONSUMER_SERVICES',\n 'CYBERSECURITY',\n 'DEFENSE_AND_AEROSPACE',\n 'E-COMMERCE',\n 'EDUCATION',\n 'ENERGY',\n 'ENGINEERING',\n 'ENTERTAINMENT',\n 'ENVIRONMENTAL_SERVICES',\n 'FASHION_TEXTILE_AND_APPAREL',\n 'FINANCIAL_SERVICES',\n 'FOOD_AND_BEVERAGE',\n 'GAMING_AND_ESPORTS',\n 'GOVERNMENT_SERVICES',\n 'HEALTHCARE',\n 'HOSPITALITY',\n 'HUMAN_RESOURCES',\n 'INSURANCE',\n 'IT_SERVICES',\n 'LEGAL',\n 'MANUFACTURING',\n 'MEDIA',\n 'MINING_AND_METALS',\n 'NONPROFIT_AND_PHILANTHROPY',\n 'OIL_AND_GAS',\n 'PHARMACEUTICALS',\n 'PRIVATE_EQUITY_AND_VENTURE_CAPITAL',\n 'REAL_ESTATE',\n 'RENEWABLE_ENERGY',\n 'RESTAURANTS',\n 'RETAIL',\n 'SAAS',\n 'SECURITY',\n 'SOFTWARE',\n 'SPORTS_AND_RECREATION',\n 'SUPPLY_CHAIN_AND_PROCUREMENT',\n 'TELECOMMUNICATIONS',\n 'TRAVEL',\n 'WELLNESS_AND_LIFESTYLE',\n]);\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class DiscoAdapter implements Provider, CompanyFinder, PeopleFinder {\n readonly name = 'disco';\n readonly capabilities: Capability[] = ['find_companies', 'find_people'];\n readonly notes =\n 'Best for: lookalike discovery, ICP text matching, tech stack filtering, website-content businesses. 60M+ company database from web crawl.';\n private readonly client: DiscoClient;\n\n constructor(apiKey: string) {\n this.client = new DiscoClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n // Disco has no account/health endpoint — use a cheap count query\n await this.client.count({ max_records: 1 });\n return true;\n } catch (error) {\n logError('disco:checkCredentials', error instanceof Error ? error : new Error(String(error)));\n return false;\n }\n }\n\n // ─── CompanyFinder ──────────────────────────────────────\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n // Validate category against Disco's enum — skip invalid values to prevent API errors.\n const category = query.category?.toUpperCase();\n const validCategory = category && VALID_CATEGORIES.has(category) ? category : undefined;\n\n const response = await this.client.discover({\n domain: query.domains ?? query.domain,\n icp_text: query.icp_text,\n max_records: query.limit,\n country: query.country,\n ...((query.min_employees != null || query.max_employees != null) && {\n employee_range: `${query.min_employees ?? ''},${query.max_employees ?? ''}`,\n }),\n // tech_stack is intentionally omitted — Disco's /discover endpoint treats tech_stack\n // values as domains (API bug). Use icp_text for tech-related queries instead.\n category: validCategory,\n negate_domain: query.negate_domains,\n offset: query.offset,\n });\n\n // Guard: API might return non-array (wrapped object) — normalize\n const companies = Array.isArray(response) ? response : [];\n\n const mapped = companies.map((c) => ({\n domain: c.domain,\n name: c.name,\n description: safeString(c.description),\n industry: c.industry_groups ? Object.keys(c.industry_groups)[0] : undefined,\n employees: c.employees ? parseInt(c.employees, 10) || undefined : undefined,\n country: safeString(c.address?.country),\n linkedin_url: safeStringArray(c.social_urls)?.find((u) => u.includes('linkedin')),\n score: c.score,\n tech_stack: undefined, // Discovery doesn't have vendor data; keywords are not tech_stack\n keywords: c.keywords ? Object.keys(c.keywords) : undefined,\n sources: [this.name],\n // Preserve raw employee string for post-filtering (not included in CompanyResult)\n _raw_employees: c.employees,\n }));\n\n // Post-filter: Disco's employee_range API param is unreliable — enforce locally.\n // Parse the raw employee range string (e.g. \"1-10\", \"51-200\", \"5001+\") to get the\n // upper bound of the range, then check overlap with requested min/max.\n const needsFilter = query.min_employees != null || query.max_employees != null;\n const filtered = needsFilter\n ? mapped.filter((c) => {\n const range = parseEmployeeRange(c._raw_employees);\n if (!range) return false; // No employee data — exclude when filtering\n const { min: companyMin, max: companyMax } = range;\n if (query.min_employees != null && companyMax < query.min_employees) return false;\n if (query.max_employees != null && companyMin > query.max_employees) return false;\n return true;\n })\n : mapped;\n\n // Strip internal _raw_employees field before returning\n return filtered.map(({ _raw_employees: _, ...rest }) => rest);\n }\n\n async countCompanies(query: CompanyQuery): Promise<number> {\n const response = await this.client.count({\n domain: query.domains ?? query.domain,\n icp_text: query.icp_text,\n country: query.country,\n ...((query.min_employees != null || query.max_employees != null) && {\n employee_range: `${query.min_employees ?? ''},${query.max_employees ?? ''}`,\n }),\n tech_stack: query.tech_stack,\n category: query.category?.toUpperCase(),\n negate_domain: query.negate_domains,\n // offset intentionally omitted — count is always total, not paged\n });\n return response.count;\n }\n\n async getCompany(domain: string): Promise<CompanyResult | null> {\n try {\n const data = await this.client.getBizData(domain);\n\n const [growth, vendors, metrics] = await Promise.allSettled([\n this.client.getGrowth(domain),\n this.client.getVendors(domain),\n this.client.getMetrics(domain),\n ]);\n\n const growthData = growth.status === 'fulfilled' ? growth.value : undefined;\n const vendorsData = vendors.status === 'fulfilled' ? vendors.value : undefined;\n const metricsData = metrics.status === 'fulfilled' ? metrics.value : undefined;\n\n const vendorTech = vendorsData?.vendors?.map((v) => v.name) ?? [];\n const keywordList = data.keywords ? Object.keys(data.keywords) : [];\n\n return {\n domain: data.domain,\n name: data.name,\n description: data.description,\n industry: data.industry_groups ? Object.keys(data.industry_groups)[0] : undefined,\n employees: data.employees ? parseInt(data.employees, 10) || undefined : undefined,\n country: data.address?.country,\n linkedin_url: data.social_urls?.find((u) => u.includes('linkedin')),\n tech_stack: vendorTech.length > 0 ? vendorTech : undefined,\n keywords: keywordList.length > 0 ? keywordList : undefined,\n growth_signals: buildGrowthSignals(growthData),\n engagement_metrics: buildEngagementMetrics(metricsData),\n sources: [this.name],\n };\n } catch (error) {\n logError('disco:getCompany', error instanceof Error ? error : new Error(String(error)), {\n domain,\n });\n return null;\n }\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n const response = await this.client.searchContacts({\n domain: query.company_domains ?? query.company_domain,\n // Fall back to icp_text when company_name given without company_domain or company_domains\n icp_text:\n !query.company_domain && !query.company_domains && query.company_name\n ? query.company_name\n : undefined,\n title: query.job_title,\n ...parseLocation(query.location),\n has_email: query.has_email ?? true,\n max_records: query.limit ?? 25,\n seniority: query.seniority as DiscoSeniority[] | undefined,\n department: query.department,\n has_phone: query.has_phone,\n has_linkedin: query.has_linkedin,\n min_connections: query.min_connections,\n offset: query.offset,\n // ─── DiscoLike filters ───\n skills: query.skills,\n filter_industry: query.filter_industry,\n email_validated: query.email_validated,\n ...((query.min_employees != null || query.max_employees != null) && {\n employees: `${query.min_employees ?? ''},${query.max_employees ?? ''}`,\n }),\n revenue_range: query.revenue_range,\n });\n\n // Guard: API might return non-array (wrapped object) — normalize\n const contacts = Array.isArray(response) ? response : [];\n\n return contacts.map((c) => {\n const nameParts = parseName(c.name);\n return {\n first_name: nameParts.first,\n last_name: nameParts.last,\n job_title: safeString(c.title),\n company: safeString(c.company_name) ?? domainToCompanyName(c.domain),\n company_domain: c.domain,\n linkedin_url: safeStringArray(c.social_urls)?.find((u) => u.includes('linkedin')),\n email: safeString(c.email),\n phone:\n typeof c.phone === 'string'\n ? c.phone\n : Array.isArray(c.phone)\n ? c.phone[0]?.phone\n : undefined,\n seniority: safeString(c.seniority),\n department: safeString(c.department),\n skills: safeStringArray(c.skills),\n connections: c.connections,\n location: safeString(c.country),\n industry: extractIndustry(c.industry),\n sources: [this.name],\n };\n });\n }\n}\n\n// ─── Safe Value Extraction ──────────────────────────────\n\n/** Safely extract a string value. Returns undefined if the input is not a string.\n * Prevents [object Object] when API returns unexpected nested objects. */\nfunction safeString(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (value == null) return undefined;\n // Number/boolean — convert to string (legitimate scalar values)\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n // Object/array — do not coerce, return undefined\n return undefined;\n}\n\n/** Safely extract a string array. Filters out any non-string elements.\n * Prevents [object Object] when API returns array of objects instead of strings. */\nfunction safeStringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const strings = value.filter((item): item is string => typeof item === 'string');\n return strings.length > 0 ? strings : undefined;\n}\n\n/** Extract industry from Disco's polymorphic industry field.\n * Can be: string, string[], or array of objects with name property. */\nfunction extractIndustry(industry: unknown): string | undefined {\n if (typeof industry === 'string') return industry;\n if (Array.isArray(industry)) {\n const first = industry[0];\n if (typeof first === 'string') return first;\n // Object with name property: { name: \"Software\" }\n if (first != null && typeof first === 'object' && 'name' in first) {\n const name = (first as Record<string, unknown>).name;\n return typeof name === 'string' ? name : undefined;\n }\n }\n return undefined;\n}\n\n// ─── Employee Range Parsing ─────────────────────────────\n\n/** Parse Disco's employee range strings into numeric bounds.\n * Formats: \"1-10\", \"51-200\", \"5001+\", \"150\", \"unknown\"\n * Returns { min, max } or null if unparseable. */\nexport function parseEmployeeRange(raw: string | undefined): { min: number; max: number } | null {\n if (!raw) return null;\n const trimmed = raw.trim();\n\n // \"5001+\" format — open-ended upper bound\n const plusMatch = trimmed.match(/^(\\d+)\\+$/);\n if (plusMatch) {\n const min = parseInt(plusMatch[1], 10);\n return { min, max: Infinity };\n }\n\n // \"51-200\" range format (handles both hyphen and en-dash)\n const rangeMatch = trimmed.match(/^(\\d+)\\s*[-–]\\s*(\\d+)$/);\n if (rangeMatch) {\n return { min: parseInt(rangeMatch[1], 10), max: parseInt(rangeMatch[2], 10) };\n }\n\n // Plain number \"150\"\n const num = parseInt(trimmed, 10);\n if (!isNaN(num)) {\n return { min: num, max: num };\n }\n\n return null;\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\nfunction buildGrowthSignals(\n data:\n | {\n quarterly_growth?: number;\n growth_trend?: string;\n digital_footprint_score?: number;\n digital_footprint_trend?: string;\n }\n | undefined\n): CompanyResult['growth_signals'] {\n if (!data) return undefined;\n const signals = {\n quarterly_growth: data.quarterly_growth,\n growth_trend: data.growth_trend,\n digital_footprint_score: data.digital_footprint_score,\n digital_footprint_trend: data.digital_footprint_trend,\n };\n return Object.values(signals).some((v) => v != null) ? signals : undefined;\n}\n\nfunction buildEngagementMetrics(\n data:\n | {\n traffic_estimate?: number;\n social_presence?: number;\n monthly_visitors?: number;\n bounce_rate?: number;\n }\n | undefined\n): CompanyResult['engagement_metrics'] {\n if (!data) return undefined;\n const metrics = {\n traffic_estimate: data.traffic_estimate,\n social_presence: data.social_presence,\n monthly_visitors: data.monthly_visitors,\n bounce_rate: data.bounce_rate,\n };\n return Object.values(metrics).some((v) => v != null) ? metrics : undefined;\n}\n\nfunction parseName(fullName: string): { first: string; last: string } {\n const parts = fullName.trim().split(/\\s+/);\n if (parts.length === 0) return { first: '', last: '' };\n if (parts.length === 1) return { first: parts[0], last: '' };\n return { first: parts[0], last: parts.slice(1).join(' ') };\n}\n\n/** Parse a location string into Disco's person_country + person_state params.\n * \"US\" → {person_country: \"US\"}, \"Texas\" → {person_state: \"TX\", person_country: \"US\"},\n * \"New York\" → {person_state: \"NY\", person_country: \"US\"}, \"Germany\" → {person_country: \"DE\"} */\nconst US_STATES: Record<string, string> = {\n alabama: 'AL',\n alaska: 'AK',\n arizona: 'AZ',\n arkansas: 'AR',\n california: 'CA',\n colorado: 'CO',\n connecticut: 'CT',\n delaware: 'DE',\n florida: 'FL',\n georgia: 'GA',\n hawaii: 'HI',\n idaho: 'ID',\n illinois: 'IL',\n indiana: 'IN',\n iowa: 'IA',\n kansas: 'KS',\n kentucky: 'KY',\n louisiana: 'LA',\n maine: 'ME',\n maryland: 'MD',\n massachusetts: 'MA',\n michigan: 'MI',\n minnesota: 'MN',\n mississippi: 'MS',\n missouri: 'MO',\n montana: 'MT',\n nebraska: 'NE',\n nevada: 'NV',\n 'new hampshire': 'NH',\n 'new jersey': 'NJ',\n 'new mexico': 'NM',\n 'new york': 'NY',\n 'north carolina': 'NC',\n 'north dakota': 'ND',\n ohio: 'OH',\n oklahoma: 'OK',\n oregon: 'OR',\n pennsylvania: 'PA',\n 'rhode island': 'RI',\n 'south carolina': 'SC',\n 'south dakota': 'SD',\n tennessee: 'TN',\n texas: 'TX',\n utah: 'UT',\n vermont: 'VT',\n virginia: 'VA',\n washington: 'WA',\n 'west virginia': 'WV',\n wisconsin: 'WI',\n wyoming: 'WY',\n};\n\n// Reverse map: abbreviation → abbreviation (for \"TX\", \"NY\" etc.)\nconst US_STATE_CODES = new Set(Object.values(US_STATES));\n\nfunction parseLocation(location: string | undefined): {\n person_country?: string;\n person_state?: string;\n} {\n if (!location) return {};\n const lower = location.toLowerCase().trim();\n\n // Check if it's a US state name\n if (US_STATES[lower]) {\n return { person_country: 'US', person_state: US_STATES[lower] };\n }\n\n // Check if it's a US state code (2 letters)\n if (location.length === 2 && US_STATE_CODES.has(location.toUpperCase())) {\n return { person_country: 'US', person_state: location.toUpperCase() };\n }\n\n // Check for \"City, State\" pattern (e.g., \"Austin, TX\" or \"New York, NY\")\n const cityStateMatch = location.match(/^(.+),\\s*([A-Za-z]{2})$/);\n if (cityStateMatch && US_STATE_CODES.has(cityStateMatch[2].toUpperCase())) {\n return { person_country: 'US', person_state: cityStateMatch[2].toUpperCase() };\n }\n\n // Common country names → ISO codes\n const COUNTRY_MAP: Record<string, string> = {\n 'united states': 'US',\n usa: 'US',\n 'united kingdom': 'UK',\n uk: 'UK',\n germany: 'DE',\n france: 'FR',\n canada: 'CA',\n australia: 'AU',\n india: 'IN',\n brazil: 'BR',\n japan: 'JP',\n 'south korea': 'KR',\n spain: 'ES',\n italy: 'IT',\n netherlands: 'NL',\n sweden: 'SE',\n switzerland: 'CH',\n israel: 'IL',\n singapore: 'SG',\n mexico: 'MX',\n ireland: 'IE',\n poland: 'PL',\n };\n\n if (COUNTRY_MAP[lower]) {\n return { person_country: COUNTRY_MAP[lower] };\n }\n\n // If 2 chars, assume country code\n if (location.length === 2) {\n return { person_country: location.toUpperCase() };\n }\n\n // Fallback: pass as country (Disco will try to match)\n return { person_country: location };\n}\n\n/** Derive a readable company name from a domain.\n * stripe.com → Stripe, wisconsintechnologycouncil.com → Wisconsin Technology Council */\nfunction domainToCompanyName(domain: string): string {\n const slug = domain.split('.')[0] ?? domain;\n // Split on hyphens, underscores, and camelCase boundaries\n const words = slug\n .replace(/[-_]/g, ' ')\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .split(/\\s+/)\n .filter(Boolean);\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');\n}\n","/** Prospeo adapter. Verified via live curl testing 2026-03-15.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * Prospeo API constraints:\n * - Fixed page size of 25 (not configurable)\n * - Location filter field is person_location_search (NOT person_location)\n * - Headcount custom filter uses { min, max } (verified), range uses string labels\n * - Empty filters object causes 400 */\n\nimport { logError } from '@maestro/logging';\nimport { ProspeoClient } from '@maestro/integrations';\n\nimport type { ProspeoSearchFilters } from '@maestro/integrations';\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n PeopleFinder,\n EmailEnricher,\n CreditBalance,\n PeopleQuery,\n PersonResult,\n ContactInput,\n EnrichEmailResult,\n} from '../types.js';\n\n// ─── Constants ──────────────────────────────────────────\n\n/** Prospeo returns exactly 25 results per page. Not configurable. */\nconst PROSPEO_PAGE_SIZE = 25;\n\n/** Max pages to iterate. ceil(1000 / 25) — matches Zod schema max limit of 1000. */\nconst MAX_PAGES = 40;\n\n// ─── Seniority Mapping ──────────────────────────────────\n\n/** Prospeo seniority enum values (from /api-docs/enum/seniorities):\n * Founder/Owner, C-Suite, Partner, Vice President, Head, Director,\n * Manager, Senior, Entry, Intern */\nconst SENIORITY_TO_PROSPEO: Record<string, string> = {\n c_suite: 'C-Suite',\n founder: 'Founder/Owner',\n owner: 'Founder/Owner',\n partner: 'Partner',\n vp: 'Vice President',\n head: 'Head',\n director: 'Director',\n manager: 'Manager',\n senior: 'Senior',\n entry: 'Entry',\n intern: 'Intern',\n};\n\nfunction mapSeniority(values: string[] | undefined): { include: string[] } | undefined {\n if (!values?.length) return undefined;\n const mapped = values.map((v) => SENIORITY_TO_PROSPEO[v] ?? v);\n return { include: [...new Set(mapped)] };\n}\n\n// ─── Error Helpers ──────────────────────────────────────\n\n/** Check if an error is an ApiClientError with a specific status code.\n * Uses duck typing to avoid instanceof issues with mocked modules. */\nfunction isApiClientError(\n error: unknown,\n statusCode: number\n): error is { statusCode: number; responseBody?: unknown; message: string } {\n return (\n error instanceof Error &&\n 'statusCode' in error &&\n (error as { statusCode: number }).statusCode === statusCode\n );\n}\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class ProspeoMcpAdapter implements Provider, PeopleFinder, EmailEnricher {\n readonly name = 'prospeo';\n readonly capabilities: Capability[] = ['find_people', 'enrich_email'];\n readonly notes =\n 'Best for: city-level people search with industry/seniority/headcount ' +\n 'filters, email enrichment, company technology detection. 200M+ contacts. ' +\n 'Note: search emails are masked until revealed with credits. ' +\n 'Returns max 25 results per page (fixed by Prospeo API).';\n private readonly client: ProspeoClient;\n\n constructor(apiKey: string) {\n this.client = new ProspeoClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.getAccountInfo();\n return true;\n } catch (error) {\n logError(\n 'prospeo:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n try {\n const info = await this.client.getAccountInfo();\n return {\n remaining: info.response?.remaining_credits ?? 0,\n unit: 'credits',\n provider: this.name,\n };\n } catch (error) {\n logError('prospeo:checkCredits', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── PeopleFinder ────────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n const filters: ProspeoSearchFilters = {};\n\n // ─── Person filters ───\n if (query.job_title) {\n filters.person_job_title = { include: [query.job_title] };\n }\n if (query.seniority) {\n filters.person_seniority = mapSeniority(query.seniority);\n }\n if (query.department?.length) {\n filters.person_departments = { include: query.department };\n }\n if (query.location) {\n // Verified field name: person_location_search (NOT person_location)\n // Format: \"State, Country\" e.g. \"Texas, United States\"\n filters.person_location_search = { include: [query.location] };\n }\n\n // ─── Company filters ───\n // Prospeo company filter is a nested object with websites/names sub-objects\n if (query.company_domain || query.company_domains?.length) {\n const domains: string[] = [];\n if (query.company_domain) domains.push(query.company_domain);\n if (query.company_domains?.length) domains.push(...query.company_domains);\n filters.company = { websites: { include: [...new Set(domains)] } };\n } else if (query.company_name) {\n filters.company = { names: { include: [query.company_name] } };\n }\n if (query.filter_industry?.length) {\n filters.company_industry = { include: query.filter_industry };\n }\n if (query.min_employees != null || query.max_employees != null) {\n // Verified via curl: company_headcount_custom with { min, max } works\n filters.company_headcount_custom = {\n ...(query.min_employees != null && { min: query.min_employees }),\n ...(query.max_employees != null && { max: query.max_employees }),\n };\n }\n if (query.skills?.length) {\n filters.company_technology = { include: query.skills };\n }\n\n // Validate: Prospeo requires at least one filter — empty filters causes 400\n if (Object.keys(filters).length === 0) {\n throw Object.assign(\n new Error(\n 'Prospeo requires at least one search filter (job_title, location, company_domain, ' +\n 'seniority, industry, etc.). Provide search criteria to narrow results.'\n ),\n { statusCode: 400 }\n );\n }\n\n const requestedLimit = query.limit ?? PROSPEO_PAGE_SIZE;\n const startPage = query.offset ? Math.floor(query.offset / PROSPEO_PAGE_SIZE) + 1 : 1;\n\n try {\n const allResults: PersonResult[] = [];\n let page = startPage;\n\n // Auto-paginate: Prospeo returns max 25/page, so loop until we hit the requested limit.\n // MAX_PAGES guard prevents runaway iteration if the API always returns full pages.\n while (allResults.length < requestedLimit && page < startPage + MAX_PAGES) {\n const response = await this.client.searchPeople({ page, filters });\n\n if (response.error || !response.results?.length) break;\n\n const mapped = response.results.map((r) => ({\n first_name: r.person?.first_name ?? '',\n last_name: r.person?.last_name ?? '',\n job_title: r.person?.current_job_title ?? undefined,\n company: r.company?.name ?? undefined,\n company_domain: r.company?.domain ?? undefined,\n email: r.person?.email?.email ?? undefined,\n phone: r.person?.mobile?.mobile ?? undefined,\n linkedin_url: r.person?.linkedin_url ?? undefined,\n seniority: r.person?.job_history?.[0]?.seniority ?? undefined,\n department: r.person?.job_history?.[0]?.departments?.[0] ?? undefined,\n location: r.person?.location\n ? [r.person.location.city, r.person.location.state, r.person.location.country]\n .filter(Boolean)\n .join(', ')\n : undefined,\n sources: [this.name] as string[],\n }));\n allResults.push(...mapped);\n\n // Fewer than a full page means no more data\n if (response.results.length < PROSPEO_PAGE_SIZE) break;\n page++;\n }\n\n return allResults.slice(0, requestedLimit);\n } catch (error) {\n // Surface Prospeo-specific error details (filter_error, error_code) from 400 responses.\n // Uses duck typing instead of instanceof to work reliably with mocked modules.\n if (isApiClientError(error, 400)) {\n const body = error.responseBody as Record<string, unknown> | undefined;\n const filterError = body?.filter_error as string | undefined;\n const errorCode = body?.error_code as string | undefined;\n const detail = filterError || errorCode || error.message;\n throw Object.assign(new Error(`Prospeo search failed: ${detail}`), { statusCode: 400 });\n }\n throw error;\n }\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n try {\n const domain =\n contact.company_domain ??\n (contact.company\n ? `${contact.company.toLowerCase().replace(/[^a-z0-9]/g, '')}.com`\n : undefined);\n\n const response = await this.client.enrichPerson({\n first_name: contact.first_name,\n last_name: contact.last_name,\n company_website: domain,\n linkedin_url: contact.linkedin_url,\n });\n\n if (response.error || !response.person?.email?.email) return null;\n\n return {\n email: response.person.email.email,\n quality: response.person.email.status === 'verified' ? '95%' : '70%',\n provider: this.name,\n credits_consumed: 1,\n };\n } catch (error) {\n logError('prospeo:enrichEmail', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n}\n","/** PlusVibe adapter. Bridges PlusVibeClient to MCP Provider CampaignManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client. */\n\nimport { logError } from '@maestro/logging';\nimport { PlusVibeClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CampaignManager,\n Campaign,\n CampaignStats,\n CampaignLead,\n PushResult,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class PlusVibeAdapter implements Provider, CampaignManager {\n readonly name = 'plusvibe';\n readonly capabilities: Capability[] = ['campaign_email'];\n readonly notes = 'Best for: cold email campaign management, inbox rotation, analytics.';\n private readonly client: PlusVibeClient;\n\n constructor(apiKey: string, workspaceId: string) {\n this.client = new PlusVibeClient(apiKey, workspaceId);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.listCampaigns();\n return true;\n } catch (error) {\n logError(\n 'plusvibe:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── CampaignManager ───────────────────────────────────\n\n async listCampaigns(): Promise<Campaign[]> {\n const campaigns = await this.client.listCampaigns();\n return campaigns.map((c) => ({\n id: c.id,\n name: c.name,\n status: c.status,\n provider: this.name,\n }));\n }\n\n async getCampaignStats(campaignId: string): Promise<CampaignStats> {\n const stats = await this.client.getCampaignStats(campaignId);\n return {\n campaign_id: campaignId,\n sent: stats.emails_sent,\n opened: stats.emails_opened,\n replied: stats.emails_replied,\n bounced: stats.emails_bounced,\n provider: this.name,\n };\n }\n\n async addLeadsToCampaign(campaignId: string, leads: CampaignLead[]): Promise<PushResult> {\n const plusVibeLeads = leads.map((l) => ({\n email: l.email,\n first_name: l.first_name ?? '',\n last_name: l.last_name ?? '',\n company_name: l.company ?? '',\n }));\n\n const response = await this.client.addLeadsToCampaign(campaignId, plusVibeLeads);\n return {\n added: response.added ?? response.leads_uploaded ?? 0,\n duplicates: response.duplicates ?? response.duplicate_email_count ?? 0,\n errors: response.invalid_email_count ?? 0,\n provider: this.name,\n };\n }\n\n // ─── Campaign Creation ───────────────────────────────────\n\n async createCampaign(\n name: string\n ): Promise<{ id: string; name: string; status: string; provider: string }> {\n const campaign = await this.client.createCampaign({ camp_name: name });\n return {\n id: campaign.id,\n name: campaign.name,\n status: campaign.status,\n provider: this.name,\n };\n }\n}\n","/** HeyReach adapter. Bridges HeyReachClient to MCP Provider OutreachManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client. */\n\nimport { logError } from '@maestro/logging';\nimport { HeyReachClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n OutreachManager,\n Campaign,\n CampaignStats,\n OutreachLead,\n PushResult,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class HeyReachAdapter implements Provider, OutreachManager {\n readonly name = 'heyreach';\n readonly capabilities: Capability[] = ['outreach_linkedin'];\n readonly notes =\n 'Best for: LinkedIn outreach automation, connection requests, messaging campaigns.';\n private readonly client: HeyReachClient;\n\n constructor(apiKey: string) {\n this.client = new HeyReachClient(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.listCampaigns();\n return true;\n } catch (error) {\n logError(\n 'heyreach:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── OutreachManager ────────────────────────────────────\n\n async listCampaigns(): Promise<Campaign[]> {\n const campaigns = await this.client.listCampaigns();\n return campaigns.map((c) => ({\n id: String(c.id),\n name: c.name ?? '',\n status: String(c.status ?? 'unknown'),\n provider: this.name,\n }));\n }\n\n async getCampaignStats(campaignId: string): Promise<CampaignStats> {\n // Parse campaign ID to number — strip any surrounding quotes from CLI arg coercion\n const numericId = Number(campaignId.replace(/^\"|\"$/g, ''));\n if (Number.isNaN(numericId)) {\n throw new Error(`Invalid campaign_id: \"${campaignId}\" — must be a numeric HeyReach campaign ID`);\n }\n const analytics = await this.client.getCampaignAnalytics(numericId);\n return {\n campaign_id: campaignId,\n sent: (analytics.sent as number) ?? 0,\n opened: (analytics.accepted as number) ?? 0,\n replied: (analytics.replied as number) ?? 0,\n bounced: 0,\n provider: this.name,\n };\n }\n\n async addLeadsToCampaign(campaignId: string, leads: OutreachLead[]): Promise<PushResult> {\n // HeyReach AddLeadsToCampaign returns void — no per-lead counts available.\n const numericId = Number(campaignId.replace(/^\"|\"$/g, ''));\n await this.client.addLeadsToList(\n numericId,\n leads.map((l) => ({\n profileUrl: l.linkedin_url,\n firstName: l.first_name,\n lastName: l.last_name,\n }))\n );\n\n return {\n added: leads.length,\n duplicates: 0,\n errors: 0,\n provider: this.name,\n };\n }\n}\n","/** Attio adapter. Bridges AttioClient to MCP Provider CrmManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * FIELD TYPES: Attio fields have different shapes per type — text ({value}),\n * name ({full_name}), email ({email_address}), domain ({domain}),\n * record-reference ({target_object, target_record_id}),\n * select ({option}), status ({status}). extractField handles all of them. */\n\nimport { logError, logInfo, logWarn } from '@maestro/logging';\nimport { AttioClient } from '@maestro/integrations';\n\nimport type { AttioPerson } from '@maestro/integrations';\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CrmManager,\n CrmPersonQuery,\n CrmPerson,\n CrmPersonInput,\n CrmCompany,\n CrmDealInput,\n CrmDeal,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class AttioAdapter implements Provider, CrmManager {\n readonly name = 'attio';\n readonly capabilities: Capability[] = ['crm_read', 'crm_write'];\n readonly notes = 'Best for: CRM operations — people, companies, deals, tags.';\n private readonly client: AttioClient;\n\n constructor(apiKey: string) {\n this.client = new AttioClient(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n // Try to list people with a non-matching query to verify auth\n await this.client.findPersonByEmail('health-check@test.invalid');\n return true;\n } catch (error) {\n logError('attio:checkCredentials', error instanceof Error ? error : new Error(String(error)));\n return false;\n }\n }\n\n // ─── CrmManager ────────────────────────────────────────\n\n async findPerson(query: CrmPersonQuery): Promise<CrmPerson | null> {\n let person = null;\n\n if (query.email) {\n person = await this.client.findPersonByEmail(query.email);\n } else if (query.linkedin_url) {\n person = await this.client.findPersonByLinkedIn(query.linkedin_url);\n }\n\n if (!person) return null;\n\n return this.mapPerson(person);\n }\n\n async createPerson(data: CrmPersonInput): Promise<CrmPerson> {\n const companyRef = data.company ? await this.resolveCompany(data.company) : undefined;\n\n const person = await this.client.createPerson({\n first_name: data.first_name,\n last_name: data.last_name,\n email_addresses: data.email ? [data.email] : [],\n job_title: data.job_title,\n company: companyRef,\n });\n\n return this.mapPerson(person);\n }\n\n async updatePerson(id: string, data: Partial<CrmPersonInput>): Promise<CrmPerson> {\n const companyRef = data.company ? await this.resolveCompany(data.company) : undefined;\n\n const person = await this.client.updatePerson(id, {\n first_name: data.first_name,\n last_name: data.last_name,\n email_addresses: data.email ? [data.email] : undefined,\n job_title: data.job_title,\n company: companyRef,\n });\n\n return this.mapPerson(person);\n }\n\n async findCompany(name: string): Promise<CrmCompany | null> {\n const company = await this.client.findCompany(name);\n if (!company) return null;\n\n return {\n id: company.id.record_id,\n name: extractField(company.values, 'name') ?? name,\n domain: extractField(company.values, 'domains') ?? '',\n provider: this.name,\n };\n }\n\n async createDeal(data: CrmDealInput): Promise<CrmDeal> {\n const deal = await this.client.createDeal({\n name: data.name,\n stage: data.stage ?? 'New',\n owner_id: data.owner_id ?? '',\n });\n\n return {\n id: deal.id.record_id,\n name: data.name,\n stage: data.stage ?? 'New',\n provider: this.name,\n };\n }\n\n // ─── Helpers ────────────────────────────────────────────\n\n /**\n * Resolve a company name string to an Attio record reference.\n * Finds existing company by name, or creates a new one if not found.\n * Returns undefined only if both lookup and creation fail.\n */\n private async resolveCompany(\n companyName: string\n ): Promise<{ target_object: 'companies'; target_record_id: string } | undefined> {\n try {\n const found = await this.client.findCompany(companyName);\n if (found) {\n return { target_object: 'companies' as const, target_record_id: found.id.record_id };\n }\n } catch (error) {\n logWarn(\n 'attio:resolveCompany',\n `Company lookup failed for \"${companyName}\", will attempt creation`,\n {\n error: error instanceof Error ? error.message : String(error),\n }\n );\n }\n\n // Company not found — create it\n try {\n const created = await this.client.createCompany({ name: companyName });\n logInfo('attio:resolveCompany', `Created company \"${companyName}\" in Attio`, {\n record_id: created.id.record_id,\n });\n return { target_object: 'companies' as const, target_record_id: created.id.record_id };\n } catch (error) {\n logWarn(\n 'attio:resolveCompany',\n `Failed to create company \"${companyName}\" — person will be created without company link`,\n {\n error: error instanceof Error ? error.message : String(error),\n }\n );\n return undefined;\n }\n }\n\n private async mapPerson(person: AttioPerson): Promise<CrmPerson> {\n const recordId = person.id.record_id;\n const values = person.values;\n\n // Company is a record reference — resolve to company name via API lookup\n const companyName = await this.resolveCompanyName(values);\n\n return {\n id: recordId,\n name: extractField(values, 'name') ?? '',\n email: extractField(values, 'email_addresses') ?? '',\n company: companyName,\n job_title: extractField(values, 'job_title') ?? '',\n provider: this.name,\n };\n }\n\n /** Extract company name from a person's company record-reference field.\n * Falls back to empty string if lookup fails or field is missing. */\n private async resolveCompanyName(\n values: Record<string, Record<string, unknown>[]>\n ): Promise<string> {\n const companyValues = values.company;\n if (!Array.isArray(companyValues) || companyValues.length === 0) return '';\n\n const first = companyValues[0];\n\n // Plain text value (some Attio configs store company as text)\n if (typeof first.value === 'string') return first.value;\n\n // Record reference — look up the company name\n const recordId = first.target_record_id;\n if (typeof recordId !== 'string') return '';\n\n try {\n const company = await this.client.getCompanyById(recordId);\n if (company) {\n return extractField(company.values, 'name') ?? '';\n }\n } catch {\n // Lookup failed — return empty rather than [object Object]\n }\n\n return '';\n }\n}\n\n// ─── Field Extraction ───────────────────────────────────\n\n/** Extract a scalar string value from an Attio record's field.\n * Handles ALL Attio field types safely — never returns an object.\n *\n * Field type → shape → extracted property:\n * - text/url: { value: \"string\" } → .value\n * - name: { full_name: \"string\" } → .full_name\n * - email: { email_address: \"str\" } → .email_address\n * - domain: { domain: \"string\" } → .domain\n * - select: { option: \"string\" } → .option (string form)\n * - select (expanded): { option: { title: \"s\" }} → .option.title\n * - status: { status: \"string\" } → .status (string form)\n * - status (expanded): { status: { title: \"s\" }} → .status.title\n * - record-reference: { target_record_id: \"u\" } → NOT extracted here (use resolveCompanyName)\n */\nfunction extractField(\n obj: Record<string, Record<string, unknown>[]>,\n field: string\n): string | undefined {\n const value = obj[field];\n if (!Array.isArray(value) || value.length === 0) return undefined;\n\n const first = value[0];\n\n // Text, URL, or similar — { value: \"string\" }\n if (typeof first.value === 'string') return first.value;\n\n // Name field — { full_name: \"string\", first_name: \"string\", last_name: \"string\" }\n if (typeof first.full_name === 'string') return first.full_name;\n\n // Email field — { email_address: \"string\" }\n if (typeof first.email_address === 'string') return first.email_address;\n\n // Domain field — { domain: \"string\" }\n if (typeof first.domain === 'string') return first.domain;\n if (typeof first.original_domain === 'string') return first.original_domain;\n\n // Select field — { option: \"string\" } or { option: { title: \"string\" } }\n if (first.option != null) {\n if (typeof first.option === 'string') return first.option;\n const optionObj = first.option as Record<string, unknown>;\n if (typeof optionObj.title === 'string') return optionObj.title;\n }\n\n // Status field — { status: \"string\" } or { status: { title: \"string\" } }\n if (first.status != null) {\n if (typeof first.status === 'string') return first.status;\n const statusObj = first.status as Record<string, unknown>;\n if (typeof statusObj.title === 'string') return statusObj.title;\n }\n\n // Record reference or unknown shape — never coerce objects to strings\n return undefined;\n}\n","/** Apollo adapter. Bridges ApolloClient to MCP Provider interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client. */\n\nimport { logError } from '@maestro/logging';\nimport { ApolloClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CompanyFinder,\n PeopleFinder,\n EmailEnricher,\n CompanyQuery,\n CompanyResult,\n PeopleQuery,\n PersonResult,\n ContactInput,\n EnrichEmailResult,\n} from '../types.js';\n\n// ─── Helpers ─────────────────────────────────────────────\n\n/** Extract keyword tags from ICP text using regex splitting.\n * Fallback when AI extraction is unavailable or fails.\n * Splits on punctuation, removes noise phrases and filler words. */\nfunction extractKeywordTags(text: string): string[] {\n const NOISE =\n /\\b(\\d+[-–]\\d+\\s*employees?|employees?|companies?|businesses?|organizations?|startups?|firms?|based)\\b/gi;\n const FILLER = /\\b(in|the|a|an|and|or|for|to|of|with|that|are|is|who|which)\\b/gi;\n\n return text\n .split(/[,;.\\n]+/)\n .map((phrase) => phrase.replace(NOISE, '').replace(FILLER, '').replace(/\\s+/g, ' ').trim())\n .filter((phrase) => phrase.length > 1);\n}\n\n/** Call Haiku to extract keyword tags from ICP text. Returns null on failure.\n * 5s timeout — this is a cheap side-call, not the main operation. */\nasync function extractKeywordsWithAI(text: string, apiKey: string): Promise<string[] | null> {\n try {\n const res = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n model: 'claude-haiku-4-5-20251001',\n max_tokens: 200,\n system:\n \"Extract 3-7 keyword tags for a B2B company search API from the user's ICP description. \" +\n 'Return ONLY a JSON array of strings. Each tag should be 1-3 words. ' +\n 'Focus on industry, product type, and technology terms. ' +\n 'Omit generic words like \"companies\", \"businesses\", employee counts, and locations.',\n messages: [{ role: 'user', content: text }],\n }),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { content?: Array<{ text?: string }> };\n const content = data.content?.[0]?.text;\n if (!content) return null;\n const parsed: unknown = JSON.parse(content);\n return Array.isArray(parsed)\n ? (parsed.filter((t: unknown) => typeof t === 'string' && t.length > 1) as string[])\n : null;\n } catch {\n return null;\n }\n}\n\n/** Compose address from Apollo org fields — prefer raw_address, fallback to parts. */\nfunction buildAddress(org: {\n raw_address?: string | null;\n street_address?: string | null;\n city?: string | null;\n state?: string | null;\n postal_code?: string | null;\n country?: string | null;\n}): string | undefined {\n if (org.raw_address) return org.raw_address;\n const parts = [org.street_address, org.city, org.state, org.postal_code, org.country].filter(\n Boolean\n ) as string[];\n return parts.length > 1 ? parts.join(', ') : undefined;\n}\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class ApolloAdapter implements Provider, CompanyFinder, PeopleFinder, EmailEnricher {\n readonly name = 'apollo';\n readonly capabilities: Capability[] = ['find_companies', 'find_people', 'enrich_email'];\n readonly notes =\n 'Best for: people search by job title/company, org enrichment, email finding. 275M+ contact database.';\n private readonly client: ApolloClient;\n private readonly anthropicKey?: string;\n\n constructor(apiKey: string, anthropicKey?: string) {\n this.client = new ApolloClient({ apiKey });\n this.anthropicKey = anthropicKey;\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n // Use a minimal people search (free, no credits consumed)\n await this.client.searchPeople({ per_page: 1, page: 1 });\n return true;\n } catch (error) {\n logError(\n 'apollo:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── CompanyFinder ──────────────────────────────────────\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n const perPage = Math.min(query.limit ?? 25, 100);\n const page = query.offset ? Math.floor(query.offset / perPage) + 1 : 1;\n\n // Extract keyword tags — AI (Haiku) when available, regex fallback\n let keywords: string[] = [];\n if (query.icp_text) {\n if (this.anthropicKey) {\n keywords =\n (await extractKeywordsWithAI(query.icp_text, this.anthropicKey)) ??\n extractKeywordTags(query.icp_text);\n } else {\n keywords = extractKeywordTags(query.icp_text);\n }\n }\n\n const response = await this.client.searchOrganizations({\n ...(query.domain && { q_organization_domains: query.domain }),\n ...(query.domains?.length && { q_organization_domains_list: query.domains }),\n ...(keywords.length > 0 && { q_organization_keyword_tags: keywords }),\n ...(query.country && { organization_locations: [query.country] }),\n ...(query.min_employees != null &&\n query.max_employees != null && {\n organization_num_employees_ranges: [`${query.min_employees},${query.max_employees}`],\n }),\n ...(query.tech_stack?.length && {\n currently_using_any_of_technology_uids: query.tech_stack.map((t) =>\n t.toLowerCase().replace(/\\s+/g, '_')\n ),\n }),\n per_page: perPage,\n page,\n });\n\n return response.organizations.map((org) => ({\n domain: org.primary_domain ?? org.website_url ?? '',\n name: org.name,\n description: org.short_description ?? undefined,\n industry: org.industry ?? undefined,\n employees: org.estimated_num_employees ?? undefined,\n country: org.country ?? undefined,\n linkedin_url: org.linkedin_url ?? undefined,\n tech_stack: org.technology_names?.length ? org.technology_names : undefined,\n keywords: org.keywords?.length ? org.keywords : undefined,\n funding: org.total_funding_printed ?? undefined,\n revenue_estimate: org.annual_revenue ?? undefined,\n founded_year: org.founded_year ?? undefined,\n logo_url: org.logo_url ?? undefined,\n phone: org.phone ?? undefined,\n twitter_url: org.twitter_url ?? undefined,\n facebook_url: org.facebook_url ?? undefined,\n address: buildAddress(org),\n latest_funding_stage: org.latest_funding_stage ?? undefined,\n total_funding: org.total_funding ?? undefined,\n alexa_ranking: org.alexa_ranking ?? undefined,\n sources: [this.name],\n }));\n }\n\n async getCompany(domain: string): Promise<CompanyResult | null> {\n try {\n const response = await this.client.enrichOrganization({ domain });\n const org = response.organization;\n if (!org) return null;\n\n return {\n domain: org.primary_domain ?? domain,\n name: org.name,\n description: org.short_description ?? undefined,\n industry: org.industry ?? undefined,\n employees: org.estimated_num_employees ?? undefined,\n country: org.country ?? undefined,\n linkedin_url: org.linkedin_url ?? undefined,\n tech_stack: org.technology_names?.length ? org.technology_names : undefined,\n keywords: org.keywords?.length ? org.keywords : undefined,\n funding: org.total_funding_printed ?? undefined,\n revenue_estimate: org.annual_revenue ?? undefined,\n founded_year: org.founded_year ?? undefined,\n logo_url: org.logo_url ?? undefined,\n phone: org.phone ?? undefined,\n twitter_url: org.twitter_url ?? undefined,\n facebook_url: org.facebook_url ?? undefined,\n address: buildAddress(org),\n latest_funding_stage: org.latest_funding_stage ?? undefined,\n total_funding: org.total_funding ?? undefined,\n alexa_ranking: org.alexa_ranking ?? undefined,\n sources: [this.name],\n };\n } catch (error) {\n logError('apollo:getCompany', error instanceof Error ? error : new Error(String(error)), {\n domain,\n });\n return null;\n }\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n const perPage = Math.min(query.limit ?? 25, 100);\n const page = query.offset ? Math.floor(query.offset / perPage) + 1 : 1;\n\n // Build domain list — use q_organization_domains_list (exact match, array) not\n // q_organization_domains (fuzzy text search) for reliable domain-specific results.\n const domainList = [\n ...(query.company_domain ? [query.company_domain] : []),\n ...(query.company_domains ?? []),\n ];\n const uniqueDomains = [...new Set(domainList)];\n\n const response = await this.client.searchPeople({\n ...(query.job_title && {\n person_titles: query.job_titles ?? [query.job_title],\n }),\n ...(uniqueDomains.length > 0 && { q_organization_domains_list: uniqueDomains }),\n ...(query.company_name && { q_keywords: query.company_name }),\n ...(query.location && { person_locations: [query.location] }),\n ...(query.seniority && { person_seniorities: query.seniority }),\n per_page: perPage,\n page,\n });\n\n return response.people.map((p) => ({\n first_name: p.first_name,\n last_name: p.last_name,\n job_title: p.title ?? undefined,\n company: p.organization_name ?? undefined,\n linkedin_url: p.linkedin_url ?? undefined,\n // People search does NOT return email — null by design\n email: p.email ?? undefined,\n phone: p.phone_number ?? undefined,\n seniority: p.seniority ?? undefined,\n department: p.departments?.[0] ?? undefined,\n headline: p.headline ?? undefined,\n location: [p.city, p.state, p.country].filter(Boolean).join(', ') || undefined,\n photo_url: p.photo_url ?? undefined,\n twitter_url: p.twitter_url ?? undefined,\n github_url: p.github_url ?? undefined,\n facebook_url: p.facebook_url ?? undefined,\n email_status: p.email_status ?? undefined,\n sources: [this.name],\n }));\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n const response = await this.client.enrichPerson({\n first_name: contact.first_name,\n last_name: contact.last_name,\n ...(contact.company && { organization_name: contact.company }),\n ...(contact.company_domain && { domain: contact.company_domain }),\n ...(contact.linkedin_url && { linkedin_url: contact.linkedin_url }),\n });\n\n const person = response.person;\n if (!person?.email) return null;\n\n return {\n email: person.email,\n quality: person.email_status ?? undefined,\n provider: this.name,\n };\n }\n}\n","/** Instantly adapter. Bridges InstantlyClient to MCP Provider CampaignManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client. */\n\nimport { logError } from '@maestro/logging';\nimport { InstantlyClient, INSTANTLY_STATUS_LABELS } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CampaignManager,\n Campaign,\n CampaignStats,\n CampaignLead,\n PushResult,\n} from '../types.js';\n\nimport type { InstantlyCampaignStatus } from '@maestro/integrations';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class InstantlyAdapter implements Provider, CampaignManager {\n readonly name = 'instantly';\n readonly capabilities: Capability[] = ['campaign_email'];\n readonly notes =\n 'Best for: cold email campaigns with built-in warmup, deliverability tools, and analytics.';\n private readonly client: InstantlyClient;\n\n constructor(apiKey: string) {\n this.client = new InstantlyClient(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.listCampaigns();\n return true;\n } catch (error) {\n logError(\n 'instantly:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── CampaignManager ───────────────────────────────────\n\n async listCampaigns(): Promise<Campaign[]> {\n const campaigns = await this.client.listCampaigns();\n return campaigns.map((c) => ({\n id: c.id,\n name: c.name ?? '',\n status: INSTANTLY_STATUS_LABELS[c.status as InstantlyCampaignStatus] ?? 'unknown',\n provider: this.name,\n }));\n }\n\n async getCampaignStats(campaignId: string): Promise<CampaignStats> {\n const analytics = await this.client.getCampaignAnalytics(campaignId);\n return {\n campaign_id: campaignId,\n sent: analytics.emails_sent_count ?? 0,\n opened: analytics.open_count ?? 0,\n replied: analytics.reply_count ?? 0,\n bounced: analytics.bounced_count ?? 0,\n provider: this.name,\n };\n }\n\n async addLeadsToCampaign(campaignId: string, leads: CampaignLead[]): Promise<PushResult> {\n const instantlyLeads = leads.map((l) => ({\n email: l.email,\n first_name: l.first_name ?? '',\n last_name: l.last_name ?? '',\n company_name: l.company ?? '',\n ...(l.custom_fields && Object.keys(l.custom_fields).length > 0\n ? { custom_variables: l.custom_fields }\n : {}),\n }));\n\n await this.client.addLeadsToCampaign(campaignId, instantlyLeads);\n\n // Instantly's add endpoint doesn't return per-lead counts\n return {\n added: leads.length,\n duplicates: 0,\n errors: 0,\n provider: this.name,\n };\n }\n}\n","/** SmartLead adapter. Bridges SmartLeadClient to MCP Provider CampaignManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client. */\n\nimport { logError } from '@maestro/logging';\nimport { SmartLeadClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CampaignManager,\n Campaign,\n CampaignStats,\n CampaignLead,\n PushResult,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class SmartLeadAdapter implements Provider, CampaignManager {\n readonly name = 'smartlead';\n readonly capabilities: Capability[] = ['campaign_email'];\n readonly notes = 'Best for: cold email campaigns with multi-mailbox rotation and AI warmup.';\n private readonly client: SmartLeadClient;\n\n constructor(apiKey: string) {\n this.client = new SmartLeadClient(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.listCampaigns();\n return true;\n } catch (error) {\n logError(\n 'smartlead:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── CampaignManager ───────────────────────────────────\n\n async listCampaigns(): Promise<Campaign[]> {\n const campaigns = await this.client.listCampaigns();\n return campaigns.map((c) => ({\n id: String(c.id),\n name: c.name,\n status: c.status,\n provider: this.name,\n }));\n }\n\n async getCampaignStats(campaignId: string): Promise<CampaignStats> {\n const analytics = await this.client.getCampaignAnalytics(Number(campaignId));\n return {\n campaign_id: campaignId,\n sent: analytics.total_sent,\n opened: analytics.total_opened,\n replied: analytics.total_replied,\n bounced: 0,\n provider: this.name,\n };\n }\n\n async addLeadsToCampaign(campaignId: string, leads: CampaignLead[]): Promise<PushResult> {\n const smartLeadLeads = leads.map((l) => {\n const { phone_number, linkedin_profile, ...remainingCustom } = l.custom_fields ?? {};\n return {\n email: l.email,\n first_name: l.first_name ?? '',\n last_name: l.last_name ?? '',\n company_name: l.company ?? '',\n ...(phone_number && { phone_number }),\n ...(linkedin_profile && { linkedin_profile }),\n ...(Object.keys(remainingCustom).length > 0 && { custom_fields: remainingCustom }),\n };\n });\n\n const response = await this.client.addLeadsToCampaign(Number(campaignId), smartLeadLeads);\n return {\n added: response.added_count,\n duplicates: response.skipped_count,\n errors: 0,\n provider: this.name,\n };\n }\n}\n","/** StoreLeads adapter. Queries StorLeads API for e-commerce company data.\n * Constraint: No Supabase. Direct API calls to storeleads.app. */\n\nimport { logError } from '@maestro/logging';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider, CompanyFinder, CompanyQuery, CompanyResult } from '../types.js';\n\n// ─── Constants ─────────────────────────────────────────\n\nconst BASE_URL = 'https://storeleads.app/json/api/v1/all/domain';\nconst MAX_PAGE_SIZE = 50;\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nconst FIELDS = [\n 'domain',\n 'merchant_name',\n 'categories',\n 'country_code',\n 'administrative_area_level_1',\n 'employee_count',\n 'estimated_yearly_sales',\n 'description',\n 'contact_info',\n 'platform',\n].join(',');\n\n// ─── Query Type ─────────────────────────────────────────\n\nexport interface StoreLeadsQuery {\n search?: string;\n category?: string;\n country?: string;\n state?: string;\n min_revenue?: number;\n max_revenue?: number;\n min_employees?: number;\n max_employees?: number;\n platform?: string;\n limit?: number;\n}\n\n// ─── API Response Type ──────────────────────────────────\n\ninterface StoreLeadsDomain {\n domain?: string;\n merchant_name?: string;\n categories?: string[];\n country_code?: string;\n administrative_area_level_1?: string;\n employee_count?: number;\n estimated_yearly_sales?: number;\n description?: string;\n contact_info?: {\n linkedin?: string;\n };\n platform?: string;\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class StoreLeadsAdapter implements Provider, CompanyFinder {\n readonly name = 'storeleads';\n readonly capabilities: Capability[] = ['find_companies'];\n readonly notes =\n 'Best for: DTC, e-commerce, Shopify brands. 1.2M+ active stores with revenue estimates and categories. Requires API key from storeleads.app.';\n private readonly apiKey: string;\n\n constructor(apiKey: string) {\n this.apiKey = apiKey;\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n const url = `${BASE_URL}?page_size=1&fields=domain`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n return res.ok;\n } catch (error) {\n logError(\n 'storeleads:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n return this.search({\n search: query.search,\n category: query.category,\n country: query.country,\n state: query.state,\n platform: query.platform,\n min_revenue: query.min_revenue,\n max_revenue: query.max_revenue,\n min_employees: query.min_employees,\n max_employees: query.max_employees,\n limit: query.limit,\n });\n }\n\n private async search(query: StoreLeadsQuery): Promise<CompanyResult[]> {\n const params = new URLSearchParams();\n params.set('fields', FIELDS);\n params.set('sort', '-estimated_yearly_sales');\n params.set('page_size', String(Math.min(query.limit ?? 50, MAX_PAGE_SIZE)));\n\n if (query.search) params.set('q', query.search);\n if (query.category) params.set('f:categories', query.category);\n if (query.country) params.set('f:country_code', query.country);\n if (query.state) params.set('f:administrative_area_level_1', query.state);\n if (query.platform) params.set('f:platform', query.platform);\n if (query.min_revenue != null)\n params.set('f:estimated_yearly_sales:min', String(query.min_revenue));\n if (query.max_revenue != null)\n params.set('f:estimated_yearly_sales:max', String(query.max_revenue));\n if (query.min_employees != null) params.set('f:ec:min', String(query.min_employees));\n if (query.max_employees != null) params.set('f:ec:max', String(query.max_employees));\n\n const url = `${BASE_URL}?${params.toString()}`;\n\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw Object.assign(\n new Error(`StoreLeads API error ${res.status}: ${body || res.statusText}`),\n { statusCode: res.status === 429 ? 429 : 502 }\n );\n }\n\n const data: StoreLeadsDomain[] = await res.json();\n\n return data.map((d) => ({\n domain: d.domain ?? '',\n name: d.merchant_name ?? d.domain ?? '',\n description: d.description ?? undefined,\n industry: d.categories?.join(', ') ?? undefined,\n employees: d.employee_count ?? undefined,\n country: d.country_code ?? undefined,\n linkedin_url: d.contact_info?.linkedin ?? undefined,\n score: d.estimated_yearly_sales ? Number(d.estimated_yearly_sales) : undefined,\n revenue_estimate: d.estimated_yearly_sales ? Number(d.estimated_yearly_sales) : undefined,\n }));\n }\n}\n","/** HarvestAPI adapter. Bridges HarvestClient to MCP Provider interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * NOT an Extractor — has 5 distinct actions with different inputs/outputs. */\n\nimport { logError } from '@maestro/logging';\nimport { HarvestClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider } from '../types.js';\nimport type {\n HarvestProfile,\n HarvestPost,\n HarvestComment,\n HarvestReaction,\n HarvestResponse,\n HarvestPostSearchOptions,\n HarvestProfilePostsOptions,\n HarvestCompanyPostsOptions,\n HarvestPaginationOptions,\n} from '@maestro/integrations';\n\n// ─── Engagement Result ──────────────────────────────────\n\nexport interface EngagementResult {\n comments: HarvestComment[];\n reactions: HarvestReaction[];\n post_url: string;\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class HarvestApiAdapter implements Provider {\n readonly name = 'harvest';\n readonly capabilities: Capability[] = ['extract_linkedin'];\n readonly notes =\n 'Best for: LinkedIn profile scraping, post search, engagement mining, activity signals. Called by gtm_extract for LinkedIn types.';\n private readonly client: HarvestClient;\n private credentialsCached: boolean | null = null;\n\n constructor(apiKey: string) {\n this.client = new HarvestClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n if (this.credentialsCached !== null) return this.credentialsCached;\n try {\n await this.client.searchPosts({ search: 'test', postedLimit: '24h' });\n this.credentialsCached = true;\n return true;\n } catch (error) {\n logError(\n 'harvest:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n this.credentialsCached = false;\n return false;\n }\n }\n\n // ─── Profile ────────────────────────────────────────────\n\n async getProfile(identifier: string, findEmail?: boolean): Promise<HarvestProfile> {\n return this.client.getProfile(identifier, findEmail ? { findEmail: true } : undefined);\n }\n\n // ─── Posts ──────────────────────────────────────────────\n\n async searchPosts(\n query: string,\n options?: Omit<HarvestPostSearchOptions, 'search'>\n ): Promise<HarvestResponse<HarvestPost>> {\n return this.client.searchPosts({ search: query, ...options });\n }\n\n async getProfilePosts(\n options: HarvestProfilePostsOptions\n ): Promise<HarvestResponse<HarvestPost>> {\n return this.client.getProfilePosts(options);\n }\n\n async getCompanyPosts(\n options: HarvestCompanyPostsOptions\n ): Promise<HarvestResponse<HarvestPost>> {\n return this.client.getCompanyPosts(options);\n }\n\n // ─── Engagement ─────────────────────────────────────────\n\n async getPostEngagement(\n postUrl: string,\n type: 'comments' | 'reactions' | 'both',\n options?: HarvestPaginationOptions\n ): Promise<EngagementResult> {\n const [comments, reactions] = await Promise.all([\n type === 'reactions'\n ? Promise.resolve({ elements: [] as HarvestComment[] })\n : this.client.getPostComments(postUrl, options),\n type === 'comments'\n ? Promise.resolve({ elements: [] as HarvestReaction[] })\n : this.client.getPostReactions(postUrl, options),\n ]);\n\n return {\n comments: comments.elements as HarvestComment[],\n reactions: reactions.elements as HarvestReaction[],\n post_url: postUrl,\n };\n }\n}\n","/** Exa adapter. Bridges Exa.ai semantic search API to MCP Provider CompanyFinder interface.\n * Constraint: No @maestro/integrations dependency. Direct fetch() calls to Exa REST API. */\n\nimport { logError } from '@maestro/logging';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider, CompanyFinder, CompanyQuery, CompanyResult } from '../types.js';\n\n// ─── Constants ─────────────────────────────────────────\n\nconst BASE_URL = 'https://api.exa.ai';\nconst REQUEST_TIMEOUT_MS = 15_000;\n\n// ─── Exa API Response Types ───────────────────────────\n\ninterface ExaSearchResult {\n url: string;\n title?: string;\n text?: string;\n summary?: string;\n score?: number;\n}\n\ninterface ExaSearchResponse {\n results: ExaSearchResult[];\n}\n\n// ─── Adapter ──────────────────────────────────────────\n\nexport class ExaAdapter implements Provider, CompanyFinder {\n readonly name = 'exa';\n readonly capabilities: Capability[] = ['find_companies'];\n readonly notes =\n 'Best for: semantic/neural company search. \"Companies like Stripe but for healthcare\" works. Meaning-based, not keyword matching.';\n private readonly apiKey: string;\n\n constructor(apiKey: string) {\n this.apiKey = apiKey;\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n const res = await this.post('/search', {\n query: 'test',\n type: 'neural',\n category: 'company',\n numResults: 1,\n });\n return res.ok;\n } catch (error) {\n logError('exa:checkCredentials', error instanceof Error ? error : new Error(String(error)));\n return false;\n }\n }\n\n // ─── CompanyFinder ──────────────────────────────────\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n const response = await this.routeQuery(query);\n const data: ExaSearchResponse = await response.json();\n const results = Array.isArray(data.results) ? data.results : [];\n\n return results.map((r) => this.mapResult(r));\n }\n\n // ─── Query Routing ──────────────────────────────────\n\n private async routeQuery(query: CompanyQuery): Promise<Response> {\n // Single domain lookup\n if (query.domain && !query.icp_text && !query.domains?.length) {\n return this.searchSingleDomain(query.domain, query);\n }\n\n // Lookalike search (find companies similar to a given domain)\n if (query.domains?.length) {\n return this.findSimilar(query.domains, query);\n }\n\n // Semantic ICP search (default)\n return this.searchByIcp(query.icp_text ?? '', query);\n }\n\n private async searchByIcp(icpText: string, query: CompanyQuery): Promise<Response> {\n const body: Record<string, unknown> = {\n query: icpText,\n type: 'neural',\n category: 'company',\n numResults: query.limit ?? 25,\n contents: {\n text: { maxCharacters: 500 },\n summary: { query: 'What does this company do?' },\n },\n };\n\n if (query.negate_domains?.length) {\n body.excludeDomains = query.negate_domains;\n }\n\n return this.post('/search', body);\n }\n\n private async findSimilar(domains: string[], query: CompanyQuery): Promise<Response> {\n const primaryDomain = domains[0];\n const url = primaryDomain.includes('://') ? primaryDomain : `https://${primaryDomain}`;\n\n const body: Record<string, unknown> = {\n url,\n numResults: query.limit ?? 25,\n category: 'company',\n contents: {\n text: { maxCharacters: 500 },\n summary: { query: 'What does this company do?' },\n },\n };\n\n // Use remaining domains as includeDomains filter\n if (domains.length > 1) {\n body.includeDomains = domains.slice(1);\n }\n\n if (query.negate_domains?.length) {\n body.excludeDomains = query.negate_domains;\n }\n\n return this.post('/findSimilar', body);\n }\n\n private async searchSingleDomain(domain: string, query: CompanyQuery): Promise<Response> {\n const body: Record<string, unknown> = {\n query: domain,\n type: 'neural',\n category: 'company',\n includeDomains: [domain],\n numResults: 1,\n contents: {\n text: { maxCharacters: 1000 },\n summary: { query: 'What does this company do and what industry is it in?' },\n },\n };\n\n if (query.negate_domains?.length) {\n body.excludeDomains = query.negate_domains;\n }\n\n return this.post('/search', body);\n }\n\n // ─── Result Mapping ─────────────────────────────────\n\n private mapResult(result: ExaSearchResult): CompanyResult {\n return {\n domain: extractDomain(result.url),\n name: cleanTitle(result.title ?? extractDomain(result.url)),\n description: result.summary ?? truncate(result.text, 300),\n score: result.score,\n sources: [this.name],\n };\n }\n\n // ─── HTTP ───────────────────────────────────────────\n\n private async post(path: string, body: Record<string, unknown>): Promise<Response> {\n const res = await fetch(`${BASE_URL}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw Object.assign(new Error(`Exa API error ${res.status}: ${text || res.statusText}`), {\n statusCode: res.status === 429 ? 429 : 502,\n });\n }\n\n return res;\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────\n\n/** Extract bare domain from a URL. Strips protocol, www prefix, and path. */\nfunction extractDomain(url: string): string {\n try {\n return new URL(url).hostname.replace(/^www\\./, '');\n } catch {\n // Fallback for malformed URLs\n return (\n url\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0] ?? url\n );\n }\n}\n\n/** Clean up title strings (remove trailing \" - Company\" suffixes, etc.) */\nfunction cleanTitle(title: string): string {\n return title.replace(/\\s*[-|]\\s*[^-|]*$/, '').trim() || title;\n}\n\n/** Truncate a string to maxLength characters, adding ellipsis if truncated. */\nfunction truncate(text: string | undefined, maxLength: number): string | undefined {\n if (!text) return undefined;\n if (text.length <= maxLength) return text;\n return text.slice(0, maxLength - 3) + '...';\n}\n","/** LeadMagic adapter. Full B2B enrichment: email, phone, validation, people, companies.\n * Constraint: No direct API calls. Delegates to @maestro/integrations LeadMagicClient.\n * Pricing: pay-on-find for most endpoints. Email validation is 0.05 credits. */\n\nimport { logError } from '@maestro/logging';\nimport { LeadMagicClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CreditBalance,\n EmailEnricher,\n PhoneEnricher,\n EmailVerifier,\n PeopleFinder,\n ContactInput,\n EnrichEmailResult,\n EnrichPhoneResult,\n VerificationResult,\n PeopleQuery,\n PersonResult,\n} from '../types.js';\n\n// ─── Status Mapping ─────────────────────────────────────\n\n/** Map LeadMagic email status to quality label. */\nfunction mapEmailQuality(status?: string): string {\n switch (status) {\n case 'valid':\n return '95%';\n case 'valid_catch_all':\n return '80%';\n case 'catch_all':\n return '60%';\n default:\n return '50%';\n }\n}\n\n/** Map LeadMagic email_status to MCP verification status. */\nfunction mapVerificationStatus(\n status?: string\n): 'deliverable' | 'catch_all_safe' | 'catch_all_not_safe' | 'undeliverable' | 'unknown' {\n switch (status) {\n case 'valid':\n return 'deliverable';\n case 'valid_catch_all':\n return 'catch_all_safe';\n case 'catch_all':\n return 'catch_all_not_safe';\n case 'invalid':\n return 'undeliverable';\n default:\n return 'unknown';\n }\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class LeadMagicAdapter\n implements Provider, EmailEnricher, PhoneEnricher, EmailVerifier, PeopleFinder\n{\n readonly name = 'leadmagic';\n readonly capabilities: Capability[] = [\n 'enrich_email',\n 'enrich_phone',\n 'verify_email',\n 'find_people',\n ];\n readonly notes =\n 'Best for: email enrichment (name+domain), email validation (0.05 credits), ' +\n 'mobile finder (needs LinkedIn URL, 5 credits), employee lists (0.05/employee). ' +\n 'Also supports: profile search, company search, technographics, funding, competitors, ' +\n 'job change detection. Pay-on-find pricing — free when no result.';\n private readonly client: LeadMagicClient;\n\n constructor(apiKey: string) {\n this.client = new LeadMagicClient({ apiKey });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n // LeadMagic has no dedicated credentials endpoint.\n // Validate by making a cheap email validation call.\n await this.client.validateEmail({ email: 'test@example.com' });\n return true;\n } catch (error) {\n logError(\n 'leadmagic:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n // LeadMagic has no credits/balance API endpoint\n return null;\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n try {\n // Try name + domain first (most common enrichment path)\n if (contact.first_name && contact.last_name && (contact.company_domain || contact.company)) {\n const response = await this.client.findEmail({\n first_name: contact.first_name,\n last_name: contact.last_name,\n domain: contact.company_domain,\n company_name: !contact.company_domain ? contact.company : undefined,\n });\n\n if (response.email && response.status !== 'not_found') {\n return {\n email: response.email,\n quality: mapEmailQuality(response.status),\n provider: this.name,\n credits_consumed: response.credits_consumed,\n };\n }\n }\n\n // Fallback: try LinkedIn profile → email if we have a profile URL\n if (contact.linkedin_url) {\n const response = await this.client.profileToEmail({\n profile_url: contact.linkedin_url,\n });\n\n if (response.email) {\n return {\n email: response.email,\n quality: '80%', // Profile-to-email doesn't return validation status\n provider: this.name,\n credits_consumed: response.credits_consumed,\n };\n }\n }\n\n return null;\n } catch (error) {\n logError('leadmagic:enrichEmail', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── PhoneEnricher ──────────────────────────────────────\n\n async enrichPhone(contact: ContactInput): Promise<EnrichPhoneResult | null> {\n try {\n const response = await this.client.findMobile({\n profile_url: contact.linkedin_url,\n work_email: undefined, // Could pass email if available\n personal_email: undefined,\n });\n\n if (!response.mobile_number) return null;\n\n return {\n phone: response.mobile_number,\n provider: this.name,\n };\n } catch (error) {\n logError('leadmagic:enrichPhone', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── EmailVerifier ──────────────────────────────────────\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n try {\n const response = await this.client.validateEmail({ email });\n\n return {\n email: response.email ?? email,\n valid: response.email_status === 'valid' || response.email_status === 'valid_catch_all',\n status: mapVerificationStatus(response.email_status),\n provider: this.name,\n };\n } catch (error) {\n logError('leadmagic:verifyEmail', error instanceof Error ? error : new Error(String(error)));\n return {\n email,\n valid: false,\n status: 'unknown',\n provider: this.name,\n };\n }\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n try {\n // If we have a job title + company, use Role Finder (finds one person by role)\n if (query.job_title && (query.company_domain || query.company_name)) {\n const response = await this.client.findRole({\n job_title: query.job_title,\n company_domain: query.company_domain,\n company_name: !query.company_domain ? query.company_name : undefined,\n });\n\n if (response.first_name && response.last_name) {\n return [\n {\n first_name: response.first_name,\n last_name: response.last_name,\n job_title: response.job_title ?? undefined,\n company: response.company_name ?? undefined,\n company_domain: response.company_website ?? query.company_domain ?? undefined,\n linkedin_url: response.profile_url ?? undefined,\n sources: [this.name],\n },\n ];\n }\n return [];\n }\n\n // Otherwise, use Employee Finder (lists employees at a company)\n if (query.company_domain || query.company_name) {\n const response = await this.client.findEmployees({\n company_domain: query.company_domain,\n company_name: !query.company_domain ? query.company_name : undefined,\n limit: query.limit ?? 20,\n });\n\n if (!response.data?.length) return [];\n\n return response.data.map((emp) => ({\n first_name: emp.first_name ?? '',\n last_name: emp.last_name ?? '',\n job_title: emp.title ?? undefined,\n company: emp.company_name ?? undefined,\n company_domain: emp.website ?? query.company_domain ?? undefined,\n sources: [this.name],\n }));\n }\n\n return [];\n } catch (error) {\n logError('leadmagic:findPeople', error instanceof Error ? error : new Error(String(error)));\n return [];\n }\n }\n}\n","/** Twenty CRM adapter. Bridges TwentyClient to MCP Provider CrmManager interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * FIELD TYPES: Twenty uses composite fields — FullName for names, Emails for email,\n * Links for URLs/domains, Currency for amounts. All mapped to flat CRM types here. */\n\nimport { logError, logInfo, logWarn } from '@maestro/logging';\nimport { TwentyClient } from '@maestro/integrations';\n\nimport type { TwentyPerson, TwentyCompany } from '@maestro/integrations';\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CrmManager,\n CrmPersonQuery,\n CrmPerson,\n CrmPersonInput,\n CrmCompany,\n CrmDealInput,\n CrmDeal,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class TwentyAdapter implements Provider, CrmManager {\n readonly name = 'twenty';\n readonly capabilities: Capability[] = ['crm_read', 'crm_write'];\n readonly notes = 'Twenty CRM: people, companies, opportunities (deals).';\n private readonly client: TwentyClient;\n\n constructor(apiKey: string, baseUrl: string) {\n this.client = new TwentyClient({ apiKey, baseUrl });\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.listPeople({ limit: 1 });\n return true;\n } catch (error) {\n logError(\n 'twenty:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n // ─── CrmManager ────────────────────────────────────────\n\n async findPerson(query: CrmPersonQuery): Promise<CrmPerson | null> {\n let person: TwentyPerson | null = null;\n\n if (query.email) {\n person = await this.client.findPersonByEmail(query.email);\n }\n // Twenty REST API doesn't support native LinkedIn URL filter.\n // Name search would require listing + client-side match — skip for now.\n\n if (!person) return null;\n\n return this.mapPerson(person);\n }\n\n async createPerson(data: CrmPersonInput): Promise<CrmPerson> {\n const person = await this.client.createPerson({\n name: { firstName: data.first_name, lastName: data.last_name },\n emails: { primaryEmail: data.email ?? '' },\n ...(data.job_title ? { jobTitle: data.job_title } : {}),\n });\n\n if (data.company) {\n const companyId = await this.resolveCompanyId(data.company);\n if (companyId) {\n await this.client.updatePerson(person.id, { companyId });\n }\n }\n\n return this.mapPerson(person);\n }\n\n async updatePerson(id: string, data: Partial<CrmPersonInput>): Promise<CrmPerson> {\n const updates: Record<string, unknown> = {};\n\n if (data.first_name !== undefined || data.last_name !== undefined) {\n updates.name = {\n firstName: data.first_name ?? '',\n lastName: data.last_name ?? '',\n };\n }\n if (data.email !== undefined) {\n updates.emails = { primaryEmail: data.email };\n }\n if (data.job_title !== undefined) {\n updates.jobTitle = data.job_title;\n }\n if (data.company) {\n const companyId = await this.resolveCompanyId(data.company);\n if (companyId) updates.companyId = companyId;\n }\n\n const person = await this.client.updatePerson(id, updates);\n return this.mapPerson(person);\n }\n\n async findCompany(name: string): Promise<CrmCompany | null> {\n // Try domain search if name looks like a domain\n if (name.includes('.')) {\n const company = await this.client.findCompanyByDomain(name);\n if (company) return this.mapCompany(company);\n }\n\n // Search by exact name — strip double quotes to prevent filter injection\n const safeName = name.replace(/\"/g, '');\n const res = await this.client.listCompanies({\n filter: `and(name[eq]:\"${safeName}\")`,\n limit: 1,\n });\n const companies = res.data.companies ?? [];\n if (companies.length === 0) return null;\n\n return this.mapCompany(companies[0]);\n }\n\n async createDeal(data: CrmDealInput): Promise<CrmDeal> {\n const opp = await this.client.createOpportunity({\n name: data.name,\n stage: data.stage ?? 'New',\n pointOfContactId: data.person_id,\n companyId: data.company_id,\n ...(data.value != null\n ? { amount: { amountMicros: Math.round(data.value * 1_000_000), currencyCode: 'USD' } }\n : {}),\n });\n\n return {\n id: opp.id,\n name: data.name,\n stage: data.stage ?? 'New',\n provider: this.name,\n };\n }\n\n // ─── Helpers ────────────────────────────────────────────\n\n private mapPerson(person: TwentyPerson): CrmPerson {\n const firstName = person.name.firstName ?? '';\n const lastName = person.name.lastName ?? '';\n return {\n id: person.id,\n name: [firstName, lastName].filter(Boolean).join(' '),\n email: person.emails.primaryEmail || undefined,\n job_title: person.jobTitle ?? undefined,\n provider: this.name,\n };\n }\n\n private mapCompany(company: TwentyCompany): CrmCompany {\n return {\n id: company.id,\n name: company.name ?? '',\n domain: company.domainName?.primaryLinkUrl ?? '',\n provider: this.name,\n };\n }\n\n /** Resolve a company name/domain to a Twenty company ID.\n * Finds existing or creates new. Returns undefined on failure. */\n private async resolveCompanyId(companyName: string): Promise<string | undefined> {\n try {\n const found = await this.findCompany(companyName);\n if (found) return found.id;\n\n const isDomain = companyName.includes('.');\n const created = await this.client.createCompany({\n name: companyName,\n ...(isDomain\n ? { domainName: { primaryLinkUrl: companyName, primaryLinkLabel: companyName } }\n : {}),\n });\n logInfo('twenty:resolveCompanyId', `Created company \"${companyName}\" in Twenty`, {\n id: created.id,\n });\n return created.id;\n } catch (error) {\n logWarn(\n 'twenty:resolveCompanyId',\n `Failed to resolve company \"${companyName}\" — person will be created without company link`,\n { error: error instanceof Error ? error.message : String(error) }\n );\n return undefined;\n }\n }\n}\n","/** Hunter adapter. Bridges HunterClient to MCP Provider interface.\n * Constraint: No direct API calls. Delegates to @maestro/integrations client.\n * Capabilities: find_companies (discover), find_people (domain-search),\n * enrich_email (email-finder), verify_email (email-verifier). */\n\nimport { logError } from '@maestro/logging';\nimport { HunterClient } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CompanyFinder,\n PeopleFinder,\n EmailEnricher,\n EmailVerifier,\n CreditBalance,\n CompanyQuery,\n CompanyResult,\n PeopleQuery,\n PersonResult,\n ContactInput,\n EnrichEmailResult,\n VerificationResult,\n} from '../types.js';\n\n// ─── Adapter ─────────────────────────────────────────────\n\nexport class HunterAdapter\n implements Provider, CompanyFinder, PeopleFinder, EmailEnricher, EmailVerifier\n{\n readonly name = 'hunter';\n readonly capabilities: Capability[] = [\n 'find_companies',\n 'find_people',\n 'enrich_email',\n 'verify_email',\n ];\n readonly notes =\n 'Best for: domain-based email discovery, email finding by name+company, email verification. Free discovery and email count endpoints.';\n private readonly client: HunterClient;\n\n constructor(apiKey: string) {\n this.client = new HunterClient(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n try {\n await this.client.getAccount();\n return true;\n } catch (error) {\n logError(\n 'hunter:checkCredentials',\n error instanceof Error ? error : new Error(String(error))\n );\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n try {\n const account = await this.client.getAccount();\n const searches = account.data.requests.searches;\n return {\n remaining: searches.available - searches.used,\n unit: 'searches',\n provider: this.name,\n };\n } catch (error) {\n logError('hunter.checkCredits', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── CompanyFinder ──────────────────────────────────────\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n try {\n const response = await this.client.discover({\n ...(query.icp_text && { query: query.icp_text }),\n ...(query.country && {\n headquarters_location: { include: [{ country: query.country }] },\n }),\n ...(query.min_employees != null &&\n query.max_employees != null && {\n headcount: [mapHeadcountRange(query.min_employees, query.max_employees)],\n }),\n limit: Math.min(query.limit ?? 25, 100),\n offset: query.offset ?? 0,\n });\n\n return response.data.map((company) => ({\n domain: company.domain,\n name: company.organization,\n sources: [this.name],\n }));\n } catch (error) {\n logError('hunter:findCompanies', error instanceof Error ? error : new Error(String(error)));\n return [];\n }\n }\n\n // ─── PeopleFinder ───────────────────────────────────────\n\n async findPeople(query: PeopleQuery): Promise<PersonResult[]> {\n try {\n const response = await this.client.domainSearch({\n ...(query.company_domain && { domain: query.company_domain }),\n ...(query.company_name && { company: query.company_name }),\n ...(query.seniority?.length && { seniority: query.seniority.join(',') }),\n limit: Math.min(query.limit ?? 10, 100),\n offset: query.offset ?? 0,\n });\n\n return response.data.emails\n .filter((e) => e.first_name || e.last_name)\n .map((email) => ({\n first_name: email.first_name ?? '',\n last_name: email.last_name ?? '',\n email: email.value,\n job_title: email.position ?? undefined,\n company: response.data.organization ?? undefined,\n company_domain: response.data.domain ?? undefined,\n linkedin_url: email.linkedin ?? undefined,\n phone: email.phone_number ?? undefined,\n seniority: email.seniority ?? undefined,\n department: email.department ?? undefined,\n sources: [this.name],\n }));\n } catch (error) {\n logError('hunter:findPeople', error instanceof Error ? error : new Error(String(error)));\n return [];\n }\n }\n\n // ─── EmailEnricher ──────────────────────────────────────\n\n async enrichEmail(contact: ContactInput): Promise<EnrichEmailResult | null> {\n try {\n const response = await this.client.emailFinder({\n first_name: contact.first_name,\n last_name: contact.last_name,\n ...(contact.company_domain && { domain: contact.company_domain }),\n ...(contact.company && { company: contact.company }),\n });\n\n if (!response.data.email) return null;\n\n return {\n email: response.data.email,\n quality: response.data.verification?.status ?? undefined,\n provider: this.name,\n };\n } catch (error) {\n logError('hunter:enrichEmail', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n // ─── EmailVerifier ──────────────────────────────────────\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n const response = await this.client.verifyEmail(email);\n const d = response.data;\n\n return {\n email: d.email,\n valid: d.status === 'valid',\n status: mapVerificationStatus(d.status),\n provider: this.name,\n };\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\n/** Map min/max employees to Hunter headcount range enum. */\nfunction mapHeadcountRange(min: number, max: number): string {\n if (max <= 10) return '1-10';\n if (max <= 50) return '11-50';\n if (max <= 200) return '51-200';\n if (max <= 500) return '201-500';\n if (max <= 1000) return '501-1000';\n if (max <= 5000) return '1001-5000';\n if (max <= 10000) return '5001-10000';\n return '10001+';\n}\n\n/** Map Hunter verification status to MCP verification status. */\nfunction mapVerificationStatus(\n status: string\n): 'deliverable' | 'catch_all_safe' | 'catch_all_not_safe' | 'undeliverable' | 'unknown' {\n switch (status) {\n case 'valid':\n return 'deliverable';\n case 'accept_all':\n return 'catch_all_safe';\n case 'invalid':\n case 'disposable':\n return 'undeliverable';\n case 'webmail':\n return 'catch_all_not_safe';\n default:\n return 'unknown';\n }\n}\n","/** ZeroBounce MCP adapter. Wraps @maestro/integrations ZeroBounceAdapter for email verification.\n * Constraint: Thin wrapper only — all logic lives in the integration client. */\n\nimport { ZeroBounceAdapter } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider, CreditBalance, EmailVerifier, VerificationResult } from '../types.js';\n\n// ─── Status Mapping ─────────────────────────────────────\n\nfunction mapStatus(\n status: 'valid' | 'catch_all' | 'invalid' | 'unknown'\n): VerificationResult['status'] {\n switch (status) {\n case 'valid':\n return 'deliverable';\n case 'catch_all':\n return 'catch_all_safe';\n case 'invalid':\n return 'undeliverable';\n default:\n return 'unknown';\n }\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class ZeroBounceMcpAdapter implements Provider, EmailVerifier {\n readonly name = 'zerobounce';\n readonly capabilities: Capability[] = ['verify_email'];\n readonly notes = 'Email verification via ZeroBounce. $0.008/email.';\n private client: ZeroBounceAdapter;\n\n constructor(apiKey: string) {\n this.client = new ZeroBounceAdapter(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n return this.client.isConfigured();\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n return null;\n }\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n const result = await this.client.validateEmail(email);\n return {\n email,\n valid: result.valid,\n status: mapStatus(result.status),\n provider: 'zerobounce',\n };\n }\n}\n","/** BounceBan MCP adapter. Wraps @maestro/integrations BouncebanAdapter for deep email verification.\n * Constraint: Thin wrapper only — all logic lives in the integration client. */\n\nimport { BouncebanAdapter } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider, CreditBalance, EmailVerifier, VerificationResult } from '../types.js';\n\n// ─── Status Mapping ─────────────────────────────────────\n\nfunction mapStatus(\n status: 'valid' | 'catch_all' | 'invalid' | 'unknown'\n): VerificationResult['status'] {\n switch (status) {\n case 'valid':\n return 'deliverable';\n case 'catch_all':\n return 'catch_all_not_safe';\n case 'invalid':\n return 'undeliverable';\n default:\n return 'unknown';\n }\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class BounceBanMcpAdapter implements Provider, EmailVerifier {\n readonly name = 'bounceban';\n readonly capabilities: Capability[] = ['verify_email'];\n readonly notes =\n 'Deep email verification via BounceBan. Best for catch-all domains. ~$0.003/email.';\n private client: BouncebanAdapter;\n\n constructor(apiKey: string) {\n this.client = new BouncebanAdapter(apiKey);\n }\n\n async checkCredentials(): Promise<boolean> {\n return this.client.isConfigured();\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n return null;\n }\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n const result = await this.client.validateEmail(email);\n return {\n email,\n valid: result.valid,\n status: mapStatus(result.status),\n provider: 'bounceban',\n };\n }\n}\n","/** Mailin MCP adapter. Wraps @maestro/integrations MailinAdapter for bulk email verification.\n * Constraint: Thin wrapper only — all logic lives in the integration client. */\n\nimport { MailinAdapter } from '@maestro/integrations';\n\nimport type { Capability } from '../../constants.js';\nimport type { Provider, CreditBalance, EmailVerifier, VerificationResult } from '../types.js';\n\n// ─── Status Mapping ─────────────────────────────────────\n\nfunction mapStatus(\n status: 'valid' | 'catch_all' | 'invalid' | 'unknown'\n): VerificationResult['status'] {\n switch (status) {\n case 'valid':\n return 'deliverable';\n case 'catch_all':\n return 'catch_all_safe';\n case 'invalid':\n return 'undeliverable';\n default:\n return 'unknown';\n }\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class MailinMcpAdapter implements Provider, EmailVerifier {\n readonly name = 'mailin';\n readonly capabilities: Capability[] = ['verify_email'];\n readonly notes = 'Bulk email verification via Mailin. Cheapest option ~$0.001/email.';\n private client: MailinAdapter;\n\n constructor(email: string, password: string) {\n this.client = new MailinAdapter({ email, password, deviceName: 'maestro' });\n }\n\n async checkCredentials(): Promise<boolean> {\n return this.client.isConfigured();\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n return null;\n }\n\n async verifyEmail(email: string): Promise<VerificationResult> {\n const result = await this.client.validateEmail(email);\n return {\n email,\n valid: result.valid,\n status: mapStatus(result.status),\n provider: 'mailin',\n };\n }\n}\n","/** ApifyAdapter. Company discovery via Apify actors (Google Maps in v1).\n * Constraint: Direct fetch to Apify API. No @maestro/integrations dependency. */\n\nimport { logError } from '@maestro/logging';\n\nimport type { Capability } from '../../constants.js';\nimport type {\n Provider,\n CreditBalance,\n CompanyFinder,\n CompanyQuery,\n CompanyResult,\n} from '../types.js';\n\n// ─── Constants ──────────────────────────────────────────\n\nconst APIFY_BASE_URL = 'https://api.apify.com/v2';\nconst GOOGLE_MAPS_ACTOR = 'compass~crawler-google-places';\nconst POLL_INTERVAL_MS = 3000;\nconst MAX_POLL_ATTEMPTS = 100; // 5 minutes max at 3s interval\n\n// ─── Google Maps Result Mapping ─────────────────────────\n\ninterface GoogleMapsPlace {\n title?: string;\n website?: string;\n url?: string;\n phone?: string;\n address?: string;\n city?: string;\n state?: string;\n countryCode?: string;\n categoryName?: string;\n totalScore?: number;\n reviewsCount?: number;\n [key: string]: unknown;\n}\n\nfunction extractDomain(url: string | undefined): string {\n if (!url) return '';\n try {\n const parsed = new URL(url.startsWith('http') ? url : `https://${url}`);\n return parsed.hostname.replace(/^www\\./, '');\n } catch {\n return (\n url\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0] ?? ''\n );\n }\n}\n\nfunction mapGoogleMapsResult(place: GoogleMapsPlace): CompanyResult | null {\n const domain = extractDomain(place.website);\n const name = place.title;\n if (!name) return null;\n\n return {\n domain: domain || `no-website-${name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`,\n name,\n description: place.categoryName,\n industry: place.categoryName,\n country: place.countryCode,\n phone: place.phone,\n address: [place.address, place.city, place.state].filter(Boolean).join(', '),\n score: place.totalScore,\n };\n}\n\n// ─── Location Extraction ─────────────────────────────────\n\n/** Extract location from ICP text (e.g. \"Yoga studios in Los Angeles\" → \"Los Angeles\").\n * Matches \"in/near/around {City}[, ST]\" — handles multi-word cities and state abbreviations. */\nfunction extractLocationFromText(text: string | undefined): string | null {\n if (!text) return null;\n // Match: \"in/near/around\" + capitalized words + optional \", STATE\"\n const match = text.match(/\\b(?:in|near|around)\\s+((?:[A-Z][a-zA-Z]+\\s*)+(?:,\\s*[A-Z]{2})?)\\b/);\n return match?.[1]?.trim() ?? null;\n}\n\n// ─── Adapter ────────────────────────────────────────────\n\nexport class ApifyAdapter implements Provider, CompanyFinder {\n name = 'apify';\n capabilities: Capability[] = ['find_companies'];\n notes = 'Google Maps company discovery via Apify. Best for local/physical businesses.';\n\n constructor(private apiKey: string) {}\n\n async checkCredentials(): Promise<boolean> {\n try {\n const res = await fetch(`${APIFY_BASE_URL}/users/me`, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n });\n return res.ok;\n } catch (error) {\n logError('apify:checkCredentials', error instanceof Error ? error : new Error(String(error)));\n return false;\n }\n }\n\n async checkCredits(): Promise<CreditBalance | null> {\n try {\n const res = await fetch(`${APIFY_BASE_URL}/users/me/usage`, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as {\n data?: { usageTotalUsd?: number; planTotalUsd?: number };\n };\n const used = data.data?.usageTotalUsd ?? 0;\n const total = data.data?.planTotalUsd ?? 0;\n return {\n remaining: Math.max(0, total - used),\n unit: 'USD',\n provider: 'apify',\n };\n } catch (error) {\n logError('apify:checkCredits', error instanceof Error ? error : new Error(String(error)));\n return null;\n }\n }\n\n async findCompanies(query: CompanyQuery): Promise<CompanyResult[]> {\n const searchTerms = this.buildSearchTerms(query);\n const limit = query.limit ?? 100;\n\n // Build actor input\n const input: Record<string, unknown> = {\n searchStringsArray: searchTerms,\n maxCrawledPlacesPerSearch: limit,\n language: 'en',\n ...(query.country && { countryCode: query.country.toLowerCase() }),\n };\n\n // Start actor run\n const runRes = await fetch(\n `${APIFY_BASE_URL}/acts/${GOOGLE_MAPS_ACTOR}/runs?token=${this.apiKey}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n }\n );\n\n if (!runRes.ok) {\n const body = await runRes.text();\n throw new Error(`Apify actor start failed (${runRes.status}): ${body}`);\n }\n\n const runData = (await runRes.json()) as { data?: { id?: string; defaultDatasetId?: string } };\n const runId = runData.data?.id;\n if (!runId) throw new Error('Apify actor run did not return a run ID');\n\n // Poll for completion\n const datasetId = await this.pollForCompletion(runId);\n\n // Fetch results\n const itemsRes = await fetch(\n `${APIFY_BASE_URL}/datasets/${datasetId}/items?token=${this.apiKey}&limit=${limit}`\n );\n\n if (!itemsRes.ok) {\n throw new Error(`Apify dataset fetch failed (${itemsRes.status})`);\n }\n\n const items = (await itemsRes.json()) as GoogleMapsPlace[];\n return items.map(mapGoogleMapsResult).filter((c): c is CompanyResult => c !== null);\n }\n\n // ─── Private ────────────────────────────────────────────\n\n private buildSearchTerms(query: CompanyQuery): string[] {\n const terms: string[] = [];\n const location = extractLocationFromText(query.icp_text);\n\n if (query.category) {\n // Append location to category so Google Maps scopes results geographically\n terms.push(location ? `${query.category} ${location}` : query.category);\n }\n\n if (query.icp_text) {\n terms.push(query.icp_text);\n }\n\n if (terms.length === 0) {\n terms.push(location ? `business ${location}` : 'business');\n }\n\n return terms;\n }\n\n private async pollForCompletion(runId: string): Promise<string> {\n for (let i = 0; i < MAX_POLL_ATTEMPTS; i++) {\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n\n const res = await fetch(`${APIFY_BASE_URL}/actor-runs/${runId}?token=${this.apiKey}`);\n if (!res.ok) continue;\n\n const data = (await res.json()) as {\n data?: { status?: string; defaultDatasetId?: string };\n };\n\n const status = data.data?.status;\n if (status === 'SUCCEEDED') {\n const datasetId = data.data?.defaultDatasetId;\n if (!datasetId) throw new Error('Apify run succeeded but no dataset ID');\n return datasetId;\n }\n\n if (status === 'FAILED' || status === 'ABORTED' || status === 'TIMED-OUT') {\n throw new Error(`Apify actor run ${status}`);\n }\n }\n\n throw new Error(\n `Apify actor run did not complete within ${(MAX_POLL_ATTEMPTS * POLL_INTERVAL_MS) / 1000}s`\n );\n }\n}\n","/** Provider factory. Creates and registers adapters based on config.\n * Constraint: Only reads config. No side effects beyond registration. */\n\nimport { logInfo, logWarn } from '@maestro/logging';\n\nimport type { ClientConfig, ProviderConfig } from '../config.js';\nimport type { ProviderRegistry } from './registry.js';\n\nimport {\n BetterContactAdapter,\n BlitzApiAdapter,\n DiscoAdapter,\n ProspeoMcpAdapter,\n PlusVibeAdapter,\n HeyReachAdapter,\n AttioAdapter,\n ApolloAdapter,\n InstantlyAdapter,\n SmartLeadAdapter,\n StoreLeadsAdapter,\n HarvestApiAdapter,\n ExaAdapter,\n LeadMagicAdapter,\n TwentyAdapter,\n HunterAdapter,\n ZeroBounceMcpAdapter,\n BounceBanMcpAdapter,\n MailinMcpAdapter,\n ApifyAdapter,\n} from './adapters/index.js';\n\n// ─── Factory Map ─────────────────────────────────────────\n\nfunction createAdapter(name: string, config: ProviderConfig) {\n switch (name) {\n case 'bettercontact':\n return config.api_key ? new BetterContactAdapter(config.api_key) : null;\n case 'blitz':\n return config.api_key ? new BlitzApiAdapter(config.api_key) : null;\n case 'disco':\n return config.api_key ? new DiscoAdapter(config.api_key) : null;\n case 'prospeo':\n return config.api_key ? new ProspeoMcpAdapter(config.api_key) : null;\n case 'plusvibe':\n return config.api_key ? new PlusVibeAdapter(config.api_key, config.workspace_id ?? '') : null;\n case 'heyreach':\n return config.api_key ? new HeyReachAdapter(config.api_key) : null;\n case 'attio':\n return config.api_key ? new AttioAdapter(config.api_key) : null;\n case 'apollo': {\n if (!config.api_key) return null;\n const anthropicKey =\n process.env.GTM_ANTHROPIC_API_KEY ?? process.env.ANTHROPIC_API_KEY ?? undefined;\n return new ApolloAdapter(config.api_key, anthropicKey);\n }\n case 'instantly':\n return config.api_key ? new InstantlyAdapter(config.api_key) : null;\n case 'smartlead':\n return config.api_key ? new SmartLeadAdapter(config.api_key) : null;\n case 'storeleads':\n return config.api_key ? new StoreLeadsAdapter(config.api_key) : null;\n case 'harvest':\n return config.api_key ? new HarvestApiAdapter(config.api_key) : null;\n case 'exa':\n return config.api_key ? new ExaAdapter(config.api_key) : null;\n case 'leadmagic':\n return config.api_key ? new LeadMagicAdapter(config.api_key) : null;\n case 'twenty':\n return config.api_key && config.base_url\n ? new TwentyAdapter(config.api_key, config.base_url)\n : null;\n case 'hunter':\n return config.api_key ? new HunterAdapter(config.api_key) : null;\n case 'zerobounce':\n return config.api_key ? new ZeroBounceMcpAdapter(config.api_key) : null;\n case 'bounceban':\n return config.api_key ? new BounceBanMcpAdapter(config.api_key) : null;\n case 'mailin':\n return config.api_key && config.workspace_id\n ? new MailinMcpAdapter(config.api_key, config.workspace_id)\n : null;\n case 'apify':\n return config.api_key ? new ApifyAdapter(config.api_key) : null;\n default:\n return null;\n }\n}\n\n// ─── Registration ────────────────────────────────────────\n\nexport function registerProviders(registry: ProviderRegistry, clientConfig: ClientConfig): void {\n registry.deregisterAll();\n\n for (const [name, config] of Object.entries(clientConfig.providers)) {\n const adapter = createAdapter(name, config);\n if (adapter) {\n registry.register(adapter);\n logInfo('provider:register', `Registered ${name}`, {\n capabilities: adapter.capabilities,\n });\n } else {\n logWarn('provider:register', `Could not create adapter for \"${name}\" — skipped`);\n }\n }\n}\n"],"mappings":"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","names":["BASE_URL","REQUEST_TIMEOUT_MS","mapVerificationStatus","mapStatus","mapStatus","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","extractDomain"]}
|