@signaliz/sdk 1.0.28 → 1.0.29
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 +2 -0
- package/dist/{chunk-YQXKJ6FB.mjs → chunk-R4DIAP7P.mjs} +140 -31
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +140 -31
- package/dist/index.mjs +1 -1
- package/dist/mcp-config.js +140 -31
- package/dist/mcp-config.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,8 @@ 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
|
+
Signal to Copy batches are transported in 25-row chunks; exact duplicates and
|
|
81
|
+
shared company research are single-flighted without changing input order.
|
|
80
82
|
|
|
81
83
|
Company Signal Enrichment defaults `online` and `enableDeepSearch` to `true`
|
|
82
84
|
unless the caller explicitly disables them. Signal to Copy AI returns three
|
|
@@ -506,16 +506,7 @@ var Signaliz = class {
|
|
|
506
506
|
return runBatch(companies, (company) => this.enrichCompanySignals(company), options);
|
|
507
507
|
}
|
|
508
508
|
async signalToCopy(params) {
|
|
509
|
-
const request =
|
|
510
|
-
company_domain: params.companyDomain,
|
|
511
|
-
person_name: params.personName,
|
|
512
|
-
title: params.title,
|
|
513
|
-
campaign_offer: params.campaignOffer,
|
|
514
|
-
research_prompt: params.researchPrompt,
|
|
515
|
-
signal_run_id: params.signalRunId,
|
|
516
|
-
skip_cache: params.skipCache,
|
|
517
|
-
enable_deep_search: params.enableDeepSearch
|
|
518
|
-
});
|
|
509
|
+
const request = signalToCopyRequestBody(params);
|
|
519
510
|
let data = await this.client.post("api/v1/signal-to-copy", request);
|
|
520
511
|
if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
|
|
521
512
|
const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
|
|
@@ -532,30 +523,113 @@ var Signaliz = class {
|
|
|
532
523
|
throw new Error(`Signal Copy ${data.run_id} did not complete within ${maxWaitMs}ms`);
|
|
533
524
|
}
|
|
534
525
|
}
|
|
526
|
+
return normalizeSignalToCopyResult(data);
|
|
527
|
+
}
|
|
528
|
+
async createSignalCopyBatch(requests, options) {
|
|
529
|
+
if (!Array.isArray(requests) || requests.length === 0) {
|
|
530
|
+
throw new Error("Signaliz batch requests require at least one item");
|
|
531
|
+
}
|
|
532
|
+
if (requests.length > 5e3) {
|
|
533
|
+
throw new Error(`Signaliz batch requests support at most 5,000 items; received ${requests.length}`);
|
|
534
|
+
}
|
|
535
|
+
const startedAt = Date.now();
|
|
536
|
+
const chunks = [];
|
|
537
|
+
for (let offset = 0; offset < requests.length; offset += 25) {
|
|
538
|
+
chunks.push({ offset, requests: requests.slice(offset, offset + 25) });
|
|
539
|
+
}
|
|
540
|
+
const serverConcurrency = Math.min(10, options?.concurrency ?? 10);
|
|
541
|
+
const chunkBatch = await runBatch(
|
|
542
|
+
chunks,
|
|
543
|
+
(chunk) => this.runSignalCopyBatchChunk(chunk.requests, serverConcurrency),
|
|
544
|
+
options
|
|
545
|
+
);
|
|
546
|
+
const results = new Array(requests.length);
|
|
547
|
+
for (const chunkResult of chunkBatch.results) {
|
|
548
|
+
const chunk = chunks[chunkResult.index];
|
|
549
|
+
if (!chunkResult.success || !chunkResult.data) {
|
|
550
|
+
for (let index = 0; index < chunk.requests.length; index += 1) {
|
|
551
|
+
results[chunk.offset + index] = {
|
|
552
|
+
index: chunk.offset + index,
|
|
553
|
+
success: false,
|
|
554
|
+
error: chunkResult.error || "Signal to Copy batch request failed"
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
for (const item of chunkResult.data) {
|
|
560
|
+
results[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const succeeded = results.filter((item) => item.success).length;
|
|
535
564
|
return {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
subjectLine: data.subject_line ?? "",
|
|
542
|
-
openingLine: data.opening_line ?? "",
|
|
543
|
-
confidence: data.confidence ?? 0,
|
|
544
|
-
evidenceUrl: data.evidence_url ?? "",
|
|
545
|
-
researchPrompt: data.research_prompt,
|
|
546
|
-
variations: (data.variations ?? []).map((variation) => ({
|
|
547
|
-
style: variation.style,
|
|
548
|
-
subjectLine: variation.subject_line ?? "",
|
|
549
|
-
openingLine: variation.opening_line ?? "",
|
|
550
|
-
cta: variation.cta ?? "",
|
|
551
|
-
prediction: variation.prediction,
|
|
552
|
-
email: variation.email
|
|
553
|
-
})),
|
|
554
|
-
raw: data
|
|
565
|
+
total: requests.length,
|
|
566
|
+
succeeded,
|
|
567
|
+
failed: requests.length - succeeded,
|
|
568
|
+
durationMs: Date.now() - startedAt,
|
|
569
|
+
results
|
|
555
570
|
};
|
|
556
571
|
}
|
|
557
|
-
async
|
|
558
|
-
|
|
572
|
+
async runSignalCopyBatchChunk(requests, concurrency) {
|
|
573
|
+
const startedAt = Date.now();
|
|
574
|
+
const results = new Array(requests.length);
|
|
575
|
+
let pending = requests.map((params, index) => ({
|
|
576
|
+
index,
|
|
577
|
+
params,
|
|
578
|
+
request: signalToCopyRequestBody(params)
|
|
579
|
+
}));
|
|
580
|
+
while (pending.length > 0) {
|
|
581
|
+
const data = await this.client.post("api/v1/signal-to-copy", {
|
|
582
|
+
requests: pending.map((item) => item.request),
|
|
583
|
+
concurrency
|
|
584
|
+
});
|
|
585
|
+
if (!Array.isArray(data.results) || data.results.length !== pending.length) {
|
|
586
|
+
throw new Error("Signal to Copy batch returned an invalid result count");
|
|
587
|
+
}
|
|
588
|
+
const nextPending = [];
|
|
589
|
+
let nextDelayMs = 6e4;
|
|
590
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
591
|
+
const task = pending[index];
|
|
592
|
+
const item = data.results[index];
|
|
593
|
+
if (item.success === false) {
|
|
594
|
+
results[task.index] = { index: task.index, success: false, error: item.error || item.message || "Signal to Copy failed" };
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
if (!isPendingSignalResponse(item)) {
|
|
598
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (task.params.waitForResult === false) {
|
|
602
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
const maxWaitMs = Math.max(1e3, task.params.maxWaitMs ?? 20 * 6e4);
|
|
606
|
+
if (Date.now() - startedAt >= maxWaitMs) {
|
|
607
|
+
results[task.index] = {
|
|
608
|
+
index: task.index,
|
|
609
|
+
success: false,
|
|
610
|
+
error: `Signal Copy ${item.signal_run_id || item.run_id || ""} did not complete within ${maxWaitMs}ms`
|
|
611
|
+
};
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const signalRunId = item.signal_run_id || item.run_id;
|
|
615
|
+
if (!signalRunId) {
|
|
616
|
+
results[task.index] = { index: task.index, success: false, error: "Signal Copy is processing without a signal_run_id" };
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
nextDelayMs = Math.min(
|
|
620
|
+
nextDelayMs,
|
|
621
|
+
signalPollDelayMs(item, task.params.pollIntervalMs),
|
|
622
|
+
maxWaitMs - (Date.now() - startedAt)
|
|
623
|
+
);
|
|
624
|
+
nextPending.push({
|
|
625
|
+
...task,
|
|
626
|
+
request: { ...task.request, signal_run_id: signalRunId }
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
pending = nextPending;
|
|
630
|
+
if (pending.length > 0) await sleep2(nextDelayMs);
|
|
631
|
+
}
|
|
632
|
+
return results;
|
|
559
633
|
}
|
|
560
634
|
async listTools() {
|
|
561
635
|
const result = await this.client.mcp("tools/list");
|
|
@@ -572,6 +646,41 @@ var Signaliz = class {
|
|
|
572
646
|
function compact(input) {
|
|
573
647
|
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
574
648
|
}
|
|
649
|
+
function signalToCopyRequestBody(params) {
|
|
650
|
+
return compact({
|
|
651
|
+
company_domain: params.companyDomain,
|
|
652
|
+
person_name: params.personName,
|
|
653
|
+
title: params.title,
|
|
654
|
+
campaign_offer: params.campaignOffer,
|
|
655
|
+
research_prompt: params.researchPrompt,
|
|
656
|
+
signal_run_id: params.signalRunId,
|
|
657
|
+
skip_cache: params.skipCache,
|
|
658
|
+
enable_deep_search: params.enableDeepSearch
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
function normalizeSignalToCopyResult(data) {
|
|
662
|
+
return {
|
|
663
|
+
success: data.success ?? true,
|
|
664
|
+
status: data.status,
|
|
665
|
+
runId: data.signal_run_id ?? data.run_id,
|
|
666
|
+
strongestSignal: data.strongest_signal ?? "",
|
|
667
|
+
whyNow: data.why_now ?? "",
|
|
668
|
+
subjectLine: data.subject_line ?? "",
|
|
669
|
+
openingLine: data.opening_line ?? "",
|
|
670
|
+
confidence: data.confidence ?? 0,
|
|
671
|
+
evidenceUrl: data.evidence_url ?? "",
|
|
672
|
+
researchPrompt: data.research_prompt,
|
|
673
|
+
variations: (data.variations ?? []).map((variation) => ({
|
|
674
|
+
style: variation.style,
|
|
675
|
+
subjectLine: variation.subject_line ?? "",
|
|
676
|
+
openingLine: variation.opening_line ?? "",
|
|
677
|
+
cta: variation.cta ?? "",
|
|
678
|
+
prediction: variation.prediction,
|
|
679
|
+
email: variation.email
|
|
680
|
+
})),
|
|
681
|
+
raw: data
|
|
682
|
+
};
|
|
683
|
+
}
|
|
575
684
|
function isPendingSignalResponse(data) {
|
|
576
685
|
return ["triggered", "queued", "processing", "pending", "pending_version", "waiting_for_deploy"].includes(String(data.status || "").toLowerCase());
|
|
577
686
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -203,6 +203,7 @@ 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 runSignalCopyBatchChunk;
|
|
206
207
|
listTools(): Promise<MCPToolInfo[]>;
|
|
207
208
|
health(): Promise<PlatformHealth>;
|
|
208
209
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -203,6 +203,7 @@ 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 runSignalCopyBatchChunk;
|
|
206
207
|
listTools(): Promise<MCPToolInfo[]>;
|
|
207
208
|
health(): Promise<PlatformHealth>;
|
|
208
209
|
}
|
package/dist/index.js
CHANGED
|
@@ -533,16 +533,7 @@ var Signaliz = class {
|
|
|
533
533
|
return runBatch(companies, (company) => this.enrichCompanySignals(company), options);
|
|
534
534
|
}
|
|
535
535
|
async signalToCopy(params) {
|
|
536
|
-
const request =
|
|
537
|
-
company_domain: params.companyDomain,
|
|
538
|
-
person_name: params.personName,
|
|
539
|
-
title: params.title,
|
|
540
|
-
campaign_offer: params.campaignOffer,
|
|
541
|
-
research_prompt: params.researchPrompt,
|
|
542
|
-
signal_run_id: params.signalRunId,
|
|
543
|
-
skip_cache: params.skipCache,
|
|
544
|
-
enable_deep_search: params.enableDeepSearch
|
|
545
|
-
});
|
|
536
|
+
const request = signalToCopyRequestBody(params);
|
|
546
537
|
let data = await this.client.post("api/v1/signal-to-copy", request);
|
|
547
538
|
if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
|
|
548
539
|
const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
|
|
@@ -559,30 +550,113 @@ var Signaliz = class {
|
|
|
559
550
|
throw new Error(`Signal Copy ${data.run_id} did not complete within ${maxWaitMs}ms`);
|
|
560
551
|
}
|
|
561
552
|
}
|
|
553
|
+
return normalizeSignalToCopyResult(data);
|
|
554
|
+
}
|
|
555
|
+
async createSignalCopyBatch(requests, options) {
|
|
556
|
+
if (!Array.isArray(requests) || requests.length === 0) {
|
|
557
|
+
throw new Error("Signaliz batch requests require at least one item");
|
|
558
|
+
}
|
|
559
|
+
if (requests.length > 5e3) {
|
|
560
|
+
throw new Error(`Signaliz batch requests support at most 5,000 items; received ${requests.length}`);
|
|
561
|
+
}
|
|
562
|
+
const startedAt = Date.now();
|
|
563
|
+
const chunks = [];
|
|
564
|
+
for (let offset = 0; offset < requests.length; offset += 25) {
|
|
565
|
+
chunks.push({ offset, requests: requests.slice(offset, offset + 25) });
|
|
566
|
+
}
|
|
567
|
+
const serverConcurrency = Math.min(10, options?.concurrency ?? 10);
|
|
568
|
+
const chunkBatch = await runBatch(
|
|
569
|
+
chunks,
|
|
570
|
+
(chunk) => this.runSignalCopyBatchChunk(chunk.requests, serverConcurrency),
|
|
571
|
+
options
|
|
572
|
+
);
|
|
573
|
+
const results = new Array(requests.length);
|
|
574
|
+
for (const chunkResult of chunkBatch.results) {
|
|
575
|
+
const chunk = chunks[chunkResult.index];
|
|
576
|
+
if (!chunkResult.success || !chunkResult.data) {
|
|
577
|
+
for (let index = 0; index < chunk.requests.length; index += 1) {
|
|
578
|
+
results[chunk.offset + index] = {
|
|
579
|
+
index: chunk.offset + index,
|
|
580
|
+
success: false,
|
|
581
|
+
error: chunkResult.error || "Signal to Copy batch request failed"
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
for (const item of chunkResult.data) {
|
|
587
|
+
results[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
const succeeded = results.filter((item) => item.success).length;
|
|
562
591
|
return {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
subjectLine: data.subject_line ?? "",
|
|
569
|
-
openingLine: data.opening_line ?? "",
|
|
570
|
-
confidence: data.confidence ?? 0,
|
|
571
|
-
evidenceUrl: data.evidence_url ?? "",
|
|
572
|
-
researchPrompt: data.research_prompt,
|
|
573
|
-
variations: (data.variations ?? []).map((variation) => ({
|
|
574
|
-
style: variation.style,
|
|
575
|
-
subjectLine: variation.subject_line ?? "",
|
|
576
|
-
openingLine: variation.opening_line ?? "",
|
|
577
|
-
cta: variation.cta ?? "",
|
|
578
|
-
prediction: variation.prediction,
|
|
579
|
-
email: variation.email
|
|
580
|
-
})),
|
|
581
|
-
raw: data
|
|
592
|
+
total: requests.length,
|
|
593
|
+
succeeded,
|
|
594
|
+
failed: requests.length - succeeded,
|
|
595
|
+
durationMs: Date.now() - startedAt,
|
|
596
|
+
results
|
|
582
597
|
};
|
|
583
598
|
}
|
|
584
|
-
async
|
|
585
|
-
|
|
599
|
+
async runSignalCopyBatchChunk(requests, concurrency) {
|
|
600
|
+
const startedAt = Date.now();
|
|
601
|
+
const results = new Array(requests.length);
|
|
602
|
+
let pending = requests.map((params, index) => ({
|
|
603
|
+
index,
|
|
604
|
+
params,
|
|
605
|
+
request: signalToCopyRequestBody(params)
|
|
606
|
+
}));
|
|
607
|
+
while (pending.length > 0) {
|
|
608
|
+
const data = await this.client.post("api/v1/signal-to-copy", {
|
|
609
|
+
requests: pending.map((item) => item.request),
|
|
610
|
+
concurrency
|
|
611
|
+
});
|
|
612
|
+
if (!Array.isArray(data.results) || data.results.length !== pending.length) {
|
|
613
|
+
throw new Error("Signal to Copy batch returned an invalid result count");
|
|
614
|
+
}
|
|
615
|
+
const nextPending = [];
|
|
616
|
+
let nextDelayMs = 6e4;
|
|
617
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
618
|
+
const task = pending[index];
|
|
619
|
+
const item = data.results[index];
|
|
620
|
+
if (item.success === false) {
|
|
621
|
+
results[task.index] = { index: task.index, success: false, error: item.error || item.message || "Signal to Copy failed" };
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
if (!isPendingSignalResponse(item)) {
|
|
625
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (task.params.waitForResult === false) {
|
|
629
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
const maxWaitMs = Math.max(1e3, task.params.maxWaitMs ?? 20 * 6e4);
|
|
633
|
+
if (Date.now() - startedAt >= maxWaitMs) {
|
|
634
|
+
results[task.index] = {
|
|
635
|
+
index: task.index,
|
|
636
|
+
success: false,
|
|
637
|
+
error: `Signal Copy ${item.signal_run_id || item.run_id || ""} did not complete within ${maxWaitMs}ms`
|
|
638
|
+
};
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
const signalRunId = item.signal_run_id || item.run_id;
|
|
642
|
+
if (!signalRunId) {
|
|
643
|
+
results[task.index] = { index: task.index, success: false, error: "Signal Copy is processing without a signal_run_id" };
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
nextDelayMs = Math.min(
|
|
647
|
+
nextDelayMs,
|
|
648
|
+
signalPollDelayMs(item, task.params.pollIntervalMs),
|
|
649
|
+
maxWaitMs - (Date.now() - startedAt)
|
|
650
|
+
);
|
|
651
|
+
nextPending.push({
|
|
652
|
+
...task,
|
|
653
|
+
request: { ...task.request, signal_run_id: signalRunId }
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
pending = nextPending;
|
|
657
|
+
if (pending.length > 0) await sleep2(nextDelayMs);
|
|
658
|
+
}
|
|
659
|
+
return results;
|
|
586
660
|
}
|
|
587
661
|
async listTools() {
|
|
588
662
|
const result = await this.client.mcp("tools/list");
|
|
@@ -599,6 +673,41 @@ var Signaliz = class {
|
|
|
599
673
|
function compact(input) {
|
|
600
674
|
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
601
675
|
}
|
|
676
|
+
function signalToCopyRequestBody(params) {
|
|
677
|
+
return compact({
|
|
678
|
+
company_domain: params.companyDomain,
|
|
679
|
+
person_name: params.personName,
|
|
680
|
+
title: params.title,
|
|
681
|
+
campaign_offer: params.campaignOffer,
|
|
682
|
+
research_prompt: params.researchPrompt,
|
|
683
|
+
signal_run_id: params.signalRunId,
|
|
684
|
+
skip_cache: params.skipCache,
|
|
685
|
+
enable_deep_search: params.enableDeepSearch
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
function normalizeSignalToCopyResult(data) {
|
|
689
|
+
return {
|
|
690
|
+
success: data.success ?? true,
|
|
691
|
+
status: data.status,
|
|
692
|
+
runId: data.signal_run_id ?? data.run_id,
|
|
693
|
+
strongestSignal: data.strongest_signal ?? "",
|
|
694
|
+
whyNow: data.why_now ?? "",
|
|
695
|
+
subjectLine: data.subject_line ?? "",
|
|
696
|
+
openingLine: data.opening_line ?? "",
|
|
697
|
+
confidence: data.confidence ?? 0,
|
|
698
|
+
evidenceUrl: data.evidence_url ?? "",
|
|
699
|
+
researchPrompt: data.research_prompt,
|
|
700
|
+
variations: (data.variations ?? []).map((variation) => ({
|
|
701
|
+
style: variation.style,
|
|
702
|
+
subjectLine: variation.subject_line ?? "",
|
|
703
|
+
openingLine: variation.opening_line ?? "",
|
|
704
|
+
cta: variation.cta ?? "",
|
|
705
|
+
prediction: variation.prediction,
|
|
706
|
+
email: variation.email
|
|
707
|
+
})),
|
|
708
|
+
raw: data
|
|
709
|
+
};
|
|
710
|
+
}
|
|
602
711
|
function isPendingSignalResponse(data) {
|
|
603
712
|
return ["triggered", "queued", "processing", "pending", "pending_version", "waiting_for_deploy"].includes(String(data.status || "").toLowerCase());
|
|
604
713
|
}
|
package/dist/index.mjs
CHANGED
package/dist/mcp-config.js
CHANGED
|
@@ -537,16 +537,7 @@ var Signaliz = class {
|
|
|
537
537
|
return runBatch(companies, (company) => this.enrichCompanySignals(company), options);
|
|
538
538
|
}
|
|
539
539
|
async signalToCopy(params) {
|
|
540
|
-
const request =
|
|
541
|
-
company_domain: params.companyDomain,
|
|
542
|
-
person_name: params.personName,
|
|
543
|
-
title: params.title,
|
|
544
|
-
campaign_offer: params.campaignOffer,
|
|
545
|
-
research_prompt: params.researchPrompt,
|
|
546
|
-
signal_run_id: params.signalRunId,
|
|
547
|
-
skip_cache: params.skipCache,
|
|
548
|
-
enable_deep_search: params.enableDeepSearch
|
|
549
|
-
});
|
|
540
|
+
const request = signalToCopyRequestBody(params);
|
|
550
541
|
let data = await this.client.post("api/v1/signal-to-copy", request);
|
|
551
542
|
if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
|
|
552
543
|
const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
|
|
@@ -563,30 +554,113 @@ var Signaliz = class {
|
|
|
563
554
|
throw new Error(`Signal Copy ${data.run_id} did not complete within ${maxWaitMs}ms`);
|
|
564
555
|
}
|
|
565
556
|
}
|
|
557
|
+
return normalizeSignalToCopyResult(data);
|
|
558
|
+
}
|
|
559
|
+
async createSignalCopyBatch(requests, options) {
|
|
560
|
+
if (!Array.isArray(requests) || requests.length === 0) {
|
|
561
|
+
throw new Error("Signaliz batch requests require at least one item");
|
|
562
|
+
}
|
|
563
|
+
if (requests.length > 5e3) {
|
|
564
|
+
throw new Error(`Signaliz batch requests support at most 5,000 items; received ${requests.length}`);
|
|
565
|
+
}
|
|
566
|
+
const startedAt = Date.now();
|
|
567
|
+
const chunks = [];
|
|
568
|
+
for (let offset = 0; offset < requests.length; offset += 25) {
|
|
569
|
+
chunks.push({ offset, requests: requests.slice(offset, offset + 25) });
|
|
570
|
+
}
|
|
571
|
+
const serverConcurrency = Math.min(10, options?.concurrency ?? 10);
|
|
572
|
+
const chunkBatch = await runBatch(
|
|
573
|
+
chunks,
|
|
574
|
+
(chunk) => this.runSignalCopyBatchChunk(chunk.requests, serverConcurrency),
|
|
575
|
+
options
|
|
576
|
+
);
|
|
577
|
+
const results = new Array(requests.length);
|
|
578
|
+
for (const chunkResult of chunkBatch.results) {
|
|
579
|
+
const chunk = chunks[chunkResult.index];
|
|
580
|
+
if (!chunkResult.success || !chunkResult.data) {
|
|
581
|
+
for (let index = 0; index < chunk.requests.length; index += 1) {
|
|
582
|
+
results[chunk.offset + index] = {
|
|
583
|
+
index: chunk.offset + index,
|
|
584
|
+
success: false,
|
|
585
|
+
error: chunkResult.error || "Signal to Copy batch request failed"
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
for (const item of chunkResult.data) {
|
|
591
|
+
results[chunk.offset + item.index] = { ...item, index: chunk.offset + item.index };
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
const succeeded = results.filter((item) => item.success).length;
|
|
566
595
|
return {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
subjectLine: data.subject_line ?? "",
|
|
573
|
-
openingLine: data.opening_line ?? "",
|
|
574
|
-
confidence: data.confidence ?? 0,
|
|
575
|
-
evidenceUrl: data.evidence_url ?? "",
|
|
576
|
-
researchPrompt: data.research_prompt,
|
|
577
|
-
variations: (data.variations ?? []).map((variation) => ({
|
|
578
|
-
style: variation.style,
|
|
579
|
-
subjectLine: variation.subject_line ?? "",
|
|
580
|
-
openingLine: variation.opening_line ?? "",
|
|
581
|
-
cta: variation.cta ?? "",
|
|
582
|
-
prediction: variation.prediction,
|
|
583
|
-
email: variation.email
|
|
584
|
-
})),
|
|
585
|
-
raw: data
|
|
596
|
+
total: requests.length,
|
|
597
|
+
succeeded,
|
|
598
|
+
failed: requests.length - succeeded,
|
|
599
|
+
durationMs: Date.now() - startedAt,
|
|
600
|
+
results
|
|
586
601
|
};
|
|
587
602
|
}
|
|
588
|
-
async
|
|
589
|
-
|
|
603
|
+
async runSignalCopyBatchChunk(requests, concurrency) {
|
|
604
|
+
const startedAt = Date.now();
|
|
605
|
+
const results = new Array(requests.length);
|
|
606
|
+
let pending = requests.map((params, index) => ({
|
|
607
|
+
index,
|
|
608
|
+
params,
|
|
609
|
+
request: signalToCopyRequestBody(params)
|
|
610
|
+
}));
|
|
611
|
+
while (pending.length > 0) {
|
|
612
|
+
const data = await this.client.post("api/v1/signal-to-copy", {
|
|
613
|
+
requests: pending.map((item) => item.request),
|
|
614
|
+
concurrency
|
|
615
|
+
});
|
|
616
|
+
if (!Array.isArray(data.results) || data.results.length !== pending.length) {
|
|
617
|
+
throw new Error("Signal to Copy batch returned an invalid result count");
|
|
618
|
+
}
|
|
619
|
+
const nextPending = [];
|
|
620
|
+
let nextDelayMs = 6e4;
|
|
621
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
622
|
+
const task = pending[index];
|
|
623
|
+
const item = data.results[index];
|
|
624
|
+
if (item.success === false) {
|
|
625
|
+
results[task.index] = { index: task.index, success: false, error: item.error || item.message || "Signal to Copy failed" };
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (!isPendingSignalResponse(item)) {
|
|
629
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
if (task.params.waitForResult === false) {
|
|
633
|
+
results[task.index] = { index: task.index, success: true, data: normalizeSignalToCopyResult(item) };
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
const maxWaitMs = Math.max(1e3, task.params.maxWaitMs ?? 20 * 6e4);
|
|
637
|
+
if (Date.now() - startedAt >= maxWaitMs) {
|
|
638
|
+
results[task.index] = {
|
|
639
|
+
index: task.index,
|
|
640
|
+
success: false,
|
|
641
|
+
error: `Signal Copy ${item.signal_run_id || item.run_id || ""} did not complete within ${maxWaitMs}ms`
|
|
642
|
+
};
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
const signalRunId = item.signal_run_id || item.run_id;
|
|
646
|
+
if (!signalRunId) {
|
|
647
|
+
results[task.index] = { index: task.index, success: false, error: "Signal Copy is processing without a signal_run_id" };
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
nextDelayMs = Math.min(
|
|
651
|
+
nextDelayMs,
|
|
652
|
+
signalPollDelayMs(item, task.params.pollIntervalMs),
|
|
653
|
+
maxWaitMs - (Date.now() - startedAt)
|
|
654
|
+
);
|
|
655
|
+
nextPending.push({
|
|
656
|
+
...task,
|
|
657
|
+
request: { ...task.request, signal_run_id: signalRunId }
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
pending = nextPending;
|
|
661
|
+
if (pending.length > 0) await sleep2(nextDelayMs);
|
|
662
|
+
}
|
|
663
|
+
return results;
|
|
590
664
|
}
|
|
591
665
|
async listTools() {
|
|
592
666
|
const result = await this.client.mcp("tools/list");
|
|
@@ -603,6 +677,41 @@ var Signaliz = class {
|
|
|
603
677
|
function compact(input) {
|
|
604
678
|
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
605
679
|
}
|
|
680
|
+
function signalToCopyRequestBody(params) {
|
|
681
|
+
return compact({
|
|
682
|
+
company_domain: params.companyDomain,
|
|
683
|
+
person_name: params.personName,
|
|
684
|
+
title: params.title,
|
|
685
|
+
campaign_offer: params.campaignOffer,
|
|
686
|
+
research_prompt: params.researchPrompt,
|
|
687
|
+
signal_run_id: params.signalRunId,
|
|
688
|
+
skip_cache: params.skipCache,
|
|
689
|
+
enable_deep_search: params.enableDeepSearch
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
function normalizeSignalToCopyResult(data) {
|
|
693
|
+
return {
|
|
694
|
+
success: data.success ?? true,
|
|
695
|
+
status: data.status,
|
|
696
|
+
runId: data.signal_run_id ?? data.run_id,
|
|
697
|
+
strongestSignal: data.strongest_signal ?? "",
|
|
698
|
+
whyNow: data.why_now ?? "",
|
|
699
|
+
subjectLine: data.subject_line ?? "",
|
|
700
|
+
openingLine: data.opening_line ?? "",
|
|
701
|
+
confidence: data.confidence ?? 0,
|
|
702
|
+
evidenceUrl: data.evidence_url ?? "",
|
|
703
|
+
researchPrompt: data.research_prompt,
|
|
704
|
+
variations: (data.variations ?? []).map((variation) => ({
|
|
705
|
+
style: variation.style,
|
|
706
|
+
subjectLine: variation.subject_line ?? "",
|
|
707
|
+
openingLine: variation.opening_line ?? "",
|
|
708
|
+
cta: variation.cta ?? "",
|
|
709
|
+
prediction: variation.prediction,
|
|
710
|
+
email: variation.email
|
|
711
|
+
})),
|
|
712
|
+
raw: data
|
|
713
|
+
};
|
|
714
|
+
}
|
|
606
715
|
function isPendingSignalResponse(data) {
|
|
607
716
|
return ["triggered", "queued", "processing", "pending", "pending_version", "waiting_for_deploy"].includes(String(data.status || "").toLowerCase());
|
|
608
717
|
}
|
package/dist/mcp-config.mjs
CHANGED
package/package.json
CHANGED