@signaliz/cli 1.0.43 → 1.0.45

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 +88 -19
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -18,6 +18,8 @@ signaliz find-email --company-domain example.com --full-name "Jane Doe" --skip-c
18
18
  signaliz verify-email jane@example.com
19
19
  # Force a fresh-provider verification instead of reusing cached proof
20
20
  signaliz verify-email jane@example.com --skip-cache
21
+ # Preview any single or batch product request without provider calls or credits
22
+ signaliz verify-email jane@example.com --dry-run --json
21
23
  # Return early when a provider check runs long, then resume the exact run
22
24
  signaliz verify-email jane@example.com --skip-cache --no-wait --json
23
25
  signaliz verify-email --verification-run-id run_... --json
@@ -67,9 +69,14 @@ generate-company-rows | signaliz company-signals --input - --jsonl --omit-raw
67
69
 
68
70
  JSONL writes one `{ "type": "result", ... }` line per input followed by one
69
71
  `{ "type": "summary", ... }` line. Input order and cardinality are preserved.
70
-
71
- If a batch submission response is lost, rerun the same command with
72
- `--idempotency-key <key>` to recover the original job without duplicate work.
72
+ Failed result lines preserve `errorCode`, `retryEligible`, and
73
+ `retryAfterSeconds` when the API supplies recovery guidance.
74
+
75
+ If a single request or batch submission response is lost, rerun the same
76
+ command with `--idempotency-key <key>` to recover the original request or job
77
+ without duplicate work. Add `--dry-run` to any product command, including one
78
+ using `--input`, to receive a conservative credit ceiling without provider
79
+ calls, jobs, writes, or spend.
73
80
 
74
81
  Batch input is capped at 5,000 records, concurrency is bounded to `1-50`, input
75
82
  order is preserved, and a failed item does not abort successful items.
package/dist/bin.js CHANGED
@@ -39,7 +39,8 @@ Common flags:
39
39
  --input <json-or-jsonl-file> Batch up to 5,000 records with any product command
40
40
  --input - Read a JSON array or JSONL batch from stdin
41
41
  --concurrency <1-50> Simultaneous API requests for batch input (default: 10)
42
- --idempotency-key <key> Reuse after an ambiguous batch submission to recover the same job
42
+ --idempotency-key <key> Reuse after an ambiguous response to recover the same request or job
43
+ --dry-run Return a no-spend plan without provider calls, jobs, or writes
43
44
  `;
44
45
  function loadConfig() {
45
46
  if (!(0, import_node_fs.existsSync)(CONFIG_FILE)) return {};
@@ -143,6 +144,15 @@ function batchOutput(value) {
143
144
  if (value.failed > 0) process.stdout.write("Use --json to inspect per-record errors.\n");
144
145
  });
145
146
  }
147
+ function dryRunOutput(value) {
148
+ output(value, () => {
149
+ process.stdout.write(`Planned ${value.inputCount} ${value.capability} request(s).
150
+ `);
151
+ process.stdout.write(`Maximum estimated credits: ${value.estimatedCredits.max}
152
+ `);
153
+ process.stdout.write("No provider calls, jobs, writes, or credits were used.\n");
154
+ });
155
+ }
146
156
  function resolveApiKey() {
147
157
  const key = process.env.SIGNALIZ_API_KEY || loadConfig().apiKey;
148
158
  if (!key) fail("No API key configured. Run: signaliz auth login");
@@ -238,7 +248,7 @@ async function auth(args) {
238
248
  async function findEmail() {
239
249
  const rows = readBatchInput();
240
250
  if (rows) {
241
- const result2 = await createClient().findEmails(rows.map((value) => {
251
+ const requests = rows.map((value) => {
242
252
  const row = record(value);
243
253
  return {
244
254
  companyDomain: row.companyDomain || row.company_domain || row.domain,
@@ -249,7 +259,13 @@ async function findEmail() {
249
259
  companyName: row.companyName || row.company_name,
250
260
  skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache")
251
261
  };
252
- }), batchOptions());
262
+ });
263
+ if (hasFlag("dry-run")) {
264
+ const result3 = await createClient().findEmails(requests, { ...batchOptions(), dryRun: true });
265
+ dryRunOutput(result3);
266
+ return;
267
+ }
268
+ const result2 = await createClient().findEmails(requests, batchOptions());
253
269
  batchOutput(result2);
254
270
  return;
255
271
  }
@@ -261,15 +277,22 @@ async function findEmail() {
261
277
  if (!companyDomain || !fullName && !(firstName && lastName)) {
262
278
  fail('Usage: signaliz find-email --company-domain example.com --full-name "Jane Doe"');
263
279
  }
264
- const result = await createClient().findEmail({
280
+ const request = {
265
281
  companyDomain,
266
282
  fullName,
267
283
  firstName,
268
284
  lastName,
269
285
  linkedinUrl,
270
286
  companyName: flag("company-name"),
271
- skipCache: hasFlag("skip-cache")
272
- });
287
+ skipCache: hasFlag("skip-cache"),
288
+ idempotencyKey: flag("idempotency-key")
289
+ };
290
+ if (hasFlag("dry-run")) {
291
+ const result2 = await createClient().findEmail({ ...request, dryRun: true });
292
+ dryRunOutput(result2);
293
+ return;
294
+ }
295
+ const result = await createClient().findEmail(request);
273
296
  output(result, () => {
274
297
  process.stdout.write(`${result.email || "No email found"} (${result.verificationStatus})
