@signaliz/sdk 1.0.31 → 1.0.33

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
@@ -77,10 +77,13 @@ resumes long-running research through the same `/company-signals` endpoint;
77
77
  callers never need an internal Trigger.dev status URL. The SDK follows the
78
78
  server's adaptive polling hints by default and still honors `pollIntervalMs`
79
79
  when a caller explicitly overrides the cadence.
80
- All four products are transported in 25-row REST chunks. Exact duplicate tasks
81
- are single-flighted across the full batch before chunking, without changing
82
- input order or result cardinality. Signal to Copy also shares company research
83
- across copy recipients.
80
+ Exact duplicate tasks are single-flighted across each full batch without
81
+ changing input order or result cardinality. Verify Email batches larger than 25
82
+ use one cache-aware recoverable REST job with 500-row result pages; Find Email
83
+ and Company Signal Enrichment use 25-row REST chunks. Signal to Copy batches
84
+ larger than 25 use one recoverable REST job when they can reuse available signal
85
+ data; fresh or deep-search requests keep the 25-row path. Signal to Copy also
86
+ shares company research across copy recipients.
84
87
 
85
88
  Company Signal Enrichment defaults `online` and `enableDeepSearch` to `true`
86
89
  unless the caller explicitly disables them. Signal to Copy AI returns three
@@ -518,6 +518,24 @@ var Signaliz = class {
518
518
  poll_interval_ms: params.pollIntervalMs
519
519
  }));
520
520
  const uniqueRequests = deduplicated.uniqueItems;
521
+ const canUseRecoverableAvailableDataJob = uniqueRequests.length > 25 && uniqueRequests.every(
522
+ (params) => params.waitForResult !== false && params.skipCache !== true && params.enableDeepSearch !== true && params.maxWaitMs === void 0 && params.pollIntervalMs === void 0
523
+ );
524
+ const uniqueResults = canUseRecoverableAvailableDataJob ? await this.runAvailableSignalCopyBatchJob(uniqueRequests) : await this.runSignalCopyBatchChunks(uniqueRequests, options);
525
+ const results = requests.map((_, index) => ({
526
+ ...uniqueResults[deduplicated.sourceIndexByInput[index]],
527
+ index
528
+ }));
529
+ const succeeded = results.filter((item) => item.success).length;
530
+ return {
531
+ total: requests.length,
532
+ succeeded,
533
+ failed: requests.length - succeeded,
534
+ durationMs: Date.now() - startedAt,
535
+ results
536
+ };
537
+ }
538
+ async runSignalCopyBatchChunks(uniqueRequests, options) {
521
539
  const chunks = [];
522
540
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
523
541
  chunks.push({ offset, requests: uniqueRequests.slice(offset, offset + 25) });
@@ -545,18 +563,74 @@ var Signaliz = class {
545
563
  uniqueResults[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
546
564
  }
547
565
  }
548
- const results = requests.map((_, index) => ({
549
- ...uniqueResults[deduplicated.sourceIndexByInput[index]],
550
- index
551
- }));
552
- const succeeded = results.filter((item) => item.success).length;
553
- return {
554
- total: requests.length,
555
- succeeded,
556
- failed: requests.length - succeeded,
557
- durationMs: Date.now() - startedAt,
558
- results
559
- };
566
+ return uniqueResults;
567
+ }
568
+ async runAvailableSignalCopyBatchJob(requests) {
569
+ const rows = await this.runRecoverableCoreBatchJob(
570
+ "api/v1/signal-to-copy",
571
+ requests.map(signalToCopyRequestBody),
572
+ "Signal to Copy"
573
+ );
574
+ const results = new Array(requests.length);
575
+ for (const row of rows) {
576
+ const index = Number(row.index);
577
+ results[index] = recoverableJobRowFailed(row) ? { index, success: false, error: row.error || row.message || "Signal to Copy failed" } : { index, success: true, data: normalizeSignalToCopyResult(row) };
578
+ }
579
+ return results;
580
+ }
581
+ async runRecoverableCoreBatchJob(path, requests, label) {
582
+ const startedAt = Date.now();
583
+ const maxWaitMs = 20 * 6e4;
584
+ const submission = await this.client.post(path, {
585
+ requests,
586
+ idempotency_key: newBatchIdempotencyKey(label)
587
+ });
588
+ const jobId = String(submission.job_id || "").trim();
589
+ if (!jobId) throw new Error(`${label} batch did not return a recoverable job_id`);
590
+ let status = await this.client.post(path, {
591
+ job_id: jobId,
592
+ page: 1,
593
+ page_size: 500
594
+ });
595
+ while (!["completed", "partial", "failed"].includes(String(status.status || "").toLowerCase())) {
596
+ if (Date.now() - startedAt >= maxWaitMs) {
597
+ throw new Error(`${label} batch ${jobId} did not complete within ${maxWaitMs}ms`);
598
+ }
599
+ const retryAfterMs = Number(status.next_poll_after_seconds || 2) * 1e3;
600
+ await sleep2(Math.min(Math.max(250, retryAfterMs), maxWaitMs - (Date.now() - startedAt)));
601
+ status = await this.client.post(path, {
602
+ job_id: jobId,
603
+ page: 1,
604
+ page_size: 500
605
+ });
606
+ }
607
+ const totalPages = Math.max(1, Number(status.total_pages || 1));
608
+ const pages = [Array.isArray(status.results) ? status.results : []];
609
+ if (totalPages > 1) {
610
+ const remainingPages = await Promise.all(Array.from(
611
+ { length: totalPages - 1 },
612
+ (_, index) => this.client.post(path, {
613
+ job_id: jobId,
614
+ page: index + 2,
615
+ page_size: 500
616
+ })
617
+ ));
618
+ for (const page of remainingPages) pages.push(Array.isArray(page.results) ? page.results : []);
619
+ }
620
+ const rows = pages.flat();
621
+ if (rows.length !== requests.length) {
622
+ throw new Error(`${label} batch returned ${rows.length} results for ${requests.length} requests`);
623
+ }
624
+ const seen = /* @__PURE__ */ new Set();
625
+ for (const row of rows) {
626
+ const index = Number(row.index);
627
+ if (!Number.isInteger(index) || index < 0 || index >= requests.length || seen.has(index)) {
628
+ throw new Error(`${label} batch returned an invalid result index`);
629
+ }
630
+ seen.add(index);
631
+ }
632
+ if (seen.size !== requests.length) throw new Error(`${label} batch returned incomplete indexed results`);
633
+ return rows;
560
634
  }
