@signaliz/cli 1.0.50 → 1.0.52

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.
Files changed (3) hide show
  1. package/README.md +10 -3
  2. package/dist/bin.js +121 -16
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -35,6 +35,8 @@ signaliz signal-to-copy \
35
35
  signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" \
36
36
  --title "VP Sales" --campaign-offer "pipeline intelligence" --skip-cache --deep-search
37
37
 
38
+ # Omit --deep-search for bounded credit-free first-party and Bing grounding.
39
+
38
40
  # Signals Everything returns distinct companies with a source-backed signal.
39
41
  # It is asynchronous by default; add --wait or resume the returned run ID.
40
42
  signaliz signals "companies that just got funded" --limit 100 --sources web,news
@@ -74,10 +76,15 @@ Failed result lines preserve `errorCode`, `retryEligible`, and
74
76
  `retryAfterSeconds` when the API supplies recovery guidance.
75
77
 
76
78
  If a single request or batch submission response is lost, rerun the same
77
- command with `--idempotency-key <key>` to recover the original request or durable job
78
- without duplicate work. Add `--dry-run` to any product command, including one
79
+ command with `--idempotency-key <key>` to recover the original request, durable
80
+ job, or provider run without duplicate work or spend. The same key is portable
81
+ across CLI, SDK, REST API, and MCP calls for the same workspace and logical
82
+ input; chunked batches retain collision-free keys for each original row. Add
83
+ `--dry-run` to any product command, including one
79
84
  using `--input`, to receive a conservative credit ceiling without provider
80
- calls, jobs, writes, or spend.
85
+ calls, jobs, writes, or spend. JSON plans expose submitted, unique-fresh, and
86
+ duplicate-suppression counts; human output calls out exact duplicates whenever
87
+ they reduce the ceiling.
81
88
 
82
89
  Batch input is capped at 5,000 records, concurrency is bounded to `1-50`, input
83
90
  order is preserved, and a failed item does not abort successful items.
