@signaliz/cli 1.0.44 → 1.0.46
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 +12 -14
- package/dist/bin.js +104 -30
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,21 +18,18 @@ 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
|
|
24
26
|
signaliz company-signals --domain example.com --research-prompt "expansion priorities"
|
|
25
|
-
# Resume a queued run in a later agent/process without duplicate spend
|
|
26
|
-
signaliz company-signals --signal-run-id run_...
|
|
27
27
|
signaliz signal-to-copy \
|
|
28
28
|
--company-domain example.com \
|
|
29
29
|
--person-name "Jane Doe" \
|
|
30
30
|
--title "VP Sales" \
|
|
31
31
|
--campaign-offer "pipeline intelligence"
|
|
32
32
|
|
|
33
|
-
# Resume a queued copy request with the returned ID only
|
|
34
|
-
signaliz signal-to-copy --signal-run-id copy_... --json
|
|
35
|
-
|
|
36
33
|
# Force fresh signals or opt into slower deep research only when needed
|
|
37
34
|
signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" \
|
|
38
35
|
--title "VP Sales" --campaign-offer "pipeline intelligence" --skip-cache --deep-search
|
|
@@ -70,20 +67,21 @@ JSONL writes one `{ "type": "result", ... }` line per input followed by one
|
|
|
70
67
|
Failed result lines preserve `errorCode`, `retryEligible`, and
|
|
71
68
|
`retryAfterSeconds` when the API supplies recovery guidance.
|
|
72
69
|
|
|
73
|
-
If a batch submission response is lost, rerun the same
|
|
74
|
-
`--idempotency-key <key>` to recover the original
|
|
70
|
+
If a single request or batch submission response is lost, rerun the same
|
|
71
|
+
command with `--idempotency-key <key>` to recover the original request or supported email job
|
|
72
|
+
without duplicate work. Add `--dry-run` to any product command, including one
|
|
73
|
+
using `--input`, to receive a conservative credit ceiling without provider
|
|
74
|
+
calls, jobs, writes, or spend.
|
|
75
75
|
|
|
76
76
|
Batch input is capped at 5,000 records, concurrency is bounded to `1-50`, input
|
|
77
77
|
order is preserved, and a failed item does not abort successful items.
|
|
78
78
|
Exact duplicate tasks are single-flighted across the full input before
|
|
79
79
|
transport. Find Email and Verify Email inputs larger than 25 use one cache-aware
|
|
80
|
-
recoverable REST job with 500-row result pages.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
deep-search requests keep the 25-row path. Signal to Copy also shares company
|
|
86
|
-
research across recipients.
|
|
80
|
+
recoverable REST job with 500-row result pages. Company Signal Enrichment and
|
|
81
|
+
Signal to Copy inputs larger than 25 are chunked client-side into synchronous
|
|
82
|
+
requests of at most 25; the CLI waits for every chunk and emits only complete
|
|
83
|
+
results or terminal per-row errors. Signal to Copy also shares company research
|
|
84
|
+
across recipients.
|
|
87
85
|
|
|
88
86
|
Connection commands are limited to access infrastructure:
|
|
89
87
|
|
package/dist/bin.js
CHANGED
|
@@ -14,12 +14,12 @@ var HELP = `Signaliz CLI
|
|
|
14
14
|
Four product commands:
|
|
15
15
|
signaliz find-email --company-domain example.com --full-name "Jane Doe" [--skip-cache]
|
|
16
16
|
signaliz verify-email [jane@example.com] [--verification-run-id run_...] [--no-wait] [--max-wait-ms 600000]
|
|
17
|
-
signaliz company-signals --domain example.com [--research-prompt "..."] [--no-summary] [--max-wait-ms
|
|
18
|
-
signaliz company-signals --signal-run-id run_...
|
|
17
|
+
signaliz company-signals --domain example.com [--research-prompt "..."] [--search-mode fast|balanced|coverage] [--no-summary] [--max-wait-ms 120000]
|
|
18
|
+
signaliz company-signals --signal-run-id run_... Read a completed run without duplicate spend
|
|
19
19
|
signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" \\
|
|
20
20
|
--title "VP Sales" --campaign-offer "pipeline intelligence" [--signal-run-id run_...] \\
|
|
21
|
-
[--skip-cache] [--deep-search] [--max-wait-ms
|
|
22
|
-
signaliz signal-to-copy --signal-run-id copy_...
|
|
21
|
+
[--skip-cache] [--deep-search] [--max-wait-ms 120000]
|
|
22
|
+
signaliz signal-to-copy --signal-run-id copy_... Reuse a completed signal run
|
|
23
23
|
|
|
24
24
|
Access and connection:
|
|
25
25
|
signaliz auth login
|
|
@@ -39,7 +39,10 @@ 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
|
|
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
|
|
44
|
+
|
|
45
|
+
Company Signals and Signal to Copy always wait for complete results or terminal errors.
|
|
43
46
|
`;
|
|
44
47
|
function loadConfig() {
|
|
45
48
|
if (!(0, import_node_fs.existsSync)(CONFIG_FILE)) return {};
|
|
@@ -84,6 +87,11 @@ function csvFlag(name) {
|
|
|
84
87
|
const value = flag(name);
|
|
85
88
|
return value?.split(",").map((item) => item.trim()).filter(Boolean);
|
|
86
89
|
}
|
|
90
|
+
function companySignalSearchMode(value) {
|
|
91
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
92
|
+
if (value === "fast" || value === "balanced" || value === "coverage") return value;
|
|
93
|
+
fail("--search-mode must be fast, balanced, or coverage");
|
|
94
|
+
}
|
|
87
95
|
function readBatchInput() {
|
|
88
96
|
const path = flag("input");
|
|
89
97
|
if (!path) return null;
|
|
@@ -121,6 +129,11 @@ function batchOptions() {
|
|
|
121
129
|
compactDuplicates: !hasFlag("expand-duplicates")
|
|
122
130
|
};
|
|
123
131
|
}
|
|
132
|
+
function rejectAsyncSignalFlags() {
|
|
133
|
+
if (hasFlag("no-wait") || hasFlag("poll-interval-ms")) {
|
|
134
|
+
fail("Company Signals and Signal to Copy are always synchronous; --no-wait and --poll-interval-ms are not supported.");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
124
137
|
function batchOutput(value) {
|
|
125
138
|
if (hasFlag("jsonl")) {
|
|
126
139
|
for (const result of value.results) {
|
|
@@ -143,6 +156,15 @@ function batchOutput(value) {
|
|
|
143
156
|
if (value.failed > 0) process.stdout.write("Use --json to inspect per-record errors.\n");
|
|
144
157
|
});
|
|
145
158
|
}
|
|
159
|
+
function dryRunOutput(value) {
|
|
160
|
+
output(value, () => {
|
|
161
|
+
process.stdout.write(`Planned ${value.inputCount} ${value.capability} request(s).
|
|
162
|
+
`);
|
|
163
|
+
process.stdout.write(`Maximum estimated credits: ${value.estimatedCredits.max}
|
|
164
|
+
`);
|
|
165
|
+
process.stdout.write("No provider calls, jobs, writes, or credits were used.\n");
|
|
166
|
+
});
|
|
167
|
+
}
|
|
146
168
|
function resolveApiKey() {
|
|
147
169
|
const key = process.env.SIGNALIZ_API_KEY || loadConfig().apiKey;
|
|
148
170
|
if (!key) fail("No API key configured. Run: signaliz auth login");
|
|
@@ -238,7 +260,7 @@ async function auth(args) {
|
|
|
238
260
|
async function findEmail() {
|
|
239
261
|
const rows = readBatchInput();
|
|
240
262
|
if (rows) {
|
|
241
|
-
const
|
|
263
|
+
const requests = rows.map((value) => {
|
|
242
264
|
const row = record(value);
|
|
243
265
|
return {
|
|
244
266
|
companyDomain: row.companyDomain || row.company_domain || row.domain,
|
|
@@ -249,7 +271,13 @@ async function findEmail() {
|
|
|
249
271
|
companyName: row.companyName || row.company_name,
|
|
250
272
|
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache")
|
|
251
273
|
};
|
|
252
|
-
})
|
|
274
|
+
});
|
|
275
|
+
if (hasFlag("dry-run")) {
|
|
276
|
+
const result3 = await createClient().findEmails(requests, { ...batchOptions(), dryRun: true });
|
|
277
|
+
dryRunOutput(result3);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const result2 = await createClient().findEmails(requests, batchOptions());
|
|
253
281
|
batchOutput(result2);
|
|
254
282
|
return;
|
|
255
283
|
}
|
|
@@ -261,15 +289,22 @@ async function findEmail() {
|
|
|
261
289
|
if (!companyDomain || !fullName && !(firstName && lastName)) {
|
|
262
290
|
fail('Usage: signaliz find-email --company-domain example.com --full-name "Jane Doe"');
|
|
263
291
|
}
|
|
264
|
-
const
|
|
292
|
+
const request = {
|
|
265
293
|
companyDomain,
|
|
266
294
|
fullName,
|
|
267
295
|
firstName,
|
|
268
296
|
lastName,
|
|
269
297
|
linkedinUrl,
|
|
270
298
|
companyName: flag("company-name"),
|
|
271
|
-
skipCache: hasFlag("skip-cache")
|
|
272
|
-
|
|
299
|
+
skipCache: hasFlag("skip-cache"),
|
|
300
|
+
idempotencyKey: flag("idempotency-key")
|
|
301
|
+
};
|
|
302
|
+
if (hasFlag("dry-run")) {
|
|
303
|
+
const result2 = await createClient().findEmail({ ...request, dryRun: true });
|
|
304
|
+
dryRunOutput(result2);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const result = await createClient().findEmail(request);
|
|
273
308
|
output(result, () => {
|
|
274
309
|
process.stdout.write(`${result.email || "No email found"} (${result.verificationStatus})
|
|
275
310
|
`);
|
|
@@ -286,6 +321,15 @@ async function verifyEmail(args) {
|
|
|
286
321
|
const rows = readBatchInput();
|
|
287
322
|
if (rows) {
|
|
288
323
|
const emails = rows.map((value) => typeof value === "string" ? value : String(record(value).email || ""));
|
|
324
|
+
if (hasFlag("dry-run")) {
|
|
325
|
+
const result3 = await createClient().verifyEmails(emails, {
|
|
326
|
+
...batchOptions(),
|
|
327
|
+
skipCache: hasFlag("skip-cache"),
|
|
328
|
+
dryRun: true
|
|
329
|
+
});
|
|
330
|
+
dryRunOutput(result3);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
289
333
|
const result2 = await createClient().verifyEmails(emails, {
|
|
290
334
|
...batchOptions(),
|
|
291
335
|
skipCache: hasFlag("skip-cache")
|
|
@@ -296,13 +340,20 @@ async function verifyEmail(args) {
|
|
|
296
340
|
const email = args[0] && !args[0].startsWith("--") ? args[0] : flag("email");
|
|
297
341
|
const verificationRunId = flag("verification-run-id");
|
|
298
342
|
if (!email && !verificationRunId) fail("Usage: signaliz verify-email [jane@example.com] [--verification-run-id run_...]");
|
|
299
|
-
const
|
|
343
|
+
const options = {
|
|
300
344
|
skipCache: hasFlag("skip-cache"),
|
|
301
345
|
verificationRunId,
|
|
302
346
|
waitForResult: !hasFlag("no-wait"),
|
|
303
347
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
304
|
-
pollIntervalMs: numberFlag("poll-interval-ms")
|
|
305
|
-
|
|
348
|
+
pollIntervalMs: numberFlag("poll-interval-ms"),
|
|
349
|
+
idempotencyKey: flag("idempotency-key")
|
|
350
|
+
};
|
|
351
|
+
if (hasFlag("dry-run")) {
|
|
352
|
+
const result2 = await createClient().verifyEmail(email, { ...options, dryRun: true });
|
|
353
|
+
dryRunOutput(result2);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const result = await createClient().verifyEmail(email, options);
|
|
306
357
|
output(result, () => {
|
|
307
358
|
if (result.status === "processing") {
|
|
308
359
|
process.stdout.write(`Verification processing: ${result.verificationRunId}
|
|
@@ -319,9 +370,10 @@ Catch-all: ${result.isCatchAll}
|
|
|
319
370
|
});
|
|
320
371
|
}
|
|
321
372
|
async function companySignals() {
|
|
373
|
+
rejectAsyncSignalFlags();
|
|
322
374
|
const rows = readBatchInput();
|
|
323
375
|
if (rows) {
|
|
324
|
-
const
|
|
376
|
+
const requests = rows.map((value) => {
|
|
325
377
|
const row = record(value);
|
|
326
378
|
const online = row.online ?? !hasFlag("offline");
|
|
327
379
|
return {
|
|
@@ -334,15 +386,20 @@ async function companySignals() {
|
|
|
334
386
|
lookbackDays: row.lookbackDays || row.lookback_days || numberFlag("lookback-days"),
|
|
335
387
|
online,
|
|
336
388
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? (online && !hasFlag("shallow")),
|
|
389
|
+
searchMode: companySignalSearchMode(row.searchMode ?? row.search_mode ?? flag("search-mode")),
|
|
337
390
|
includeSummary: row.includeSummary ?? row.include_summary ?? !hasFlag("no-summary"),
|
|
338
391
|
enableOutreachIntelligence: row.enableOutreachIntelligence ?? row.enable_outreach_intelligence,
|
|
339
392
|
enablePredictiveIntelligence: row.enablePredictiveIntelligence ?? row.enable_predictive_intelligence,
|
|
340
393
|
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
341
|
-
|
|
342
|
-
maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms"),
|
|
343
|
-
pollIntervalMs: row.pollIntervalMs || row.poll_interval_ms || numberFlag("poll-interval-ms")
|
|
394
|
+
maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms")
|
|
344
395
|
};
|
|
345
|
-
})
|
|
396
|
+
});
|
|
397
|
+
if (hasFlag("dry-run")) {
|
|
398
|
+
const result3 = await createClient().enrichCompanies(requests, { ...batchOptions(), dryRun: true });
|
|
399
|
+
dryRunOutput(result3);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const result2 = await createClient().enrichCompanies(requests, batchOptions());
|
|
346
403
|
batchOutput(result2);
|
|
347
404
|
return;
|
|
348
405
|
}
|
|
@@ -350,7 +407,7 @@ async function companySignals() {
|
|
|
350
407
|
const companyName = flag("company-name");
|
|
351
408
|
const signalRunId = flag("signal-run-id");
|
|
352
409
|
if (!companyDomain && !companyName && !signalRunId) fail("Usage: signaliz company-signals --domain example.com");
|
|
353
|
-
const
|
|
410
|
+
const request = {
|
|
354
411
|
signalRunId,
|
|
355
412
|
companyDomain,
|
|
356
413
|
companyName,
|
|
@@ -360,14 +417,20 @@ async function companySignals() {
|
|
|
360
417
|
lookbackDays: numberFlag("lookback-days"),
|
|
361
418
|
online: !hasFlag("offline"),
|
|
362
419
|
enableDeepSearch: !hasFlag("offline") && !hasFlag("shallow"),
|
|
420
|
+
searchMode: companySignalSearchMode(flag("search-mode")),
|
|
363
421
|
includeSummary: !hasFlag("no-summary"),
|
|
364
422
|
enableOutreachIntelligence: hasFlag("outreach-intelligence") || void 0,
|
|
365
423
|
enablePredictiveIntelligence: hasFlag("predictive-intelligence") || void 0,
|
|
366
424
|
skipCache: hasFlag("skip-cache"),
|
|
367
|
-
waitForResult: !hasFlag("no-wait"),
|
|
368
425
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
369
|
-
|
|
370
|
-
}
|
|
426
|
+
idempotencyKey: flag("idempotency-key")
|
|
427
|
+
};
|
|
428
|
+
if (hasFlag("dry-run")) {
|
|
429
|
+
const result2 = await createClient().enrichCompanySignals({ ...request, dryRun: true });
|
|
430
|
+
dryRunOutput(result2);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const result = await createClient().enrichCompanySignals(request);
|
|
371
434
|
output(result, () => {
|
|
372
435
|
process.stdout.write(`Company: ${result.company.name || result.company.domain}
|
|
373
436
|
Signals: ${result.signalCount}
|
|
@@ -379,9 +442,10 @@ Signals: ${result.signalCount}
|
|
|
379
442
|
});
|
|
380
443
|
}
|
|
381
444
|
async function signalToCopy() {
|
|
445
|
+
rejectAsyncSignalFlags();
|
|
382
446
|
const rows = readBatchInput();
|
|
383
447
|
if (rows) {
|
|
384
|
-
const
|
|
448
|
+
const requests = rows.map((value) => {
|
|
385
449
|
const row = record(value);
|
|
386
450
|
return {
|
|
387
451
|
companyDomain: row.companyDomain || row.company_domain || row.domain,
|
|
@@ -392,11 +456,15 @@ async function signalToCopy() {
|
|
|
392
456
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
393
457
|
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
394
458
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? hasFlag("deep-search"),
|
|
395
|
-
|
|
396
|
-
maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms"),
|
|
397
|
-
pollIntervalMs: row.pollIntervalMs || row.poll_interval_ms || numberFlag("poll-interval-ms")
|
|
459
|
+
maxWaitMs: row.maxWaitMs || row.max_wait_ms || numberFlag("max-wait-ms")
|
|
398
460
|
};
|
|
399
|
-
})
|
|
461
|
+
});
|
|
462
|
+
if (hasFlag("dry-run")) {
|
|
463
|
+
const result3 = await createClient().createSignalCopyBatch(requests, { ...batchOptions(), dryRun: true });
|
|
464
|
+
dryRunOutput(result3);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const result2 = await createClient().createSignalCopyBatch(requests, batchOptions());
|
|
400
468
|
batchOutput(result2);
|
|
401
469
|
return;
|
|
402
470
|
}
|
|
@@ -408,7 +476,7 @@ async function signalToCopy() {
|
|
|
408
476
|
if (!signalRunId && (!companyDomain || !personName || !title || !campaignOffer)) {
|
|
409
477
|
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
478
|
}
|
|
411
|
-
const
|
|
479
|
+
const request = {
|
|
412
480
|
companyDomain,
|
|
413
481
|
personName,
|
|
414
482
|
title,
|
|
@@ -418,8 +486,14 @@ async function signalToCopy() {
|
|
|
418
486
|
skipCache: hasFlag("skip-cache"),
|
|
419
487
|
enableDeepSearch: hasFlag("deep-search"),
|
|
420
488
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
421
|
-
|
|
422
|
-
}
|
|
489
|
+
idempotencyKey: flag("idempotency-key")
|
|
490
|
+
};
|
|
491
|
+
if (hasFlag("dry-run")) {
|
|
492
|
+
const result2 = await createClient().signalToCopy({ ...request, dryRun: true });
|
|
493
|
+
dryRunOutput(result2);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const result = await createClient().signalToCopy(request);
|
|
423
497
|
output(result, () => {
|
|
424
498
|
if (result.variations.length === 0) {
|
|
425
499
|
process.stdout.write(`${String(result.raw.message || "Signal research completed without supported evidence.")}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaliz/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.46",
|
|
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.
|
|
31
|
+
"@signaliz/sdk": "^1.0.47"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"tsup": "^8.0.0",
|