@coldiq/mcp 0.1.0 → 0.1.1

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/test-web-live.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { initClient } from './src/client.js'
2
2
  import { searchWebHandler } from './src/tools/search-web.js'
3
3
 
4
- const API_URL = 'https://api.coldiq.com'
5
- const API_KEY = 'ciq_test_3797d4ddc5542ceb'
4
+ const API_URL = process.env.COLDIQ_API_URL ?? 'https://api.coldiq.com'
5
+ const API_KEY = process.env.COLDIQ_API_KEY
6
+ if (!API_KEY) { console.error('COLDIQ_API_KEY env var is required'); process.exit(1) }
6
7
 
7
8
  initClient(API_URL, API_KEY)
8
9
 
@@ -62,7 +62,7 @@ describe('client', () => {
62
62
 
63
63
  expect(result.ok).toBe(false)
64
64
  expect(result.status).toBe(0)
65
- expect((result.data as Record<string, unknown>).error).toBe('Network timeout')
65
+ expect((result.data as Record<string, unknown>).error).toBe('Network error')
66
66
  })
67
67
 
68
68
  it('returns parsed JSON on success', async () => {
@@ -1,6 +1,233 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
2
  import { initClient } from '../src/client.js'
3
3
  import { executeWithFallback } from '../src/executor.js'
4
+ import * as registry from '../src/registry.js'
5
+ import type { ProviderEntry } from '../src/registry.js'
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Helpers for synthetic provider injection
9
+ // ---------------------------------------------------------------------------
10
+
11
+ function makeProvider(overrides: Partial<ProviderEntry> & { id: string }): ProviderEntry {
12
+ return {
13
+ endpoint: '/test',
14
+ method: 'POST',
15
+ priority: 1,
16
+ mapParams: () => ({ body: {} }),
17
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
18
+ ...overrides,
19
+ }
20
+ }
21
+
22
+ function stubProviders(providers: ProviderEntry[]) {
23
+ return vi.spyOn(registry, 'getProviders').mockReturnValueOnce(providers)
24
+ }
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // Exception safety — mapParams / hasResult / postFilter / isApplicable
28
+ // ---------------------------------------------------------------------------
29
+
30
+ describe('executor exception safety', () => {
31
+ const originalFetch = globalThis.fetch
32
+
33
+ beforeEach(() => {
34
+ initClient('http://test-api.local', 'test-key-123')
35
+ })
36
+
37
+ afterEach(() => {
38
+ globalThis.fetch = originalFetch
39
+ vi.restoreAllMocks()
40
+ })
41
+
42
+ it('mapParams throws → skips to next provider', async () => {
43
+ stubProviders([
44
+ makeProvider({
45
+ id: 'bad',
46
+ mapParams: () => { throw new Error('mapParams explosion') },
47
+ hasResult: () => false,
48
+ }),
49
+ makeProvider({
50
+ id: 'good',
51
+ mapParams: () => ({ body: {} }),
52
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
53
+ }),
54
+ ])
55
+
56
+ globalThis.fetch = vi.fn(async () =>
57
+ new Response(JSON.stringify({ ok: true }), { status: 200 }),
58
+ ) as typeof fetch
59
+
60
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
61
+
62
+ expect('data' in result).toBe(true)
63
+ if ('data' in result) {
64
+ expect(result._meta.provider).toBe('good')
65
+ }
66
+ })
67
+
68
+ it('hasResult throws → treated as no result, next provider tried', async () => {
69
+ stubProviders([
70
+ makeProvider({
71
+ id: 'exploding-has-result',
72
+ mapParams: () => ({ body: {} }),
73
+ hasResult: () => { throw new Error('hasResult explosion') },
74
+ }),
75
+ makeProvider({
76
+ id: 'safe',
77
+ mapParams: () => ({ body: {} }),
78
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
79
+ }),
80
+ ])
81
+
82
+ globalThis.fetch = vi.fn(async () =>
83
+ new Response(JSON.stringify({ ok: true }), { status: 200 }),
84
+ ) as typeof fetch
85
+
86
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
87
+
88
+ expect('data' in result).toBe(true)
89
+ if ('data' in result) {
90
+ expect(result._meta.provider).toBe('safe')
91
+ }
92
+ })
93
+
94
+ it('postFilter throws → falls back to raw payload, success path continues', async () => {
95
+ stubProviders([
96
+ makeProvider({
97
+ id: 'exploding-post-filter',
98
+ mapParams: () => ({ body: {} }),
99
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
100
+ postFilter: () => { throw new Error('postFilter explosion') },
101
+ }),
102
+ ])
103
+
104
+ globalThis.fetch = vi.fn(async () =>
105
+ new Response(JSON.stringify({ ok: true }), { status: 200 }),
106
+ ) as typeof fetch
107
+
108
+ // postFilter throws → raw payload is used → hasResult(raw) should still return true
109
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
110
+
111
+ expect('data' in result).toBe(true)
112
+ if ('data' in result) {
113
+ expect(result._meta.provider).toBe('exploding-post-filter')
114
+ }
115
+ })
116
+
117
+ it('isApplicable=false → provider skipped and NOT recorded in providers_tried', async () => {
118
+ stubProviders([
119
+ makeProvider({
120
+ id: 'skipped',
121
+ isApplicable: () => false,
122
+ hasResult: () => false,
123
+ }),
124
+ ])
125
+
126
+ globalThis.fetch = vi.fn(async () =>
127
+ new Response(JSON.stringify({ ok: false }), { status: 200 }),
128
+ ) as typeof fetch
129
+
130
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
131
+
132
+ expect('error' in result).toBe(true)
133
+ if ('error' in result) {
134
+ // Skipped providers do not appear in providers_tried
135
+ expect(result.providers_tried.length).toBe(0)
136
+ }
137
+ })
138
+
139
+ it('isApplicable throws → provider skipped gracefully', async () => {
140
+ stubProviders([
141
+ makeProvider({
142
+ id: 'throwing-applicable',
143
+ isApplicable: () => { throw new Error('isApplicable explosion') },
144
+ hasResult: () => false,
145
+ }),
146
+ makeProvider({
147
+ id: 'safe',
148
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
149
+ }),
150
+ ])
151
+
152
+ globalThis.fetch = vi.fn(async () =>
153
+ new Response(JSON.stringify({ ok: true }), { status: 200 }),
154
+ ) as typeof fetch
155
+
156
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
157
+
158
+ expect('data' in result).toBe(true)
159
+ if ('data' in result) {
160
+ expect(result._meta.provider).toBe('safe')
161
+ }
162
+ })
163
+
164
+ it('all providers fail → providers_tried uses provider_N keys (not internal ids)', async () => {
165
+ stubProviders([
166
+ makeProvider({ id: 'alpha', hasResult: () => false }),
167
+ makeProvider({ id: 'beta', hasResult: () => false }),
168
+ ])
169
+
170
+ globalThis.fetch = vi.fn(async () =>
171
+ new Response(JSON.stringify({ ok: false }), { status: 200 }),
172
+ ) as typeof fetch
173
+
174
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
175
+
176
+ expect('error' in result).toBe(true)
177
+ if ('error' in result) {
178
+ expect(result.providers_tried).toHaveLength(2)
179
+ expect(result.providers_tried[0].provider).toBe('provider_1')
180
+ expect(result.providers_tried[1].provider).toBe('provider_2')
181
+ expect('id' in result.providers_tried[0]).toBe(false)
182
+ }
183
+ })
184
+
185
+ it('async create returns 4xx → recorded as failure, next provider tried', async () => {
186
+ stubProviders([
187
+ makeProvider({
188
+ id: 'async-fail',
189
+ hasResult: () => false,
190
+ async: {
191
+ extractId: () => 'job-1',
192
+ pollEndpoint: (id) => `/poll/${id}`,
193
+ pollIntervalMs: 10,
194
+ timeoutMs: 50,
195
+ isComplete: () => true,
196
+ },
197
+ }),
198
+ makeProvider({
199
+ id: 'sync-success',
200
+ hasResult: (data) => (data as Record<string, unknown>).ok === true,
201
+ }),
202
+ ])
203
+
204
+ let callCount = 0
205
+ globalThis.fetch = vi.fn(async (url: string | URL | Request) => {
206
+ callCount++
207
+ const u = url.toString()
208
+ if (u.includes('/test') && !u.includes('/poll/')) {
209
+ if (callCount === 1) {
210
+ // async-fail create — returns 4xx so executor skips polling
211
+ return new Response(JSON.stringify({ error: 'quota exceeded' }), { status: 429 })
212
+ }
213
+ // sync-success
214
+ return new Response(JSON.stringify({ ok: true }), { status: 200 })
215
+ }
216
+ return new Response(JSON.stringify({}), { status: 200 })
217
+ }) as typeof fetch
218
+
219
+ const result = await executeWithFallback('enrich_company', { domain: 'coldiq.com' })
220
+
221
+ expect('data' in result).toBe(true)
222
+ if ('data' in result) {
223
+ expect(result._meta.provider).toBe('sync-success')
224
+ }
225
+ })
226
+ })
227
+
228
+ // ---------------------------------------------------------------------------
229
+ // postFilter integration (existing tests)
230
+ // ---------------------------------------------------------------------------
4
231
 
5
232
  describe('executor postFilter integration', () => {
6
233
  const originalFetch = globalThis.fetch
@@ -384,53 +384,6 @@ describe('registry', () => {
384
384
  expect(sumble.isApplicable!({ countries: ['FR'] })).toBe(false)
385
385
  })
386
386
 
387
- it('Wiza creates a prospect list with [{v}] filter shape, translates ISO codes, and has async config', () => {
388
- const providers = getProviders('search_companies')
389
- const wiza = providers.find((p) => p.id === 'wiza')!
390
- const result = wiza.mapParams({
391
- industries: ['SaaS'],
392
- countries: ['FR'],
393
- min_founded_year: 2015,
394
- limit: 25,
395
- })
396
- expect(result.body).toEqual({
397
- list: { name: 'mcp-search-companies', max_profiles: 25 },
398
- filters: {
399
- company_industry: [{ v: 'SaaS' }],
400
- company_location: [{ v: 'France' }],
401
- year_founded_start: [{ v: '2015' }],
402
- },
403
- enrichment_level: 'none',
404
- })
405
- expect(wiza.async).toBeDefined()
406
- expect(wiza.async!.pollEndpoint('123')).toBe('/wiza/lists/123')
407
- expect(wiza.async!.extractId({ data: { id: 123 } })).toBe('123')
408
- })
409
-
410
- it('Wiza isComplete accepts both finished and completed terminal states', () => {
411
- const providers = getProviders('search_companies')
412
- const wiza = providers.find((p) => p.id === 'wiza')!
413
- expect(wiza.async!.isComplete({ data: { status: 'finished' } })).toBe(true)
414
- expect(wiza.async!.isComplete({ data: { status: 'completed' } })).toBe(true)
415
- expect(wiza.async!.isComplete({ data: { status: 'failed' } })).toBe(true)
416
- expect(wiza.async!.isComplete({ data: { status: 'scraping' } })).toBe(false)
417
- expect(wiza.async!.isComplete({ data: { status: 'queued' } })).toBe(false)
418
- })
419
-
420
- it('Wiza extractId throws when no list id is present', () => {
421
- const providers = getProviders('search_companies')
422
- const wiza = providers.find((p) => p.id === 'wiza')!
423
- expect(() => wiza.async!.extractId({})).toThrow('Wiza response has no list id')
424
- expect(() => wiza.async!.extractId({ data: {} })).toThrow('Wiza response has no list id')
425
- })
426
-
427
- it('Wiza hasResult checks data.stats.people > 0', () => {
428
- const providers = getProviders('search_companies')
429
- const wiza = providers.find((p) => p.id === 'wiza')!
430
- expect(wiza.hasResult({ data: { status: 'finished', stats: { people: 10 } } })).toBe(true)
431
- expect(wiza.hasResult({ data: { status: 'finished', stats: { people: 0 } } })).toBe(false)
432
- expect(wiza.hasResult({ data: { status: 'finished' } })).toBe(false)
433
- })
434
387
 
435
388
  it('LimaData prospect filter maps employees to company_headcount filter_type', () => {
436
389
  const providers = getProviders('search_companies')
@@ -464,14 +417,13 @@ describe('registry', () => {
464
417
  expect(ld.isApplicable!({ linkedin_search_url: 'https://...' })).toBe(true)
465
418
  })
466
419
 
467
- it('search_companies has 18 providers in priority order', () => {
420
+ it('search_companies has 17 providers in priority order', () => {
468
421
  const providers = getProviders('search_companies')
469
422
  expect(providers.map((p) => p.id)).toEqual([
470
423
  'companyenrich',
471
424
  'fullenrich',
472
425
  'pdl',
473
426
  'theirstack',
474
- 'wiza',
475
427
  'signalbase',
476
428
  'blitzapi',
477
429
  'apollo',
@@ -1176,16 +1128,6 @@ describe('registry', () => {
1176
1128
  expect(ts.isApplicable!({ countries: ['FR'] })).toBe(false)
1177
1129
  })
1178
1130
 
1179
- it('Wiza isApplicable: fires for min/max_founded_year and funding filters', () => {
1180
- const wiza = getProviders('search_companies').find((p) => p.id === 'wiza')!
1181
- expect(wiza.isApplicable!({})).toBe(false)
1182
- expect(wiza.isApplicable!({ keywords: ['x'] })).toBe(false)
1183
- expect(wiza.isApplicable!({ min_founded_year: 2015 })).toBe(true)
1184
- expect(wiza.isApplicable!({ max_founded_year: 2020 })).toBe(true)
1185
- expect(wiza.isApplicable!({ funding_stages: ['seed'] })).toBe(true)
1186
- expect(wiza.isApplicable!({ min_funding_amount: 500_000 })).toBe(true)
1187
- expect(wiza.isApplicable!({ max_funding_amount: 10_000_000 })).toBe(true)
1188
- })
1189
1131
 
1190
1132
  it('Apollo postFilter strips accounts key entirely', () => {
1191
1133
  const apollo = getProviders('search_companies').find((p) => p.id === 'apollo')!
@@ -1327,24 +1269,6 @@ describe('registry', () => {
1327
1269
  expect((result.body as Record<string, unknown>).exclude).toEqual({ domains: ['a.com'] })
1328
1270
  })
1329
1271
 
1330
- it('Wiza mapParams adds funding_stage, funding_min, funding_max in [{v}] shape', () => {
1331
- const wiza = getProviders('search_companies').find((p) => p.id === 'wiza')!
1332
- const result = wiza.mapParams({
1333
- funding_stages: ['seed', 'series_a'],
1334
- min_funding_amount: 500_000,
1335
- max_funding_amount: 20_000_000,
1336
- limit: 25,
1337
- })
1338
- expect(result.body).toEqual({
1339
- list: { name: 'mcp-search-companies', max_profiles: 25 },
1340
- filters: {
1341
- funding_stage: [{ v: 'seed' }, { v: 'series_a' }],
1342
- funding_min: [{ v: '500000' }],
1343
- funding_max: [{ v: '20000000' }],
1344
- },
1345
- enrichment_level: 'none',
1346
- })
1347
- })
1348
1272
 
1349
1273
  it('LimaData passes has_jobs: true when is_hiring is true', () => {
1350
1274
  const ld = getProviders('search_companies').find((p) => p.id === 'limadata')!
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
2
  import { initClient } from '../../src/client.js'
3
- import { findEmailHandler as enrichEmailHandler } from '../../src/tools/find-email.js'
3
+ import { findEmailHandler } from '../../src/tools/find-email.js'
4
4
 
5
5
  describe('find_email handler (waterfall)', () => {
6
6
  const originalFetch = globalThis.fetch
@@ -18,7 +18,7 @@ describe('find_email handler (waterfall)', () => {
18
18
  new Response(JSON.stringify({ email: 'michel@coldiq.com' }), { status: 200 })
19
19
  ) as typeof fetch
20
20
 
21
- const result = await enrichEmailHandler({
21
+ const result = await findEmailHandler({
22
22
  first_name: 'Michel',
23
23
  last_name: 'Lieben',
24
24
  domain: 'coldiq.com',
@@ -41,7 +41,7 @@ describe('find_email handler (waterfall)', () => {
41
41
  return new Response(JSON.stringify({ email: 'michel@coldiq.com' }), { status: 200 })
42
42
  }) as typeof fetch
43
43
 
44
- const result = await enrichEmailHandler({
44
+ const result = await findEmailHandler({
45
45
  first_name: 'Michel',
46
46
  last_name: 'Lieben',
47
47
  domain: 'coldiq.com',
@@ -65,7 +65,7 @@ describe('find_email handler (waterfall)', () => {
65
65
  )
66
66
  }) as typeof fetch
67
67
 
68
- const result = await enrichEmailHandler({
68
+ const result = await findEmailHandler({
69
69
  first_name: 'Michel',
70
70
  last_name: 'Lieben',
71
71
  domain: 'coldiq.com',
@@ -80,7 +80,7 @@ describe('find_email handler (waterfall)', () => {
80
80
  new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })
81
81
  ) as typeof fetch
82
82
 
83
- const result = await enrichEmailHandler({
83
+ const result = await findEmailHandler({
84
84
  first_name: 'Unknown',
85
85
  last_name: 'Person',
86
86
  domain: 'unknown.xyz',
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
2
  import { initClient } from '../../src/client.js'
3
- import { findEmailsHandler as enrichEmailsHandler } from '../../src/tools/find-emails.js'
3
+ import { findEmailsHandler } from '../../src/tools/find-emails.js'
4
4
 
5
5
  describe('find_emails handler (bulk)', () => {
6
6
  const originalFetch = globalThis.fetch
@@ -32,7 +32,7 @@ describe('find_emails handler (bulk)', () => {
32
32
  return new Response(JSON.stringify({ error: 'unexpected call' }), { status: 500 })
33
33
  }) as typeof fetch
34
34
 
35
- const result = await enrichEmailsHandler({
35
+ const result = await findEmailsHandler({
36
36
  people: [
37
37
  { id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'example.com' },
38
38
  { id: 'p2', first_name: 'Bob', last_name: 'Jones', domain: 'example.com' },
@@ -71,7 +71,7 @@ describe('find_emails handler (bulk)', () => {
71
71
  return new Response(JSON.stringify({ error: 'unexpected' }), { status: 500 })
72
72
  }) as typeof fetch
73
73
 
74
- const result = await enrichEmailsHandler({
74
+ const result = await findEmailsHandler({
75
75
  people: [{ id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'example.com' }],
76
76
  })
77
77
 
@@ -98,7 +98,7 @@ describe('find_emails handler (bulk)', () => {
98
98
  return new Response(JSON.stringify({ error: 'unexpected' }), { status: 500 })
99
99
  }) as typeof fetch
100
100
 
101
- const result = await enrichEmailsHandler({
101
+ const result = await findEmailsHandler({
102
102
  people: [{ id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'example.com' }],
103
103
  })
104
104
 
@@ -111,7 +111,7 @@ describe('find_emails handler (bulk)', () => {
111
111
  new Response(JSON.stringify({ error: true }), { status: 200 }),
112
112
  ) as typeof fetch
113
113
 
114
- const result = await enrichEmailsHandler({
114
+ const result = await findEmailsHandler({
115
115
  people: [{ id: 'p1', first_name: 'Unknown', last_name: 'Person', domain: 'nowhere.xyz' }],
116
116
  })
117
117
 
@@ -153,7 +153,7 @@ describe('find_emails handler (bulk)', () => {
153
153
  return new Response(JSON.stringify({ error: 'unexpected' }), { status: 500 })
154
154
  }) as typeof fetch
155
155
 
156
- const result = await enrichEmailsHandler({
156
+ const result = await findEmailsHandler({
157
157
  people: [
158
158
  { id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'a.com' },
159
159
  { id: 'p2', first_name: 'Bob', last_name: 'Jones', domain: 'b.com' },
@@ -187,7 +187,7 @@ describe('find_emails handler (bulk)', () => {
187
187
  return new Response(JSON.stringify({ email: null }), { status: 200 })
188
188
  }) as typeof fetch
189
189
 
190
- await enrichEmailsHandler({
190
+ await findEmailsHandler({
191
191
  people: [{ id: 'p1', linkedin_url: 'https://linkedin.com/in/michel-lieben' }],
192
192
  })
193
193
 
@@ -196,13 +196,13 @@ describe('find_emails handler (bulk)', () => {
196
196
  expect(body.data[0].first_name).toBeUndefined()
197
197
  })
198
198
 
199
- it('uses FullEnrich batch for Prospeo misses and matches by index', async () => {
199
+ it('uses FullEnrich batch for Prospeo misses and matches by custom_id', async () => {
200
200
  vi.useFakeTimers()
201
201
 
202
- let feCreateCalled = false
202
+ let feCreateBody: unknown
203
203
  let fePollCalled = false
204
204
 
205
- globalThis.fetch = vi.fn(async (url: string | URL | Request) => {
205
+ globalThis.fetch = vi.fn(async (url: string | URL | Request, init?: RequestInit) => {
206
206
  const u = url.toString()
207
207
 
208
208
  if (u.includes('/prospeo/bulk-enrich-person')) {
@@ -217,19 +217,19 @@ describe('find_emails handler (bulk)', () => {
217
217
  fePollCalled = true
218
218
  return new Response(JSON.stringify({
219
219
  status: 'DONE',
220
- data: [{ emails: ['alice@example.com'] }],
220
+ data: [{ custom_id: 'p1', emails: ['alice@example.com'] }],
221
221
  }), { status: 200 })
222
222
  }
223
223
 
224
224
  if (u.includes('/fullenrich/contact/enrich/bulk')) {
225
- feCreateCalled = true
225
+ feCreateBody = JSON.parse(init?.body as string)
226
226
  return new Response(JSON.stringify({ enrichment_id: 'abc-fe-123' }), { status: 200 })
227
227
  }
228
228
 
229
229
  return new Response(JSON.stringify({ error: 'unexpected' }), { status: 500 })
230
230
  }) as typeof fetch
231
231
 
232
- const handlerPromise = enrichEmailsHandler({
232
+ const handlerPromise = findEmailsHandler({
233
233
  people: [{ id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'example.com' }],
234
234
  })
235
235
 
@@ -237,8 +237,9 @@ describe('find_emails handler (bulk)', () => {
237
237
  const result = await handlerPromise
238
238
  vi.useRealTimers()
239
239
 
240
- expect(feCreateCalled).toBe(true)
241
240
  expect(fePollCalled).toBe(true)
241
+ const body = feCreateBody as { data: Array<Record<string, unknown>> }
242
+ expect(body.data[0].custom_id).toBe('p1')
242
243
  const parsed = JSON.parse(result.content[0].text)
243
244
  expect(parsed.data.results[0]).toEqual({ id: 'p1', email: 'alice@example.com', provider: 'fullenrich' })
244
245
  })
@@ -255,7 +256,7 @@ describe('find_emails handler (bulk)', () => {
255
256
  return new Response(JSON.stringify({ error: 'unexpected' }), { status: 500 })
256
257
  }) as typeof fetch
257
258
 
258
- const result = await enrichEmailsHandler({
259
+ const result = await findEmailsHandler({
259
260
  people: [{ id: 'p1', first_name: 'Alice', last_name: 'Smith', domain: 'example.com' }],
260
261
  })
261
262
 
@@ -43,10 +43,10 @@ describe('find_people handler', () => {
43
43
  const lf = providers.find((p) => p.id === 'leadsfactory')!
44
44
  const originalTimeout = lf.async!.timeoutMs
45
45
  const originalInterval = lf.async!.pollIntervalMs
46
- lf.async!.timeoutMs = 100
47
- lf.async!.pollIntervalMs = 20
48
46
 
49
47
  try {
48
+ lf.async!.timeoutMs = 100
49
+ lf.async!.pollIntervalMs = 20
50
50
  const result = await findPeopleHandler({
51
51
  company_domains: ['coldiq.com'],
52
52
  job_titles: ['CEO'],
@@ -96,10 +96,10 @@ describe('find_people handler', () => {
96
96
  const lf = providers.find((p) => p.id === 'leadsfactory')!
97
97
  const originalTimeout = lf.async!.timeoutMs
98
98
  const originalInterval = lf.async!.pollIntervalMs
99
- lf.async!.timeoutMs = 500
100
- lf.async!.pollIntervalMs = 20
101
99
 
102
100
  try {
101
+ lf.async!.timeoutMs = 500
102
+ lf.async!.pollIntervalMs = 20
103
103
  const result = await findPeopleHandler({
104
104
  company_domains: ['coldiq.com'],
105
105
  job_titles: ['CEO'],
@@ -150,10 +150,10 @@ describe('find_people handler', () => {
150
150
  const lf = providers.find((p) => p.id === 'leadsfactory')!
151
151
  const originalTimeout = lf.async!.timeoutMs
152
152
  const originalInterval = lf.async!.pollIntervalMs
153
- lf.async!.timeoutMs = 500
154
- lf.async!.pollIntervalMs = 20
155
153
 
156
154
  try {
155
+ lf.async!.timeoutMs = 500
156
+ lf.async!.pollIntervalMs = 20
157
157
  const result = await findPeopleHandler({
158
158
  company_domains: ['coldiq.com', 'folk.app'],
159
159
  job_titles: ['CEO'],
@@ -203,10 +203,10 @@ describe('find_people handler', () => {
203
203
  const lf = providers.find((p) => p.id === 'leadsfactory')!
204
204
  const originalTimeout = lf.async!.timeoutMs
205
205
  const originalInterval = lf.async!.pollIntervalMs
206
- lf.async!.timeoutMs = 500
207
- lf.async!.pollIntervalMs = 20
208
206
 
209
207
  try {
208
+ lf.async!.timeoutMs = 500
209
+ lf.async!.pollIntervalMs = 20
210
210
  const result = await findPeopleHandler({
211
211
  company_linkedin_urls: ['https://linkedin.com/company/coldiq', 'https://linkedin.com/company/folk'],
212
212
  job_titles: ['CEO'],
@@ -249,10 +249,10 @@ describe('find_people handler', () => {
249
249
  const lf = providers.find((p) => p.id === 'leadsfactory')!
250
250
  const originalTimeout = lf.async!.timeoutMs
251
251
  const originalInterval = lf.async!.pollIntervalMs
252
- lf.async!.timeoutMs = 500
253
- lf.async!.pollIntervalMs = 20
254
252
 
255
253
  try {
254
+ lf.async!.timeoutMs = 500
255
+ lf.async!.pollIntervalMs = 20
256
256
  await findPeopleHandler({
257
257
  company_linkedin_urls: ['https://linkedin.com/company/coldiq', 'https://linkedin.com/company/folk'],
258
258
  company_domains: ['coldiq.com', 'folk.app'],
@@ -295,10 +295,10 @@ describe('find_people handler', () => {
295
295
  const lf = providers.find((p) => p.id === 'leadsfactory')!
296
296
  const originalTimeout = lf.async!.timeoutMs
297
297
  const originalInterval = lf.async!.pollIntervalMs
298
- lf.async!.timeoutMs = 500
299
- lf.async!.pollIntervalMs = 20
300
298
 
301
299
  try {
300
+ lf.async!.timeoutMs = 500
301
+ lf.async!.pollIntervalMs = 20
302
302
  await findPeopleHandler({
303
303
  company_domains: ['coldiq.com'],
304
304
  job_titles: ['CEO', 'VP of Sales'],
@@ -49,10 +49,10 @@ describe('search_places handler', () => {
49
49
  const providers = getProviders('search_places')
50
50
  const gm = providers.find((p) => p.id === 'google_maps')!
51
51
  const orig = { t: gm.async!.timeoutMs, i: gm.async!.pollIntervalMs }
52
- gm.async!.timeoutMs = 500
53
- gm.async!.pollIntervalMs = 20
54
52
 
55
53
  try {
54
+ gm.async!.timeoutMs = 500
55
+ gm.async!.pollIntervalMs = 20
56
56
  const result = await searchPlacesHandler({ query: 'café', country: 'FR', limit: 5 })
57
57
 
58
58
  expect(result.isError).toBeFalsy()
@@ -84,10 +84,10 @@ describe('search_places handler', () => {
84
84
  const providers = getProviders('search_places')
85
85
  const gm = providers.find((p) => p.id === 'google_maps')!
86
86
  const orig = { t: gm.async!.timeoutMs, i: gm.async!.pollIntervalMs }
87
- gm.async!.timeoutMs = 500
88
- gm.async!.pollIntervalMs = 20
89
87
 
90
88
  try {
89
+ gm.async!.timeoutMs = 500
90
+ gm.async!.pollIntervalMs = 20
91
91
  const result = await searchPlacesHandler({ query: 'coffee', country: 'US', provider: 'google_maps', limit: 5 })
92
92
 
93
93
  expect(result.isError).toBeFalsy()
@@ -33,10 +33,10 @@ describe('search_reddit handler', () => {
33
33
  const providers = getProviders('search_reddit')
34
34
  const reddit = providers.find((p) => p.id === 'reddit')!
35
35
  const orig = { t: reddit.async!.timeoutMs, i: reddit.async!.pollIntervalMs }
36
- reddit.async!.timeoutMs = 500
37
- reddit.async!.pollIntervalMs = 20
38
36
 
39
37
  try {
38
+ reddit.async!.timeoutMs = 500
39
+ reddit.async!.pollIntervalMs = 20
40
40
  const result = await searchRedditHandler({ start_urls: ['https://www.reddit.com/r/sales/'], query: 'best CRM for startups', limit: 5 })
41
41
 
42
42
  expect(result.isError).toBeFalsy()
@@ -72,10 +72,10 @@ describe('search_reddit handler', () => {
72
72
  const providers = getProviders('search_reddit')
73
73
  const reddit = providers.find((p) => p.id === 'reddit')!
74
74
  const orig = { t: reddit.async!.timeoutMs, i: reddit.async!.pollIntervalMs }
75
- reddit.async!.timeoutMs = 500
76
- reddit.async!.pollIntervalMs = 20
77
75
 
78
76
  try {
77
+ reddit.async!.timeoutMs = 500
78
+ reddit.async!.pollIntervalMs = 20
79
79
  await searchRedditHandler({
80
80
  start_urls: ['https://www.reddit.com/r/entrepreneur/'],
81
81
  limit: 5,
@@ -108,10 +108,10 @@ describe('search_reddit handler', () => {
108
108
  const providers = getProviders('search_reddit')
109
109
  const reddit = providers.find((p) => p.id === 'reddit')!
110
110
  const orig = { t: reddit.async!.timeoutMs, i: reddit.async!.pollIntervalMs }
111
- reddit.async!.timeoutMs = 100
112
- reddit.async!.pollIntervalMs = 20
113
111
 
114
112
  try {
113
+ reddit.async!.timeoutMs = 100
114
+ reddit.async!.pollIntervalMs = 20
115
115
  const result = await searchRedditHandler({ start_urls: ['https://www.reddit.com/r/sales/'], query: 'cold email', limit: 5 })
116
116
 
117
117
  expect(result.isError).toBe(true)