561
635
  async runSignalCopyBatchChunk(requests, concurrency) {
562
636
  const startedAt = Date.now();
@@ -624,6 +698,23 @@ var Signaliz = class {
624
698
  const { serverConcurrency, chunkConcurrency } = batchConcurrencyPlan(options);
625
699
  const deduplicated = dedupeExactBatchItems(tasks, (task) => JSON.stringify(task.request));
626
700
  const uniqueTasks = deduplicated.uniqueItems;
701
+ if (path === "api/v1/verify-email" && uniqueTasks.length > 25) {
702
+ const rows = await this.runRecoverableCoreBatchJob(
703
+ path,
704
+ uniqueTasks.map((task) => task.request),
705
+ "Verify Email"
706
+ );
707
+ const uniqueResults2 = rows.map((raw) => ({
708
+ index: uniqueTasks[Number(raw.index)].index,
709
+ success: !recoverableJobRowFailed(raw),
710
+ raw,
711
+ error: recoverableJobRowFailed(raw) ? raw.error || raw._error || raw.message || raw.failure_reason || "Verify Email item failed" : void 0
712
+ }));
713
+ return tasks.map((task, index) => ({
714
+ ...uniqueResults2[deduplicated.sourceIndexByInput[index]],
715
+ index: task.index
716
+ }));
717
+ }
627
718
  const chunks = [];
628
719
  for (let offset = 0; offset < uniqueTasks.length; offset += 25) {
629
720
  chunks.push({ offset, tasks: uniqueTasks.slice(offset, offset + 25) });
@@ -681,6 +772,13 @@ var Signaliz = class {
681
772
  };
682
773
  }
683
774
  };
775
+ function recoverableJobRowFailed(row) {
776
+ return row.success === false || String(row._status || "").toLowerCase() === "failed";
777
+ }
778
+ function newBatchIdempotencyKey(label) {
779
+ const nonce = globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random().toString(16).slice(2)}`;
780
+ return `signaliz-${label.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${nonce}`;
781
+ }
684
782
  function compact(input) {
685
783
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
686
784
  }
package/dist/index.d.mts CHANGED
@@ -203,6 +203,9 @@ declare class Signaliz {
203
203
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
204
204
  signalToCopy(params: SignalToCopyParams): Promise<SignalToCopyResult>;
205
205
  createSignalCopyBatch(requests: SignalToCopyParams[], options?: BatchOptions): Promise<BatchResult<SignalToCopyResult>>;
206
+ private runSignalCopyBatchChunks;
207
+ private runAvailableSignalCopyBatchJob;
208
+ private runRecoverableCoreBatchJob;
206
209
  private runSignalCopyBatchChunk;
207
210
  private runCoreBatchRound;
208
211
  listTools(): Promise<MCPToolInfo[]>;
package/dist/index.d.ts CHANGED
@@ -203,6 +203,9 @@ declare class Signaliz {
203
203
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
204
204
  signalToCopy(params: SignalToCopyParams): Promise<SignalToCopyResult>;
205
205
  createSignalCopyBatch(requests: SignalToCopyParams[], options?: BatchOptions): Promise<BatchResult<SignalToCopyResult>>;
206
+ private runSignalCopyBatchChunks;
207
+ private runAvailableSignalCopyBatchJob;
208
+ private runRecoverableCoreBatchJob;
206
209
  private runSignalCopyBatchChunk;
207
210
  private runCoreBatchRound;
208
211
  listTools(): Promise<MCPToolInfo[]>;
package/dist/index.js CHANGED
@@ -545,6 +545,24 @@ var Signaliz = class {
545
545
  poll_interval_ms: params.pollIntervalMs
546
546
  }));
547
547
  const uniqueRequests = deduplicated.uniqueItems;
548
+ const canUseRecoverableAvailableDataJob = uniqueRequests.length > 25 && uniqueRequests.every(
549
+ (params) => params.waitForResult !== false && params.skipCache !== true && params.enableDeepSearch !== true && params.maxWaitMs === void 0 && params.pollIntervalMs === void 0
550
+ );
551
+ const uniqueResults = canUseRecoverableAvailableDataJob ? await this.runAvailableSignalCopyBatchJob(uniqueRequests) : await this.runSignalCopyBatchChunks(uniqueRequests, options);
552
+ const results = requests.map((_, index) => ({
553
+ ...uniqueResults[deduplicated.sourceIndexByInput[index]],
554
+ index
555
+ }));
556
+ const succeeded = results.filter((item) => item.success).length;
557
+ return {
558
+ total: requests.length,
559
+ succeeded,
560
+ failed: requests.length - succeeded,
561
+ durationMs: Date.now() - startedAt,
562
+ results
563
+ };
564
+ }
565
+ async runSignalCopyBatchChunks(uniqueRequests, options) {
548
566
  const chunks = [];
549
567
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
550
568
  chunks.push({ offset, requests: uniqueRequests.slice(offset, offset + 25) });
@@ -572,18 +590,74 @@ var Signaliz = class {
572
590
  uniqueResults[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
573
591
  }
574
592
  }
575
- const results = requests.map((_, index) => ({
576
- ...uniqueResults[deduplicated.sourceIndexByInput[index]],
577
- index
578
- }));
579
- const succeeded = results.filter((item) => item.success).length;
580
- return {
581
- total: requests.length,
582
- succeeded,
583
- failed: requests.length - succeeded,
584
- durationMs: Date.now() - startedAt,
585
- results
586
- };
593
+ return uniqueResults;
594
+ }
595
+ async runAvailableSignalCopyBatchJob(requests) {
596
+ const rows = await this.runRecoverableCoreBatchJob(
597
+ "api/v1/signal-to-copy",
598
+ requests.map(signalToCopyRequestBody),
599
+ "Signal to Copy"
600
+ );
601
+ const results = new Array(requests.length);
602
+ for (const row of rows) {
603
+ const index = Number(row.index);
604
+ results[index] = recoverableJobRowFailed(row) ? { index, success: false, error: row.error || row.message || "Signal to Copy failed" } : { index, success: true, data: normalizeSignalToCopyResult(row) };
605
+ }
606
+ return results;
607
+ }
608
+ async runRecoverableCoreBatchJob(path, requests, label) {
609
+ const startedAt = Date.now();
610
+ const maxWaitMs = 20 * 6e4;
611
+ const submission = await this.client.post(path, {
612
+ requests,
613
+ idempotency_key: newBatchIdempotencyKey(label)
614
+ });
615
+ const jobId = String(submission.job_id || "").trim();
616
+ if (!jobId) throw new Error(`${label} batch did not return a recoverable job_id`);
617
+ let status = await this.client.post(path, {
618
+ job_id: jobId,
619
+ page: 1,
620
+ page_size: 500
621
+ });
622
+ while (!["completed", "partial", "failed"].includes(String(status.status || "").toLowerCase())) {
623
+ if (Date.now() - startedAt >= maxWaitMs) {
624
+ throw new Error(`${label} batch ${jobId} did not complete within ${maxWaitMs}ms`);
625
+ }
626
+ const retryAfterMs = Number(status.next_poll_after_seconds || 2) * 1e3;
627
+ await sleep2(Math.min(Math.max(250, retryAfterMs), maxWaitMs - (Date.now() - startedAt)));
628
+ status = await this.client.post(path, {
629
+ job_id: jobId,
630
+ page: 1,
631
+ page_size: 500
632
+ });
633
+ }
634
+ const totalPages = Math.max(1, Number(status.total_pages || 1));
635
+ const pages = [Array.isArray(status.results) ? status.results : []];
636
+ if (totalPages > 1) {
637
+ const remainingPages = await Promise.all(Array.from(
638
+ { length: totalPages - 1 },
639
+ (_, index) => this.client.post(path, {
640
+ job_id: jobId,
641
+ page: index + 2,
642
+ page_size: 500
643
+ })
644
+ ));
645
+ for (const page of remainingPages) pages.push(Array.isArray(page.results) ? page.results : []);
646
+ }
647
+ const rows = pages.flat();
648
+ if (rows.length !== requests.length) {
649
+ throw new Error(`${label} batch returned ${rows.length} results for ${requests.length} requests`);
650
+ }
651
+ const seen = /* @__PURE__ */ new Set();
652
+ for (const row of rows) {
653
+ const index = Number(row.index);
654
+ if (!Number.isInteger(index) || index < 0 || index >= requests.length || seen.has(index)) {
655
+ throw new Error(`${label} batch returned an invalid result index`);
656
+ }
657
+ seen.add(index);
658
+ }
659
+ if (seen.size !== requests.length) throw new Error(`${label} batch returned incomplete indexed results`);
660
+ return rows;
587
661
  }
588
662
  async runSignalCopyBatchChunk(requests, concurrency) {
589
663
  const startedAt = Date.now();
@@ -651,6 +725,23 @@ var Signaliz = class {
651
725
  const { serverConcurrency, chunkConcurrency } = batchConcurrencyPlan(options);
652
726
  const deduplicated = dedupeExactBatchItems(tasks, (task) => JSON.stringify(task.request));
653
727
  const uniqueTasks = deduplicated.uniqueItems;
728
+ if (path === "api/v1/verify-email" && uniqueTasks.length > 25) {
729
+ const rows = await this.runRecoverableCoreBatchJob(
730
+ path,
731
+ uniqueTasks.map((task) => task.request),
732
+ "Verify Email"
733
+ );
734
+ const uniqueResults2 = rows.map((raw) => ({
735
+ index: uniqueTasks[Number(raw.index)].index,
736
+ success: !recoverableJobRowFailed(raw),
737
+ raw,
738
+ error: recoverableJobRowFailed(raw) ? raw.error || raw._error || raw.message || raw.failure_reason || "Verify Email item failed" : void 0
739
+ }));
740
+ return tasks.map((task, index) => ({
741
+ ...uniqueResults2[deduplicated.sourceIndexByInput[index]],
742
+ index: task.index
743
+ }));
744
+ }
654
745
  const chunks = [];
655
746
  for (let offset = 0; offset < uniqueTasks.length; offset += 25) {
656
747
  chunks.push({ offset, tasks: uniqueTasks.slice(offset, offset + 25) });
@@ -708,6 +799,13 @@ var Signaliz = class {
708
799
  };
709
800
  }
710
801
  };
802
+ function recoverableJobRowFailed(row) {
803
+ return row.success === false || String(row._status || "").toLowerCase() === "failed";
804
+ }
805
+ function newBatchIdempotencyKey(label) {
806
+ const nonce = globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random().toString(16).slice(2)}`;
807
+ return `signaliz-${label.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${nonce}`;
808
+ }
711
809
  function compact(input) {
712
810
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
713
811
  }
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Signaliz,
3
3
  SignalizError
4
- } from "./chunk-P3ICLKAE.mjs";
4
+ } from "./chunk-H6HOY73X.mjs";
5
5
  export {
6
6
  Signaliz,
7
7
  SignalizError
@@ -549,6 +549,24 @@ var Signaliz = class {
549
549
  poll_interval_ms: params.pollIntervalMs
550
550
  }));
