@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 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 = compact({
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
- success: data.success ?? true,
537
- status: data.status,
538
- runId: data.run_id,
539
- strongestSignal: data.strongest_signal ?? "",
540
- whyNow: data.why_now ?? "",
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 createSignalCopyBatch(requests, options) {
558
- return runBatch(requests, (request) => this.signalToCopy(request), options);
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 = compact({
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
- success: data.success ?? true,
564
- status: data.status,
565
- runId: data.run_id,
566
- strongestSignal: data.strongest_signal ?? "",
567
- whyNow: data.why_now ?? "",
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 createSignalCopyBatch(requests, options) {
585
- return runBatch(requests, (request) => this.signalToCopy(request), options);
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
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Signaliz,
3
3
  SignalizError
4
- } from "./chunk-YQXKJ6FB.mjs";
4
+ } from "./chunk-R4DIAP7P.mjs";
5
5
  export {
6
6
  Signaliz,
7
7
  SignalizError
@@ -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 = compact({
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
- success: data.success ?? true,
568
- status: data.status,
569
- runId: data.run_id,
570
- strongestSignal: data.strongest_signal ?? "",
571
- whyNow: data.why_now ?? "",
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 createSignalCopyBatch(requests, options) {
589
- return runBatch(requests, (request) => this.signalToCopy(request), options);
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
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Signaliz
4
- } from "./chunk-YQXKJ6FB.mjs";
4
+ } from "./chunk-R4DIAP7P.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.28",
3
+ "version": "1.0.29",
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",