275
298
  `);
@@ -286,6 +309,15 @@ async function verifyEmail(args) {
286
309
  const rows = readBatchInput();
287
310
  if (rows) {
288
311
  const emails = rows.map((value) => typeof value === "string" ? value : String(record(value).email || ""));
312
+ if (hasFlag("dry-run")) {
313
+ const result3 = await createClient().verifyEmails(emails, {
314
+ ...batchOptions(),
315
+ skipCache: hasFlag("skip-cache"),
316
+ dryRun: true
317
+ });
318
+ dryRunOutput(result3);
319
+ return;
320
+ }
289
321
  const result2 = await createClient().verifyEmails(emails, {
290
322
  ...batchOptions(),
291
323
  skipCache: hasFlag("skip-cache")
@@ -296,13 +328,20 @@ async function verifyEmail(args) {
296
328
  const email = args[0] && !args[0].startsWith("--") ? args[0] : flag("email");
297
329
  const verificationRunId = flag("verification-run-id");
298
330
  if (!email && !verificationRunId) fail("Usage: signaliz verify-email [jane@example.com] [--verification-run-id run_...]");
299
- const result = await createClient().verifyEmail(email, {
331
+ const options = {
300
332
  skipCache: hasFlag("skip-cache"),
301
333
  verificationRunId,
302
334
  waitForResult: !hasFlag("no-wait"),
303
335
  maxWaitMs: numberFlag("max-wait-ms"),
304
- pollIntervalMs: numberFlag("poll-interval-ms")
305
- });
336
+ pollIntervalMs: numberFlag("poll-interval-ms"),
337
+ idempotencyKey: flag("idempotency-key")
338
+ };
339
+ if (hasFlag("dry-run")) {
340
+ const result2 = await createClient().verifyEmail(email, { ...options, dryRun: true });
341
+ dryRunOutput(result2);
342
+ return;
343
+ }
344
+ const result = await createClient().verifyEmail(email, options);
306
345
  output(result, () => {
307
346
  if (result.status === "processing") {
308
347
  process.stdout.write(`Verification processing: ${result.verificationRunId}