551
551
  const uniqueRequests = deduplicated.uniqueItems;
552
+ const canUseRecoverableAvailableDataJob = uniqueRequests.length > 25 && uniqueRequests.every(
553
+ (params) => params.waitForResult !== false && params.skipCache !== true && params.enableDeepSearch !== true && params.maxWaitMs === void 0 && params.pollIntervalMs === void 0
554
+ );
555
+ const uniqueResults = canUseRecoverableAvailableDataJob ? await this.runAvailableSignalCopyBatchJob(uniqueRequests) : await this.runSignalCopyBatchChunks(uniqueRequests, options);
556
+ const results = requests.map((_, index) => ({
557
+ ...uniqueResults[deduplicated.sourceIndexByInput[index]],
558
+ index
559
+ }));
560
+ const succeeded = results.filter((item) => item.success).length;
561
+ return {
562
+ total: requests.length,
563
+ succeeded,
564
+ failed: requests.length - succeeded,
565
+ durationMs: Date.now() - startedAt,
566
+ results
567
+ };
568
+ }
569
+ async runSignalCopyBatchChunks(uniqueRequests, options) {
552
570
  const chunks = [];
553
571
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
554
572
  chunks.push({ offset, requests: uniqueRequests.slice(offset, offset + 25) });
@@ -576,18 +594,74 @@ var Signaliz = class {
576
594
  uniqueResults[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
577
595
  }
578
596
  }
579
- const results = requests.map((_, index) => ({
580
- ...uniqueResults[deduplicated.sourceIndexByInput[index]],
581
- index
582
- }));
583
- const succeeded = results.filter((item) => item.success).length;
584
- return {
585
- total: requests.length,
586
- succeeded,
587
- failed: requests.length - succeeded,
588
- durationMs: Date.now() - startedAt,
589
- results
590
- };
597
+ return uniqueResults;
598
+ }
599
+ async runAvailableSignalCopyBatchJob(requests) {
600
+ const rows = await this.runRecoverableCoreBatchJob(
601
+ "api/v1/signal-to-copy",
602
+ requests.map(signalToCopyRequestBody),
603
+ "Signal to Copy"
604
+ );
605
+ const results = new Array(requests.length);
606
+ for (const row of rows) {
607
+ const index = Number(row.index);
608
+ results[index] = recoverableJobRowFailed(row) ? { index, success: false, error: row.error || row.message || "Signal to Copy failed" } : { index, success: true, data: normalizeSignalToCopyResult(row) };
609
+ }
610
+ return results;
611
+ }
612
+ async runRecoverableCoreBatchJob(path2, requests, label) {
613
+ const startedAt = Date.now();
614
+ const maxWaitMs = 20 * 6e4;
615
+ const submission = await this.client.post(path2, {
616
+ requests,
617
+ idempotency_key: newBatchIdempotencyKey(label)
618
+ });
619
+ const jobId = String(submission.job_id || "").trim();
620
+ if (!jobId) throw new Error(`${label} batch did not return a recoverable job_id`);
621
+ let status = await this.client.post(path2, {
622
+ job_id: jobId,
623
+ page: 1,
624
+ page_size: 500
625
+ });
626
+ while (!["completed", "partial", "failed"].includes(String(status.status || "").toLowerCase())) {
627
+ if (Date.now() - startedAt >= maxWaitMs) {
628
+ throw new Error(`${label} batch ${jobId} did not complete within ${maxWaitMs}ms`);
629
+ }
630
+ const retryAfterMs = Number(status.next_poll_after_seconds || 2) * 1e3;
631
+ await sleep2(Math.min(Math.max(250, retryAfterMs), maxWaitMs - (Date.now() - startedAt)));
632
+ status = await this.client.post(path2, {
633
+ job_id: jobId,
634
+ page: 1,
635
+ page_size: 500
636
+ });
637
+ }
638
+ const totalPages = Math.max(1, Number(status.total_pages || 1));
639
+ const pages = [Array.isArray(status.results) ? status.results : []];
640
+ if (totalPages > 1) {
641
+ const remainingPages = await Promise.all(Array.from(
642
+ { length: totalPages - 1 },
643
+ (_, index) => this.client.post(path2, {
644
+ job_id: jobId,
645
+ page: index + 2,
646
+ page_size: 500
647
+ })
648
+ ));
649
+ for (const page of remainingPages) pages.push(Array.isArray(page.results) ? page.results : []);
650
+ }
651
+ const rows = pages.flat();
652
+ if (rows.length !== requests.length) {
653
+ throw new Error(`${label} batch returned ${rows.length} results for ${requests.length} requests`);
654
+ }
655
+ const seen = /* @__PURE__ */ new Set();
656
+ for (const row of rows) {
657
+ const index = Number(row.index);
658
+ if (!Number.isInteger(index) || index < 0 || index >= requests.length || seen.has(index)) {
659
+ throw new Error(`${label} batch returned an invalid result index`);
660
+ }
661
+ seen.add(index);
662
+ }
663
+ if (seen.size !== requests.length) throw new Error(`${label} batch returned incomplete indexed results`);
664
+ return rows;
591
665
  }
