@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 +7 -4
- package/dist/{chunk-P3ICLKAE.mjs → chunk-H6HOY73X.mjs} +110 -12
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +110 -12
- package/dist/index.mjs +1 -1
- package/dist/mcp-config.js +110 -12
- package/dist/mcp-config.mjs +1 -1
- package/package.json +1 -1
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
package/dist/mcp-config.js
CHANGED
|
@@ -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
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
}
|
package/dist/mcp-config.mjs
CHANGED
package/package.json
CHANGED