@@ -321,7 +360,7 @@ Catch-all: ${result.isCatchAll}
321
360
  async function companySignals() {
322
361
  const rows = readBatchInput();
323
362
  if (rows) {
324
- const result2 = await createClient().enrichCompanies(rows.map((value) => {
363
+ const requests = rows.map((value) => {
325
364
  const row = record(value);
326
365
  const online = row.online ?? !hasFlag("offline");
327
366
  return {
@@ -342,7 +381,13 @@ async function companySignals() {
342
381
  maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms"),
343
382
  pollIntervalMs: row.pollIntervalMs || row.poll_interval_ms || numberFlag("poll-interval-ms")
344
383
  };
345
- }), batchOptions());
384
+ });
385
+ if (hasFlag("dry-run")) {
386
+ const result3 = await createClient().enrichCompanies(requests, { ...batchOptions(), dryRun: true });
387
+ dryRunOutput(result3);
388
+ return;
389
+ }
390
+ const result2 = await createClient().enrichCompanies(requests, batchOptions());
346
391
  batchOutput(result2);
347
392
  return;
348
393
  }
@@ -350,7 +395,7 @@ async function companySignals() {
350
395
  const companyName = flag("company-name");
351
396
  const signalRunId = flag("signal-run-id");
352
397
  if (!companyDomain && !companyName && !signalRunId) fail("Usage: signaliz company-signals --domain example.com");
353
- const result = await createClient().enrichCompanySignals({
398
+ const request = {
354
399
  signalRunId,
355
400
  companyDomain,
356
401
  companyName,
@@ -366,8 +411,15 @@ async function companySignals() {
366
411
  skipCache: hasFlag("skip-cache"),
367
412
  waitForResult: !hasFlag("no-wait"),
368
413
  maxWaitMs: numberFlag("max-wait-ms"),
369
- pollIntervalMs: numberFlag("poll-interval-ms")
370
- });
414
+ pollIntervalMs: numberFlag("poll-interval-ms"),
415
+ idempotencyKey: flag("idempotency-key")
416
+ };
417
+ if (hasFlag("dry-run")) {
418
+ const result2 = await createClient().enrichCompanySignals({ ...request, dryRun: true });
419
+ dryRunOutput(result2);
420
+ return;
421
+ }
422
+ const result = await createClient().enrichCompanySignals(request);
371
423
  output(result, () => {
372
424
  process.stdout.write(`Company: ${result.company.name || result.company.domain}
373
425
  Signals: ${result.signalCount}
@@ -381,7 +433,7 @@ Signals: ${result.signalCount}
381
433
  async function signalToCopy() {
382
434
  const rows = readBatchInput();
383
435
  if (rows) {
384
- const result2 = await createClient().createSignalCopyBatch(rows.map((value) => {
436
+ const requests = rows.map((value) => {
385
437
  const row = record(value);
386
438
  return {
387
439
  companyDomain: row.companyDomain || row.company_domain || row.domain,
@@ -396,7 +448,13 @@ async function signalToCopy() {
396
448
  maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms"),
397
449
  pollIntervalMs: row.pollIntervalMs || row.poll_interval_ms || numberFlag("poll-interval-ms")
398
450
  };
399
- }), batchOptions());
451
+ });
452
+ if (hasFlag("dry-run")) {
453
+ const result3 = await createClient().createSignalCopyBatch(requests, { ...batchOptions(), dryRun: true });
454
+ dryRunOutput(result3);
455
+ return;
456
+ }
457
+ const result2 = await createClient().createSignalCopyBatch(requests, batchOptions());
400
458
  batchOutput(result2);
401
459
  return;
402
460
  }
@@ -408,7 +466,7 @@ async function signalToCopy() {
408
466
  if (!signalRunId && (!companyDomain || !personName || !title || !campaignOffer)) {
409
467
  fail('Usage: signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" --title "VP Sales" --campaign-offer "pipeline intelligence" OR signaliz signal-to-copy --signal-run-id copy_...');
410
468
  }
411
- const result = await createClient().signalToCopy({
469
+ const request = {
412
470
  companyDomain,
413
471
  personName,
414
472
  title,
@@ -418,8 +476,15 @@ async function signalToCopy() {
418
476
  skipCache: hasFlag("skip-cache"),
419
477
  enableDeepSearch: hasFlag("deep-search"),
420
478
  maxWaitMs: numberFlag("max-wait-ms"),
421
- pollIntervalMs: numberFlag("poll-interval-ms")
422
- });
479
+ pollIntervalMs: numberFlag("poll-interval-ms"),
480
+ idempotencyKey: flag("idempotency-key")
481
+ };
482
+ if (hasFlag("dry-run")) {
483
+ const result2 = await createClient().signalToCopy({ ...request, dryRun: true });
484
+ dryRunOutput(result2);
485
+ return;
486
+ }
487
+ const result = await createClient().signalToCopy(request);
423
488
  output(result, () => {
424
489
  if (result.variations.length === 0) {
425
490
  process.stdout.write(`${String(result.raw.message || "Signal research completed without supported evidence.")}
@@ -517,6 +582,10 @@ main().catch((error) => {
517
582
  error_code: signalizError?.code || "CLI_ERROR",
518
583
  message,
519
584
  retry_eligible: signalizError?.isRetryable ?? false,
585
+ ...signalizError?.retryAfter !== void 0 ? {
586
+ retry_after: signalizError.retryAfter,
587
+ retry_after_seconds: signalizError.retryAfter
588
+ } : {},
520
589
  ...signalizError?.errorType ? { error_type: signalizError.errorType } : {},
521
590
  ...signalizError?.details ? { details: signalizError.details } : {}
522
591
  }, hasFlag("json") ? 2 : void 0)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/cli",
3
- "version": "1.0.43",
3
+ "version": "1.0.45",
4
4
  "description": "Signaliz CLI for Find Email, Verify Email, Company Signal Enrichment, and Signal to Copy AI.",
5
5
  "bin": {
6
6
  "signaliz": "dist/bin.js"
@@ -28,7 +28,7 @@
28
28
  "node": ">=18"
29
29
  },
30
30
  "dependencies": {
31
- "@signaliz/sdk": "^1.0.43"
31
+ "@signaliz/sdk": "^1.0.47"
32
32
  },
33
33
  "devDependencies": {
34
34
  "tsup": "^8.0.0",