592
666
  async runSignalCopyBatchChunk(requests, concurrency) {
593
667
  const startedAt = Date.now();
@@ -655,6 +729,23 @@ var Signaliz = class {
655
729
  const { serverConcurrency, chunkConcurrency } = batchConcurrencyPlan(options);
656
730
  const deduplicated = dedupeExactBatchItems(tasks, (task) => JSON.stringify(task.request));
657
731
  const uniqueTasks = deduplicated.uniqueItems;
732
+ if (path2 === "api/v1/verify-email" && uniqueTasks.length > 25) {
733
+ const rows = await this.runRecoverableCoreBatchJob(
734
+ path2,
735
+ uniqueTasks.map((task) => task.request),
736
+ "Verify Email"
737
+ );
738
+ const uniqueResults2 = rows.map((raw) => ({
739
+ index: uniqueTasks[Number(raw.index)].index,
740
+ success: !recoverableJobRowFailed(raw),
741
+ raw,
742
+ error: recoverableJobRowFailed(raw) ? raw.error || raw._error || raw.message || raw.failure_reason || "Verify Email item failed" : void 0
743
+ }));
744
+ return tasks.map((task, index) => ({
745
+ ...uniqueResults2[deduplicated.sourceIndexByInput[index]],
746
+ index: task.index
747
+ }));
748
+ }
658
749
  const chunks = [];
659
750
  for (let offset = 0; offset < uniqueTasks.length; offset += 25) {
660
751
  chunks.push({ offset, tasks: uniqueTasks.slice(offset, offset + 25) });
@@ -712,6 +803,13 @@ var Signaliz = class {
712
803
  };
713
804
  }
714
805
  };
806
+ function recoverableJobRowFailed(row) {
807
+ return row.success === false || String(row._status || "").toLowerCase() === "failed";
808
+ }
809
+ function newBatchIdempotencyKey(label) {
810
+ const nonce = globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random().toString(16).slice(2)}`;
811
+ return `signaliz-${label.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${nonce}`;
812
+ }
715
813
  function compact(input) {
716
814
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
717
815
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Signaliz
4
- } from "./chunk-P3ICLKAE.mjs";
4
+ } from "./chunk-H6HOY73X.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.31",
3
+ "version": "1.0.33",
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",