package/dist/bin.js CHANGED
@@ -124,6 +124,62 @@ function readBatchInput() {
124
124
  function record(value) {
125
125
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
126
126
  }
127
+ function customerEmailResult(value) {
128
+ const result = record(value);
129
+ if (String(result.status || "").toLowerCase() === "processing") return result;
130
+ const raw = record(result.raw);
131
+ const verifiedForSending = typeof raw.verified_for_sending === "boolean" ? raw.verified_for_sending : typeof raw._verified_for_sending === "boolean" ? raw._verified_for_sending : result.raw === void 0 && typeof result.verifiedForSending === "boolean" ? result.verifiedForSending : result.raw === void 0 && typeof result.isVerifiedForSending === "boolean" ? result.isVerifiedForSending : void 0;
132
+ const isCatchAll = typeof result.isCatchAll === "boolean" ? result.isCatchAll : void 0;
133
+ const isMalformed = result.isMalformed === true || raw.is_malformed === true;
134
+ const verificationStatus = result.verificationStatus || result.verificationVerdict;
135
+ return {
136
+ ...result,
137
+ email: typeof result.email === "string" && result.email.trim() ? result.email.trim() : null,
138
+ status: "completed",
139
+ success: result.success === true,
140
+ is_valid: verifiedForSending ?? result.isValid ?? result.isVerified ?? false,
141
+ credits_used: Number(result.creditsUsed || 0),
142
+ ...verifiedForSending !== void 0 ? { verified_for_sending: verifiedForSending } : {},
143
+ ...isCatchAll !== void 0 ? { email_is_catch_all: isCatchAll, is_catch_all: isCatchAll } : {},
144
+ ...typeof result.isMalformed === "boolean" || typeof raw.is_malformed === "boolean" ? { is_malformed: isMalformed } : {},
145
+ ...verificationStatus ? { verification_status: verificationStatus, verification_verdict: verificationStatus } : {},
146
+ ...result.billingMetadata ? { billing_metadata: result.billingMetadata } : {}
147
+ };
148
+ }
149
+ function customerEmailBatch(value) {
150
+ return {
151
+ ...value,
152
+ results: value.results.map((item) => {
153
+ const row = record(item);
154
+ return row.data ? { ...row, data: customerEmailResult(row.data) } : row;
155
+ })
156
+ };
157
+ }
158
+ function customerSignalResult(value) {
159
+ const result = record(value);
160
+ const raw = record(result.raw);
161
+ const billingMetadata = Object.keys(record(result.billingMetadata)).length > 0 ? record(result.billingMetadata) : record(raw.billing_metadata);
162
+ return {
163
+ ...result,
164
+ ...Object.keys(billingMetadata).length > 0 ? { billingMetadata } : {},
165
+ resultReturnedFrom: result.resultReturnedFrom ?? raw.result_returned_from,
166
+ cacheHit: result.cacheHit ?? raw.cache_hit,
167
+ freshEnrichmentUsed: result.freshEnrichmentUsed ?? raw.fresh_enrichment_used,
168
+ creditsUsed: result.creditsUsed ?? raw.credits_used,
169
+ liveProviderCalled: result.liveProviderCalled ?? raw.live_provider_called,
170
+ aiProviderCalled: result.aiProviderCalled ?? raw.ai_provider_called,
171
+ byoAiUsed: result.byoAiUsed ?? raw.byo_ai_used
172
+ };
173
+ }
174
+ function customerSignalBatch(value) {
175
+ return {
176
+ ...value,
177
+ results: value.results.map((item) => {
178
+ const row = record(item);
179
+ return row.data ? { ...row, data: customerSignalResult(row.data) } : row;
180
+ })
181
+ };
182
+ }
127
183
  function batchOptions() {
128
184
  return {
129
185
  concurrency: numberFlag("concurrency"),
@@ -159,10 +215,22 @@ function batchOutput(value) {
159
215
  });
160
216
  }
161
217
  function dryRunOutput(value) {
162
- output(value, () => {
163
- process.stdout.write(`Planned ${value.inputCount} ${value.capability} request(s).
218
+ const raw = record(value.raw);
219
+ const normalized = {
220
+ ...value,
221
+ freshInputCount: Number(value.freshInputCount ?? raw.fresh_input_count ?? value.inputCount),
222
+ uniqueFreshInputCount: Number(value.uniqueFreshInputCount ?? raw.unique_fresh_input_count ?? value.inputCount),
223
+ inputDuplicatesSuppressed: Number(value.inputDuplicatesSuppressed ?? raw.input_duplicates_suppressed ?? 0),
224
+ uniqueRecoveryReadCount: Number(value.uniqueRecoveryReadCount ?? raw.unique_recovery_read_count ?? 0)
225
+ };
226
+ output(normalized, () => {
227
+ process.stdout.write(`Planned ${normalized.inputCount} ${normalized.capability} request(s).
164
228
  `);
165
- process.stdout.write(`Maximum estimated credits: ${value.estimatedCredits.max}
229
+ if (normalized.inputDuplicatesSuppressed > 0) {
230
+ process.stdout.write(`Unique fresh tasks: ${normalized.uniqueFreshInputCount}; exact duplicates suppressed: ${normalized.inputDuplicatesSuppressed}.
231
+ `);
232
+ }
233
+ process.stdout.write(`Maximum estimated credits: ${normalized.estimatedCredits.max}
166
234
  `);
167
235
  process.stdout.write("No provider calls, jobs, writes, or credits were used.\n");
168
236
  });
@@ -216,10 +284,16 @@ function normalizeSignalsEverythingResult(request, value) {
216
284
  source: stringValue(item.source)
217
285
  };
218
286
  }).filter((item) => Boolean(item.url)) : [];
287
+ const eventDate = stringValue(signal.event_date || signal.date) || evidence[0]?.publishedAt || "";
288
+ const sourceUrl = stringValue(signal.source_url || signal.url) || evidence[0]?.url || null;
289
+ if (!eventDate || !sourceUrl || !evidence.some((item) => Boolean(item.publishedAt))) {
290
+ throw new Error("Signals Everything response violated the dated-evidence and source-URL contract.");
291
+ }
219
292
  return {
220
293
  company: { name, domain },
221
294
  title: stringValue(signal.title || signal.summary || signal.content),
222
- sourceUrl: stringValue(signal.source_url || signal.url) || null,
295
+ eventDate,
296
+ sourceUrl,
223
297
  evidence
224
298
  };
225
299
  });
