@signaliz/sdk 1.0.37 → 1.0.39

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/README.md CHANGED
@@ -32,6 +32,16 @@ const verified = await signaliz.verifyEmail(found.email!, {
32
32
  skipCache: true,
33
33
  });
34
34
 
35
+ // The SDK waits for long checks by default. For an agent handoff, return early
36
+ // and resume the exact provider run later without duplicate spend.
37
+ const queuedVerification = await signaliz.verifyEmail('jane@example.com', {
38
+ skipCache: true,
39
+ waitForResult: false,
40
+ });
41
+ const resumedVerification = await signaliz.verifyEmail('jane@example.com', {
42
+ verificationRunId: queuedVerification.verificationRunId,
43
+ });
44
+
35
45
  const signals = await signaliz.enrichCompanySignals({
36
46
  companyDomain: 'example.com',
37
47
  researchPrompt: 'expansion priorities',
@@ -70,6 +80,13 @@ const verifiedBatch = await signaliz.verifyEmails(emails, { concurrency: 20 });
70
80
  const foundBatch = await signaliz.findEmails(contacts, { concurrency: 20 });
71
81
  const signalBatch = await signaliz.enrichCompanies(companies, { concurrency: 5 });
72
82
  const copyBatch = await signaliz.createSignalCopyBatch(copyRequests, { concurrency: 5 });
83
+
84
+ // Keep one full result for exact repeats and return duplicateOf references for
85
+ // the rest. This is lossless and avoids multiplying evidence-rich payloads.
86
+ const compactSignals = await signaliz.enrichCompanies(companies, {
87
+ concurrency: 5,
88
+ compactDuplicates: true,
89
+ });
73
90
  ```
74
91
 
75
92
  For an ambiguous submission failure, retry with the same
@@ -81,7 +98,10 @@ callers never need an internal Trigger.dev status URL. The SDK follows the
81
98
  server's adaptive polling hints by default and still honors `pollIntervalMs`
82
99
  when a caller explicitly overrides the cadence.
83
100
  Exact duplicate tasks are single-flighted across each full batch without
84
- changing input order or result cardinality. Find Email and Verify Email batches
101
+ changing input order or result cardinality. Set `compactDuplicates: true` to
102
+ return repeated successful rows as `duplicateOf` references to the zero-based
103
+ canonical input index; the default remains expanded for compatibility. Find Email and Verify Email
104
+ batches
85
105
  larger than 25 use one cache-aware recoverable REST job with 500-row result
86
106
  pages. Uniform Company Signal Enrichment batches larger than 25 use one
87
107
  cache-aware recoverable REST job with 25-row result pages; heterogeneous,
@@ -371,15 +371,33 @@ var Signaliz = class {
371
371
  params.length,
372
372
  startedAt,
373
373
  round,
374
- (item) => normalizeFindEmailResult(item.raw)
374
+ (item) => normalizeFindEmailResult(item.raw),
375
+ options
375
376
  );
376
377
  }
377
378
  async verifyEmail(email, options) {
378
- const data = await this.client.post("api/v1/verify-email", {
379
- email,
379
+ const request = compact({
380
+ email: email || void 0,
381
+ verification_run_id: options?.verificationRunId,
380
382
  skip_cache: options?.skipCache
381
383
  });
382
- return normalizeVerifyEmailResult(email, data);
384
+ let data = await this.client.post("api/v1/verify-email", request);
385
+ if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
386
+ const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
387
+ const startedAt = Date.now();
388
+ while (Date.now() - startedAt < maxWaitMs) {
389
+ if (!await waitForNextSignalPoll(data, options?.pollIntervalMs, startedAt, maxWaitMs)) break;
390
+ data = await this.client.post("api/v1/verify-email", compact({
391
+ email: email || void 0,
392
+ verification_run_id: data.verification_run_id
393
+ }));
394
+ if (!isPendingSignalResponse(data)) break;
395
+ }
396
+ if (isPendingSignalResponse(data)) {
397
+ throw new Error(`Email verification ${data.verification_run_id} did not complete within ${maxWaitMs}ms`);
398
+ }
399
+ }
400
+ return normalizeVerifyEmailResult(email || "", data);
383
401
  }
384
402
  async verifyEmails(emails, options) {
385
403
  validateBatchSize(emails);
@@ -396,7 +414,8 @@ var Signaliz = class {
396
414
  emails.length,
397
415
  startedAt,
398
416
  round,
399
- (item) => normalizeVerifyEmailResult(emails[item.index], item.raw)
417
+ (item) => normalizeVerifyEmailResult(emails[item.index], item.raw),
418
+ options
400
419
  );
401
420
  }
402
421
  async enrichCompanySignals(params) {
@@ -491,13 +510,14 @@ var Signaliz = class {
491
510
  await sleep2(Math.max(1, nextDelayMs));
492
511
  pending = nextPending;
493
512
  }
494
- const succeeded = results.filter((item) => item.success).length;
513
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
514
+ const succeeded = compactedResults.filter((item) => item.success).length;
495
515
  return {
496
516
  total: companies.length,
497
517
  succeeded,
498
518
  failed: companies.length - succeeded,
499
519
  durationMs: Date.now() - startedAt,
500
- results
520
+ results: compactedResults
501
521
  };
502
522
  }
503
523
  async signalToCopy(params) {
@@ -538,13 +558,14 @@ var Signaliz = class {
538
558
  ...uniqueResults[deduplicated.sourceIndexByInput[index]],
539
559
  index
540
560
  }));
541
- const succeeded = results.filter((item) => item.success).length;
561
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
562
+ const succeeded = compactedResults.filter((item) => item.success).length;
542
563
  return {
543
564
  total: requests.length,
544
565
  succeeded,
545
566
  failed: requests.length - succeeded,
546
567
  durationMs: Date.now() - startedAt,
547
- results
568
+ results: compactedResults
548
569
  };
549
570
  }
550
571
  async runSignalCopyBatchChunks(uniqueRequests, options) {
@@ -864,6 +885,10 @@ function normalizeVerifyEmailResult(email, data) {
864
885
  const verified = data.email_verified === true || ["valid", "deliverable"].includes(verificationStatus);
865
886
  return {
866
887
  email: data.email ?? email,
888
+ status: String(data.status || "").toLowerCase() === "processing" ? "processing" : "completed",
889
+ verificationRunId: data.verification_run_id ?? data.run_id,
890
+ retryAfterMs: data.retry_after_ms,
891
+ nextPollAfterSeconds: data.next_poll_after_seconds,
867
892
  isValid: data.is_valid ?? data.valid ?? verified,
868
893
  isDeliverable: data.is_deliverable ?? data.deliverable ?? verified,
869
894
  isCatchAll: data.email_is_catch_all ?? data.is_catch_all ?? data.catch_all ?? data.diagnostics?.is_catch_all ?? false,
@@ -997,7 +1022,7 @@ function dedupeExactBatchItems(items, keyForItem) {
997
1022
  }
998
1023
  return { uniqueItems, sourceIndexByInput };
999
1024
  }
1000
- function finalizeCoreBatch(total, startedAt, round, normalize) {
1025
+ function finalizeCoreBatch(total, startedAt, round, normalize, options) {
1001
1026
  const results = new Array(total);
1002
1027
  for (const item of round) {
1003
1028
  if (!item.success || !item.raw) {
@@ -1014,15 +1039,31 @@ function finalizeCoreBatch(total, startedAt, round, normalize) {
1014
1039
  };
1015
1040
  }
1016
1041
  }
1017
- const succeeded = results.filter((item) => item.success).length;
1042
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
1043
+ const succeeded = compactedResults.filter((item) => item.success).length;
1018
1044
  return {
1019
1045
  total,
1020
1046
  succeeded,
1021
1047
  failed: total - succeeded,
1022
1048
  durationMs: Date.now() - startedAt,
1023
- results
1049
+ results: compactedResults
1024
1050
  };
1025
1051
  }
1052
+ function compactExactDuplicateResults(results, enabled) {
1053
+ if (!enabled) return results;
1054
+ const sourceIndexByRaw = /* @__PURE__ */ new WeakMap();
1055
+ return results.map((item) => {
1056
+ if (!item.success || !item.data || typeof item.data !== "object") return item;
1057
+ const raw = item.data.raw;
1058
+ if (!raw || typeof raw !== "object") return item;
1059
+ const duplicateOf = sourceIndexByRaw.get(raw);
1060
+ if (duplicateOf !== void 0) {
1061
+ return { index: item.index, success: true, duplicateOf };
1062
+ }
1063
+ sourceIndexByRaw.set(raw, item.index);
1064
+ return item;
1065
+ });
1066
+ }
1026
1067
  function signalToCopyRequestBody(params) {
1027
1068
  return compact({
1028
1069
  company_domain: params.companyDomain,
package/dist/index.d.mts CHANGED
@@ -11,12 +11,16 @@ interface BatchOptions {
11
11
  concurrency?: number;
12
12
  /** Stable key for safely retrying an ambiguous recoverable batch submission. */
13
13
  idempotencyKey?: string;
14
+ /** Return exact repeated successes as duplicateOf references. Defaults to false. */
15
+ compactDuplicates?: boolean;
14
16
  }
15
17
  interface BatchItemResult<T> {
16
18
  index: number;
17
19
  success: boolean;
18
20
  data?: T;
19
21
  error?: string;
22
+ /** Zero-based input index containing the full result for this exact duplicate. */
23
+ duplicateOf?: number;
20
24
  }
21
25
  interface BatchResult<T> {
22
26
  total: number;
@@ -65,6 +69,12 @@ interface FindEmailResult {
65
69
  }
66
70
  interface VerifyEmailResult {
67
71
  email: string;
72
+ /** Execution state. Processing results are never send-safe. */
73
+ status: 'processing' | 'completed';
74
+ /** Durable Trigger run id for resuming a long verification. */
75
+ verificationRunId?: string;
76
+ retryAfterMs?: number;
77
+ nextPollAfterSeconds?: number;
68
78
  isValid: boolean;
69
79
  isDeliverable: boolean;
70
80
  isCatchAll: boolean;
@@ -76,6 +86,14 @@ interface VerifyEmailResult {
76
86
  interface VerifyEmailOptions {
77
87
  /** Bypass cached verification data for a fresh-provider quality check. */
78
88
  skipCache?: boolean;
89
+ /** Resume an existing long verification without another provider call. */
90
+ verificationRunId?: string;
91
+ /** Wait for a processing verification to finish. Defaults to true. */
92
+ waitForResult?: boolean;
93
+ /** Maximum time to wait for a processing verification. Defaults to 10 minutes. */
94
+ maxWaitMs?: number;
95
+ /** Override the server-provided polling delay. */
96
+ pollIntervalMs?: number;
79
97
  }
80
98
  interface VerifyEmailBatchOptions extends BatchOptions, VerifyEmailOptions {
81
99
  }
@@ -200,7 +218,7 @@ declare class Signaliz {
200
218
  constructor(config: SignalizConfig);
201
219
  findEmail(params: FindEmailParams): Promise<FindEmailResult>;
202
220
  findEmails(params: FindEmailParams[], options?: BatchOptions): Promise<BatchResult<FindEmailResult>>;
203
- verifyEmail(email: string, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
221
+ verifyEmail(email: string | undefined, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
204
222
  verifyEmails(emails: string[], options?: VerifyEmailBatchOptions): Promise<BatchResult<VerifyEmailResult>>;
205
223
  enrichCompanySignals(params: CompanySignalEnrichmentParams): Promise<CompanySignalEnrichmentResult>;
206
224
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
package/dist/index.d.ts CHANGED
@@ -11,12 +11,16 @@ interface BatchOptions {
11
11
  concurrency?: number;
12
12
  /** Stable key for safely retrying an ambiguous recoverable batch submission. */
13
13
  idempotencyKey?: string;
14
+ /** Return exact repeated successes as duplicateOf references. Defaults to false. */
15
+ compactDuplicates?: boolean;
14
16
  }
15
17
  interface BatchItemResult<T> {
16
18
  index: number;
17
19
  success: boolean;
18
20
  data?: T;
19
21
  error?: string;
22
+ /** Zero-based input index containing the full result for this exact duplicate. */
23
+ duplicateOf?: number;
20
24
  }
21
25
  interface BatchResult<T> {
22
26
  total: number;
@@ -65,6 +69,12 @@ interface FindEmailResult {
65
69
  }
66
70
  interface VerifyEmailResult {
67
71
  email: string;
72
+ /** Execution state. Processing results are never send-safe. */
73
+ status: 'processing' | 'completed';
74
+ /** Durable Trigger run id for resuming a long verification. */
75
+ verificationRunId?: string;
76
+ retryAfterMs?: number;
77
+ nextPollAfterSeconds?: number;
68
78
  isValid: boolean;
69
79
  isDeliverable: boolean;
70
80
  isCatchAll: boolean;
@@ -76,6 +86,14 @@ interface VerifyEmailResult {
76
86
  interface VerifyEmailOptions {
77
87
  /** Bypass cached verification data for a fresh-provider quality check. */
78
88
  skipCache?: boolean;
89
+ /** Resume an existing long verification without another provider call. */
90
+ verificationRunId?: string;
91
+ /** Wait for a processing verification to finish. Defaults to true. */
92
+ waitForResult?: boolean;
93
+ /** Maximum time to wait for a processing verification. Defaults to 10 minutes. */
94
+ maxWaitMs?: number;
95
+ /** Override the server-provided polling delay. */
96
+ pollIntervalMs?: number;
79
97
  }
80
98
  interface VerifyEmailBatchOptions extends BatchOptions, VerifyEmailOptions {
81
99
  }
@@ -200,7 +218,7 @@ declare class Signaliz {
200
218
  constructor(config: SignalizConfig);
201
219
  findEmail(params: FindEmailParams): Promise<FindEmailResult>;
202
220
  findEmails(params: FindEmailParams[], options?: BatchOptions): Promise<BatchResult<FindEmailResult>>;
203
- verifyEmail(email: string, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
221
+ verifyEmail(email: string | undefined, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
204
222
  verifyEmails(emails: string[], options?: VerifyEmailBatchOptions): Promise<BatchResult<VerifyEmailResult>>;
205
223
  enrichCompanySignals(params: CompanySignalEnrichmentParams): Promise<CompanySignalEnrichmentResult>;
206
224
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
package/dist/index.js CHANGED
@@ -398,15 +398,33 @@ var Signaliz = class {
398
398
  params.length,
399
399
  startedAt,
400
400
  round,
401
- (item) => normalizeFindEmailResult(item.raw)
401
+ (item) => normalizeFindEmailResult(item.raw),
402
+ options
402
403
  );
403
404
  }
404
405
  async verifyEmail(email, options) {
405
- const data = await this.client.post("api/v1/verify-email", {
406
- email,
406
+ const request = compact({
407
+ email: email || void 0,
408
+ verification_run_id: options?.verificationRunId,
407
409
  skip_cache: options?.skipCache
408
410
  });
409
- return normalizeVerifyEmailResult(email, data);
411
+ let data = await this.client.post("api/v1/verify-email", request);
412
+ if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
413
+ const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
414
+ const startedAt = Date.now();
415
+ while (Date.now() - startedAt < maxWaitMs) {
416
+ if (!await waitForNextSignalPoll(data, options?.pollIntervalMs, startedAt, maxWaitMs)) break;
417
+ data = await this.client.post("api/v1/verify-email", compact({
418
+ email: email || void 0,
419
+ verification_run_id: data.verification_run_id
420
+ }));
421
+ if (!isPendingSignalResponse(data)) break;
422
+ }
423
+ if (isPendingSignalResponse(data)) {
424
+ throw new Error(`Email verification ${data.verification_run_id} did not complete within ${maxWaitMs}ms`);
425
+ }
426
+ }
427
+ return normalizeVerifyEmailResult(email || "", data);
410
428
  }
411
429
  async verifyEmails(emails, options) {
412
430
  validateBatchSize(emails);
@@ -423,7 +441,8 @@ var Signaliz = class {
423
441
  emails.length,
424
442
  startedAt,
425
443
  round,
426
- (item) => normalizeVerifyEmailResult(emails[item.index], item.raw)
444
+ (item) => normalizeVerifyEmailResult(emails[item.index], item.raw),
445
+ options
427
446
  );
428
447
  }
429
448
  async enrichCompanySignals(params) {
@@ -518,13 +537,14 @@ var Signaliz = class {
518
537
  await sleep2(Math.max(1, nextDelayMs));
519
538
  pending = nextPending;
520
539
  }
521
- const succeeded = results.filter((item) => item.success).length;
540
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
541
+ const succeeded = compactedResults.filter((item) => item.success).length;
522
542
  return {
523
543
  total: companies.length,
524
544
  succeeded,
525
545
  failed: companies.length - succeeded,
526
546
  durationMs: Date.now() - startedAt,
527
- results
547
+ results: compactedResults
528
548
  };
529
549
  }
530
550
  async signalToCopy(params) {
@@ -565,13 +585,14 @@ var Signaliz = class {
565
585
  ...uniqueResults[deduplicated.sourceIndexByInput[index]],
566
586
  index
567
587
  }));
568
- const succeeded = results.filter((item) => item.success).length;
588
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
589
+ const succeeded = compactedResults.filter((item) => item.success).length;
569
590
  return {
570
591
  total: requests.length,
571
592
  succeeded,
572
593
  failed: requests.length - succeeded,
573
594
  durationMs: Date.now() - startedAt,
574
- results
595
+ results: compactedResults
575
596
  };
576
597
  }
577
598
  async runSignalCopyBatchChunks(uniqueRequests, options) {
@@ -891,6 +912,10 @@ function normalizeVerifyEmailResult(email, data) {
891
912
  const verified = data.email_verified === true || ["valid", "deliverable"].includes(verificationStatus);
892
913
  return {
893
914
  email: data.email ?? email,
915
+ status: String(data.status || "").toLowerCase() === "processing" ? "processing" : "completed",
916
+ verificationRunId: data.verification_run_id ?? data.run_id,
917
+ retryAfterMs: data.retry_after_ms,
918
+ nextPollAfterSeconds: data.next_poll_after_seconds,
894
919
  isValid: data.is_valid ?? data.valid ?? verified,
895
920
  isDeliverable: data.is_deliverable ?? data.deliverable ?? verified,
896
921
  isCatchAll: data.email_is_catch_all ?? data.is_catch_all ?? data.catch_all ?? data.diagnostics?.is_catch_all ?? false,
@@ -1024,7 +1049,7 @@ function dedupeExactBatchItems(items, keyForItem) {
1024
1049
  }
1025
1050
  return { uniqueItems, sourceIndexByInput };
1026
1051
  }
1027
- function finalizeCoreBatch(total, startedAt, round, normalize) {
1052
+ function finalizeCoreBatch(total, startedAt, round, normalize, options) {
1028
1053
  const results = new Array(total);
1029
1054
  for (const item of round) {
1030
1055
  if (!item.success || !item.raw) {
@@ -1041,15 +1066,31 @@ function finalizeCoreBatch(total, startedAt, round, normalize) {
1041
1066
  };
1042
1067
  }
1043
1068
  }
1044
- const succeeded = results.filter((item) => item.success).length;
1069
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
1070
+ const succeeded = compactedResults.filter((item) => item.success).length;
1045
1071
  return {
1046
1072
  total,
1047
1073
  succeeded,
1048
1074
  failed: total - succeeded,
1049
1075
  durationMs: Date.now() - startedAt,
1050
- results
1076
+ results: compactedResults
1051
1077
  };
1052
1078
  }
1079
+ function compactExactDuplicateResults(results, enabled) {
1080
+ if (!enabled) return results;
1081
+ const sourceIndexByRaw = /* @__PURE__ */ new WeakMap();
1082
+ return results.map((item) => {
1083
+ if (!item.success || !item.data || typeof item.data !== "object") return item;
1084
+ const raw = item.data.raw;
1085
+ if (!raw || typeof raw !== "object") return item;
1086
+ const duplicateOf = sourceIndexByRaw.get(raw);
1087
+ if (duplicateOf !== void 0) {
1088
+ return { index: item.index, success: true, duplicateOf };
1089
+ }
1090
+ sourceIndexByRaw.set(raw, item.index);
1091
+ return item;
1092
+ });
1093
+ }
1053
1094
  function signalToCopyRequestBody(params) {
1054
1095
  return compact({
1055
1096
  company_domain: params.companyDomain,
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Signaliz,
3
3
  SignalizError
4
- } from "./chunk-WHD7INKU.mjs";
4
+ } from "./chunk-UVW5N4LW.mjs";
5
5
  export {
6
6
  Signaliz,
7
7
  SignalizError
@@ -402,15 +402,33 @@ var Signaliz = class {
402
402
  params.length,
403
403
  startedAt,
404
404
  round,
405
- (item) => normalizeFindEmailResult(item.raw)
405
+ (item) => normalizeFindEmailResult(item.raw),
406
+ options
406
407
  );
407
408
  }
408
409
  async verifyEmail(email, options) {
409
- const data = await this.client.post("api/v1/verify-email", {
410
- email,
410
+ const request = compact({
411
+ email: email || void 0,
412
+ verification_run_id: options?.verificationRunId,
411
413
  skip_cache: options?.skipCache
412
414
  });
413
- return normalizeVerifyEmailResult(email, data);
415
+ let data = await this.client.post("api/v1/verify-email", request);
416
+ if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
417
+ const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
418
+ const startedAt = Date.now();
419
+ while (Date.now() - startedAt < maxWaitMs) {
420
+ if (!await waitForNextSignalPoll(data, options?.pollIntervalMs, startedAt, maxWaitMs)) break;
421
+ data = await this.client.post("api/v1/verify-email", compact({
422
+ email: email || void 0,
423
+ verification_run_id: data.verification_run_id
424
+ }));
425
+ if (!isPendingSignalResponse(data)) break;
426
+ }
427
+ if (isPendingSignalResponse(data)) {
428
+ throw new Error(`Email verification ${data.verification_run_id} did not complete within ${maxWaitMs}ms`);
429
+ }
430
+ }
431
+ return normalizeVerifyEmailResult(email || "", data);
414
432
  }
415
433
  async verifyEmails(emails, options) {
416
434
  validateBatchSize(emails);
@@ -427,7 +445,8 @@ var Signaliz = class {
427
445
  emails.length,
428
446
  startedAt,
429
447
  round,
430
- (item) => normalizeVerifyEmailResult(emails[item.index], item.raw)
448
+ (item) => normalizeVerifyEmailResult(emails[item.index], item.raw),
449
+ options
431
450
  );
432
451
  }
433
452
  async enrichCompanySignals(params) {
@@ -522,13 +541,14 @@ var Signaliz = class {
522
541
  await sleep2(Math.max(1, nextDelayMs));
523
542
  pending = nextPending;
524
543
  }
525
- const succeeded = results.filter((item) => item.success).length;
544
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
545
+ const succeeded = compactedResults.filter((item) => item.success).length;
526
546
  return {
527
547
  total: companies.length,
528
548
  succeeded,
529
549
  failed: companies.length - succeeded,
530
550
  durationMs: Date.now() - startedAt,
531
- results
551
+ results: compactedResults
532
552
  };
533
553
  }
534
554
  async signalToCopy(params) {
@@ -569,13 +589,14 @@ var Signaliz = class {
569
589
  ...uniqueResults[deduplicated.sourceIndexByInput[index]],
570
590
  index
571
591
  }));
572
- const succeeded = results.filter((item) => item.success).length;
592
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
593
+ const succeeded = compactedResults.filter((item) => item.success).length;
573
594
  return {
574
595
  total: requests.length,
575
596
  succeeded,
576
597
  failed: requests.length - succeeded,
577
598
  durationMs: Date.now() - startedAt,
578
- results
599
+ results: compactedResults
579
600
  };
580
601
  }
581
602
  async runSignalCopyBatchChunks(uniqueRequests, options) {
@@ -895,6 +916,10 @@ function normalizeVerifyEmailResult(email, data) {
895
916
  const verified = data.email_verified === true || ["valid", "deliverable"].includes(verificationStatus);
896
917
  return {
897
918
  email: data.email ?? email,
919
+ status: String(data.status || "").toLowerCase() === "processing" ? "processing" : "completed",
920
+ verificationRunId: data.verification_run_id ?? data.run_id,
921
+ retryAfterMs: data.retry_after_ms,
922
+ nextPollAfterSeconds: data.next_poll_after_seconds,
898
923
  isValid: data.is_valid ?? data.valid ?? verified,
899
924
  isDeliverable: data.is_deliverable ?? data.deliverable ?? verified,
900
925
  isCatchAll: data.email_is_catch_all ?? data.is_catch_all ?? data.catch_all ?? data.diagnostics?.is_catch_all ?? false,
@@ -1028,7 +1053,7 @@ function dedupeExactBatchItems(items, keyForItem) {
1028
1053
  }
1029
1054
  return { uniqueItems, sourceIndexByInput };
1030
1055
  }
1031
- function finalizeCoreBatch(total, startedAt, round, normalize) {
1056
+ function finalizeCoreBatch(total, startedAt, round, normalize, options) {
1032
1057
  const results = new Array(total);
1033
1058
  for (const item of round) {
1034
1059
  if (!item.success || !item.raw) {
@@ -1045,15 +1070,31 @@ function finalizeCoreBatch(total, startedAt, round, normalize) {
1045
1070
  };
1046
1071
  }
1047
1072
  }
1048
- const succeeded = results.filter((item) => item.success).length;
1073
+ const compactedResults = compactExactDuplicateResults(results, options?.compactDuplicates === true);
1074
+ const succeeded = compactedResults.filter((item) => item.success).length;
1049
1075
  return {
1050
1076
  total,
1051
1077
  succeeded,
1052
1078
  failed: total - succeeded,
1053
1079
  durationMs: Date.now() - startedAt,
1054
- results
1080
+ results: compactedResults
1055
1081
  };
1056
1082
  }
1083
+ function compactExactDuplicateResults(results, enabled) {
1084
+ if (!enabled) return results;
1085
+ const sourceIndexByRaw = /* @__PURE__ */ new WeakMap();
1086
+ return results.map((item) => {
1087
+ if (!item.success || !item.data || typeof item.data !== "object") return item;
1088
+ const raw = item.data.raw;
1089
+ if (!raw || typeof raw !== "object") return item;
1090
+ const duplicateOf = sourceIndexByRaw.get(raw);
1091
+ if (duplicateOf !== void 0) {
1092
+ return { index: item.index, success: true, duplicateOf };
1093
+ }
1094
+ sourceIndexByRaw.set(raw, item.index);
1095
+ return item;
1096
+ });
1097
+ }
1057
1098
  function signalToCopyRequestBody(params) {
1058
1099
  return compact({
1059
1100
  company_domain: params.companyDomain,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Signaliz
4
- } from "./chunk-WHD7INKU.mjs";
4
+ } from "./chunk-UVW5N4LW.mjs";
5
5
 
6
6
  // src/mcp-config.ts
7
7
  import * as fs from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/sdk",
3
- "version": "1.0.37",
3
+ "version": "1.0.39",
4
4
  "description": "Signaliz SDK for Find Email, Verify Email, Company Signal Enrichment, and Signal to Copy AI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",