@@ -245,6 +319,9 @@ function normalizeSignalsEverythingResult(request, value) {
245
319
  nextPollAfterSeconds: numberValue(value.next_poll_after_seconds),
246
320
  signals: signals2,
247
321
  signalCount: signals2.length,
322
+ ...numberValue(value.available_company_signal_count) === void 0 ? {} : {
323
+ availableCompanySignalCount: numberValue(value.available_company_signal_count)
324
+ },
248
325
  ...maxCost === void 0 ? {} : {
249
326
  costGuardrail: {
250
327
  maxCostPerQualifiedSignalUsd: maxCost,
@@ -258,6 +335,7 @@ function normalizeSignalsEverythingResult(request, value) {
258
335
  async function discoverSignalsEverything(request) {
259
336
  const body = request.signalSearchRunId ? {
260
337
  signal_search_run_id: request.signalSearchRunId,
338
+ ...request.limit === void 0 ? {} : { limit: request.limit },
261
339
  ...request.dryRun === void 0 ? {} : { dry_run: request.dryRun },
262
340
  ...request.idempotencyKey ? { idempotency_key: request.idempotencyKey } : {}
263
341
  } : {
@@ -394,7 +472,7 @@ async function findEmail() {
394
472
  return;
395
473
  }
396
474
  const result2 = await createClient().findEmails(requests, batchOptions());
397
- batchOutput(result2);
475
+ batchOutput(customerEmailBatch(result2));
398
476
  return;
399
477
  }
400
478
  const companyDomain = flag("company-domain") || flag("domain");
@@ -421,12 +499,19 @@ async function findEmail() {
421
499
  return;
422
500
  }
423
501
  const result = await createClient().findEmail(request);
424
- output(result, () => {
502
+ const publicResult = customerEmailResult(result);
503
+ output(publicResult, () => {
425
504
  process.stdout.write(`${result.email || "No email found"} (${result.verificationStatus})
505
+ `);
506
+ process.stdout.write(`Verified for sending: ${result.isVerifiedForSending}
507
+ `);
508
+ process.stdout.write(`Catch-all: ${result.isCatchAll}
426
509
  `);
427
510
  process.stdout.write(`Confidence: ${result.confidence}
428
511
  `);
429
512
  process.stdout.write(`Provider: ${result.providerUsed}
513
+ `);
514
+ process.stdout.write(`Credits used: ${result.creditsUsed || 0}
430
515
  `);
431
516
  if (result.needsReverification) {
432
517
  process.stdout.write("Send safety: stale verification; rerun with --skip-cache before sending\n");
@@ -450,7 +535,7 @@ async function verifyEmail(args) {
450
535
  ...batchOptions(),
451
536
  skipCache: hasFlag("skip-cache")
452
537
  });
453
- batchOutput(result2);
538
+ batchOutput(customerEmailBatch(result2));
454
539
  return;
455
540
  }
456
541
  const email = args[0] && !args[0].startsWith("--") ? args[0] : flag("email");
@@ -470,7 +555,8 @@ async function verifyEmail(args) {
470
555
  return;
471
556
  }
472
557
  const result = await createClient().verifyEmail(email, options);
473
- output(result, () => {
558
+ const publicResult = customerEmailResult(result);
559
+ output(publicResult, () => {
474
560
  if (result.status === "processing") {
475
561
  process.stdout.write(`Verification processing: ${result.verificationRunId}
476
562
  `);
@@ -484,6 +570,9 @@ async function verifyEmail(args) {
484
570
  Deliverable: ${result.isDeliverable}
485
571
  Catch-all: ${result.isCatchAll}
486
572
  Verdict: ${result.verificationVerdict}
573
+ `);
574
+ if (result.isMalformed) process.stdout.write("Malformed: true (rejected before provider call)\n");
575
+ process.stdout.write(`Credits used: ${result.creditsUsed || 0}
487
576
  `);
488
577
  });
489
578
  }
@@ -519,7 +608,7 @@ async function companySignals() {
519
608
  return;
520
609
  }
521
610
  const result2 = await createClient().enrichCompanies(requests, batchOptions());
522
- batchOutput(result2);
611
+ batchOutput(customerSignalBatch(result2));
523
612
  return;
524
613
  }
525
614
  const companyDomain = flag("domain") || flag("company-domain");
@@ -550,10 +639,13 @@ async function companySignals() {
550
639
  dryRunOutput(result2);
551
640
  return;
552
641
  }
553
- const result = await createClient().enrichCompanySignals(request);
642
+ const result = customerSignalResult(await createClient().enrichCompanySignals(request));
554
643
  output(result, () => {
555
644
  process.stdout.write(`Company: ${result.company.name || result.company.domain}
556
645
  Signals: ${result.signalCount}
646
+ `);
647
+ process.stdout.write(`Result source: ${result.resultReturnedFrom || "unknown"}
648
+ Credits used: ${result.creditsUsed || 0}
557
649
  `);
558
650
  for (const signal of result.signals.slice(0, 5)) {
559
651
  process.stdout.write(`- ${signal.title} [${signal.type}]
@@ -617,7 +709,10 @@ async function signals(args) {
617
709
  const startedAt = Date.now();
618
710
  while (signalDiscoveryIsPending(result.status) && result.signalSearchRunId && Date.now() - startedAt < maxWaitMs) {
619
711
  await sleep(Math.max(250, pollIntervalMs ?? (result.nextPollAfterSeconds || 5) * 1e3));
620
- result = await discoverSignalsEverything({ signalSearchRunId: result.signalSearchRunId });
712
+ result = await discoverSignalsEverything({
713
+ signalSearchRunId: result.signalSearchRunId,
714
+ limit: request.limit
715
+ });
621
716
  }
622
717
  }
623
718
  output(result, () => {
@@ -638,8 +733,15 @@ async function signals(args) {
638
733
  `);
639
734
  return;
640
735
  }
641
- process.stdout.write(`Qualified companies: ${result.signalCount}
736
+ const available = result.availableCompanySignalCount ?? result.signalCount;
737
+ process.stdout.write(`Qualified companies returned: ${result.signalCount}
642
738
  `);
739
+ if (available > result.signalCount) {
740
+ process.stdout.write(
741
+ `Retained cohort: ${available}. Expand without new acquisition: signaliz signals --signal-search-run-id ${result.signalSearchRunId} --limit ${available}
742
+ `
743
+ );
744
+ }
643
745
  const guardrail = result.costGuardrail;
644
746
  if (guardrail) {
645
747
  process.stdout.write(
@@ -648,8 +750,8 @@ async function signals(args) {
648
750
  );
649
751
  }
650
752
  for (const signal of result.signals.slice(0, 20)) {
651
- process.stdout.write(`- ${signal.company.name} (${signal.company.domain}) \u2014 ${signal.title}
652
- ${signal.sourceUrl || signal.evidence[0]?.url || ""}
753
+ process.stdout.write(`- ${signal.company.name} (${signal.company.domain}) \u2014 ${signal.eventDate} \u2014 ${signal.title}
754
+ ${signal.sourceUrl}
653
755
  `);
654
756
  }
655
757
  if (result.signalCount > 20) process.stdout.write(`Showing 20 of ${result.signalCount}; use --json for the full result.
@@ -682,7 +784,7 @@ async function signalToCopy() {
682
784
  return;
683
785
  }
684
786
  const result2 = await createClient().createSignalCopyBatch(requests, batchOptions());
685
- batchOutput(result2);
787
+ batchOutput(customerSignalBatch(result2));
686
788
  return;
687
789
  }
688
790
  const companyDomain = flag("company-domain") || flag("domain");
@@ -710,7 +812,7 @@ async function signalToCopy() {
710
812
  dryRunOutput(result2);
711
813
  return;
712
814
  }
713
- const result = await createClient().signalToCopy(request);
815
+ const result = customerSignalResult(await createClient().signalToCopy(request));
714
816
  output(result, () => {
715
817
  if (result.variations.length === 0) {
716
818
  process.stdout.write(`${String(result.raw.message || "Signal research completed without supported evidence.")}
@@ -720,6 +822,9 @@ async function signalToCopy() {
720
822
  process.stdout.write(`Strongest signal: ${result.strongestSignal}
721
823
  Confidence: ${result.confidence}
722
824
  Evidence: ${result.evidenceUrl}
825
+ `);
826
+ process.stdout.write(`Result source: ${result.resultReturnedFrom || "unknown"}
827
+ Credits used: ${result.creditsUsed || 0}
723
828
  `);
724
829
  for (const variation of result.variations) {
725
830
  process.stdout.write(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/cli",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "description": "Signaliz CLI for Signals Everything, Find Email, Verify Email, Company Signal Enrichment, and Signal to Copy AI.",
5
5
  "bin": {
6
6
  "signaliz": "dist/bin.js"