@signaliz/cli 1.0.57 → 1.0.60
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 +34 -16
- package/dist/bin.js +406 -30
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -55,8 +55,20 @@ signaliz find-email --input contacts.jsonl --concurrency 20 --json
|
|
|
55
55
|
signaliz verify-email --input emails.json --concurrency 20 --json
|
|
56
56
|
signaliz company-signals --input companies.jsonl --concurrency 5 --json
|
|
57
57
|
signaliz signal-to-copy --input copy-requests.jsonl --concurrency 5 --json
|
|
58
|
+
|
|
59
|
+
# Yield an agent turn immediately for a durable >25-row batch.
|
|
60
|
+
# The response includes both job_id and the actual idempotency_key.
|
|
61
|
+
signaliz company-signals --input companies.jsonl --no-wait --json
|
|
62
|
+
signaliz company-signals --job-id job_... --idempotency-key key_... --json
|
|
63
|
+
signaliz signal-to-copy --input copy-requests.jsonl --no-wait --json
|
|
64
|
+
signaliz signal-to-copy --job-id job_... --idempotency-key key_... --json
|
|
58
65
|
```
|
|
59
66
|
|
|
67
|
+
Retrieve completed Company/Copy result pages within seven days. If retention
|
|
68
|
+
expires, the CLI returns non-retryable `BATCH_RESULTS_EXPIRED`; do not
|
|
69
|
+
automatically rerun the submission because provider work may already have been
|
|
70
|
+
performed.
|
|
71
|
+
|
|
60
72
|
The CLI compacts exact duplicate successes by default: the first row contains
|
|
61
73
|
the full result and repeats contain `duplicateOf` pointing to its zero-based
|
|
62
74
|
input index. Use `--expand-duplicates` only when every repeated row must contain
|
|
@@ -97,30 +109,36 @@ they reduce the ceiling.
|
|
|
97
109
|
|
|
98
110
|
Batch input is capped at 5,000 records, concurrency is bounded to `1-50`, input
|
|
99
111
|
order is preserved, and a failed item does not abort successful items.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
Synchronous exact duplicates are single-flighted. Durable Company/Copy
|
|
113
|
+
submissions preserve every row and index so idempotency stays stable across
|
|
114
|
+
REST, MCP, SDK, and CLI recovery. The four row-oriented core products use one
|
|
115
|
+
recoverable REST job for inputs larger than 25; the CLI waits by default or
|
|
116
|
+
returns `job_id`, `idempotency_key`, and an exact resume command with
|
|
117
|
+
`--no-wait`. Find Email, Verify Email, and Company Signal Enrichment use 25-row
|
|
118
|
+
pages; Signal to Copy uses 100-row pages. Large Find Email and Verify Email
|
|
119
|
+
batches honor `--max-wait-ms` and `--poll-interval-ms`. Durable Signal to Copy jobs use
|
|
120
|
+
persisted, eligible company-signal data only and never start live providers or
|
|
121
|
+
deep research. Large Copy inputs with fresh, deep, skip-cache, per-row
|
|
122
|
+
idempotency, or synchronous-only controls fail locally before HTTP; split those
|
|
123
|
+
requests into batches of at most 25. Company Signal `signal_run_id` recovery
|
|
124
|
+
rows likewise stay in direct batches of at most 25. Large Company Signal jobs
|
|
125
|
+
persist bounded result pages and exclude rejected candidate-evidence
|
|
126
|
+
diagnostics; use `--include-candidate-evidence` only with batches of at most 25.
|
|
111
127
|
|
|
112
128
|
Every command uses the authenticated workspace. Find Email and Verify Email
|
|
113
129
|
honor that workspace's configured cache window; eligible hits cost 0 credits,
|
|
114
|
-
while fresh discovery or verification is charged on every plan.
|
|
115
|
-
and Pay-As-You-Go include fresh Company Signals and
|
|
116
|
-
|
|
117
|
-
|
|
130
|
+
while fresh discovery or verification is charged on every plan. Builder, Team,
|
|
131
|
+
Agency, and Pay-As-You-Go include fresh Company Signals. Team and Agency also
|
|
132
|
+
include Unlimited Signal to Copy AI; Signal to Copy remains callable on other
|
|
133
|
+
plans under the standard product contract. These plans still check eligible
|
|
134
|
+
workspace signal data first even when Company Signals is set to No cache.
|
|
135
|
+
`--lookback-days` remains a hard evidence-age bound for both
|
|
118
136
|
cached and fresh Company Signals and Signal to Copy results.
|
|
119
137
|
|
|
120
138
|
Signals Everything is a query-first company discovery command rather than a
|
|
121
139
|
row batch. It returns only dated, source-linked signals that contain both a
|
|
122
140
|
company name and company domain. The default request is 100 companies and the
|
|
123
|
-
maximum is 1,000. It is included on Team and Agency plans, is resumable with
|
|
141
|
+
maximum is 1,000. It is included on Builder, Team, and Agency plans, is resumable with
|
|
124
142
|
`signal_search_run_id`, and reports a strict source-cost guardrail: results are
|
|
125
143
|
only returned when source cost is below $0.01 per qualified company. A request
|
|
126
144
|
is a ceiling, not a promise: it can return fewer results when public evidence
|
package/dist/bin.js
CHANGED
|
@@ -14,13 +14,19 @@ var HELP = `Signaliz CLI
|
|
|
14
14
|
Five product commands:
|
|
15
15
|
signaliz find-email --company-domain example.com --full-name "Jane Doe" [--skip-cache]
|
|
16
16
|
signaliz find-email --run-id run_... Resume an existing Find Email run without duplicate spend
|
|
17
|
+
signaliz find-email --job-id job_... Resume an existing Find Email batch without redispatch
|
|
17
18
|
signaliz verify-email [jane@example.com] [--verification-run-id run_...] [--no-wait] [--max-wait-ms 600000]
|
|
19
|
+
signaliz verify-email --job-id job_... Resume an existing Verify Email batch without redispatch
|
|
18
20
|
signaliz company-signals --domain example.com [--research-prompt "..."] [--search-mode fast|balanced|coverage] [--include-candidate-evidence] [--no-summary] [--max-wait-ms 120000]
|
|
21
|
+
signaliz company-signals --input companies.json --no-wait Submit a durable >25-row batch and return its job
|
|
22
|
+
signaliz company-signals --job-id job_... Resume an existing Company Signals batch without redispatch
|
|
19
23
|
signaliz company-signals --signal-run-id run_... Read a completed run without duplicate spend
|
|
20
24
|
signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" \\
|
|
21
25
|
--title "VP Sales" --campaign-offer "pipeline intelligence" [--signal-run-id run_...] \\
|
|
22
26
|
[--lookback-days 90] [--skip-cache] [--deep-search] [--max-wait-ms 120000]
|
|
23
27
|
signaliz signal-to-copy --signal-run-id copy_... Reuse a completed signal run
|
|
28
|
+
signaliz signal-to-copy --input recipients.json --no-wait Submit an available-data-only >25-row batch
|
|
29
|
+
signaliz signal-to-copy --job-id job_... Resume an existing Signal to Copy batch without redispatch
|
|
24
30
|
signaliz signals "companies that just got funded" [--icp-context "..."] [--limit 100] [--sources web,news] [--wait]
|
|
25
31
|
signaliz signals --signal-search-run-id run_... Resume an existing company-attributed signal search
|
|
26
32
|
|
|
@@ -44,10 +50,11 @@ Common flags:
|
|
|
44
50
|
--concurrency <1-50> Simultaneous API requests for batch input (default: 10)
|
|
45
51
|
--idempotency-key <key> Reuse after an ambiguous response to recover the same request or job
|
|
46
52
|
--run-id <run_...> Resume one existing Find Email run without dispatching new work
|
|
53
|
+
--job-id <job_...> Resume an existing core-product batch without dispatching new work
|
|
47
54
|
--icp-context <text> Optional ICP, product, or pain context that returned signals must support
|
|
48
55
|
--dry-run Return a no-spend plan without provider calls, jobs, or writes
|
|
49
56
|
|
|
50
|
-
Company Signals and Signal to Copy
|
|
57
|
+
Company Signals and Signal to Copy wait by default. For a durable batch larger than 25 rows, use --no-wait to return job_id + idempotency_key immediately, then resume with --job-id. Large Company Signal batches exclude candidate-evidence diagnostics; split --include-candidate-evidence requests into batches of at most 25. Large Signal to Copy batches are available-data-only. Signals Everything is asynchronous by default; use --wait to poll until it completes.
|
|
51
58
|
`;
|
|
52
59
|
function loadConfig() {
|
|
53
60
|
if (!(0, import_node_fs.existsSync)(CONFIG_FILE)) return {};
|
|
@@ -88,6 +95,12 @@ function numberFlag(name) {
|
|
|
88
95
|
if (!Number.isFinite(parsed)) fail(`--${name} must be a number`);
|
|
89
96
|
return parsed;
|
|
90
97
|
}
|
|
98
|
+
function requireIntegerInRange(value, name, minimum, maximum) {
|
|
99
|
+
if (value === void 0) return;
|
|
100
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum) {
|
|
101
|
+
throw new RangeError(`${name} must be an integer between ${minimum} and ${maximum}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
91
104
|
function csvFlag(name) {
|
|
92
105
|
const value = flag(name);
|
|
93
106
|
return value?.split(",").map((item) => item.trim()).filter(Boolean);
|
|
@@ -127,37 +140,191 @@ function readBatchInput() {
|
|
|
127
140
|
function record(value) {
|
|
128
141
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
129
142
|
}
|
|
130
|
-
function
|
|
143
|
+
function safeNonNegativeNumber(value) {
|
|
144
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
145
|
+
const numeric = Number(value);
|
|
146
|
+
return Number.isFinite(numeric) && numeric >= 0 ? numeric : null;
|
|
147
|
+
}
|
|
148
|
+
function customerEmailBillingMetadata(value) {
|
|
149
|
+
const source = record(value);
|
|
150
|
+
const safe = {};
|
|
151
|
+
if (typeof source.result_returned_from === "string") safe.result_returned_from = source.result_returned_from;
|
|
152
|
+
for (const field of ["cache_hit", "fresh_enrichment_used", "live_provider_called", "openrouter_called", "byo_openrouter_used"]) {
|
|
153
|
+
if (typeof source[field] === "boolean") safe[field] = source[field];
|
|
154
|
+
}
|
|
155
|
+
for (const field of ["credits_used", "credits_charged", "estimated_external_cost_usd"]) {
|
|
156
|
+
const numeric = safeNonNegativeNumber(source[field]);
|
|
157
|
+
if (numeric !== null) safe[field] = numeric;
|
|
158
|
+
}
|
|
159
|
+
return safe;
|
|
160
|
+
}
|
|
161
|
+
function customerEmailResult(value, kind) {
|
|
131
162
|
const result = record(value);
|
|
132
163
|
const raw = record(result.raw);
|
|
133
164
|
if (String(result.status || "").toLowerCase() === "processing") {
|
|
134
|
-
const
|
|
135
|
-
const
|
|
165
|
+
const verificationRunId2 = result.verificationRunId ?? raw.verification_run_id;
|
|
166
|
+
const runId2 = result.runId ?? raw.run_id ?? verificationRunId2;
|
|
136
167
|
return {
|
|
137
168
|
success: true,
|
|
138
169
|
status: "processing",
|
|
139
170
|
email: null,
|
|
140
|
-
run_id:
|
|
141
|
-
...
|
|
171
|
+
run_id: runId2,
|
|
172
|
+
...verificationRunId2 ? { verification_run_id: verificationRunId2 } : {},
|
|
142
173
|
next_poll_after_seconds: result.nextPollAfterSeconds ?? raw.next_poll_after_seconds,
|
|
143
|
-
suggested_action: result.suggestedAction ?? raw.suggested_action ?? (
|
|
174
|
+
suggested_action: result.suggestedAction ?? raw.suggested_action ?? (verificationRunId2 ? "retry_with_verification_run_id" : "retry_with_run_id")
|
|
144
175
|
};
|
|
145
176
|
}
|
|
146
177
|
const creditsUsed = Number(result.creditsUsed ?? raw.credits_used ?? 0);
|
|
147
|
-
|
|
178
|
+
const base = {
|
|
148
179
|
email: typeof result.email === "string" && result.email.trim() ? result.email.trim() : null,
|
|
149
180
|
status: "completed",
|
|
150
181
|
success: result.success === true,
|
|
151
|
-
is_valid: typeof raw.is_valid === "boolean" ? raw.is_valid : result.
|
|
182
|
+
is_valid: typeof result.isValid === "boolean" ? result.isValid : typeof raw.is_valid === "boolean" ? raw.is_valid : result.isVerified ?? false,
|
|
152
183
|
credits_used: Number.isFinite(creditsUsed) && creditsUsed >= 0 ? creditsUsed : 0
|
|
153
184
|
};
|
|
185
|
+
if (kind === "find") {
|
|
186
|
+
const verifiedForSending2 = typeof result.isVerifiedForSending === "boolean" ? result.isVerifiedForSending : raw.verified_for_sending === true;
|
|
187
|
+
const isCatchAll2 = typeof result.isCatchAll === "boolean" ? result.isCatchAll : raw.email_is_catch_all === true || raw.is_catch_all === true;
|
|
188
|
+
const verificationStatus2 = String(
|
|
189
|
+
result.verificationStatus ?? raw.verification_status ?? raw.deliverability_status ?? (verifiedForSending2 ? "valid" : "unknown")
|
|
190
|
+
).toLowerCase();
|
|
191
|
+
const deliverabilityStatus2 = String(
|
|
192
|
+
result.deliverabilityStatus ?? raw.deliverability_status ?? verificationStatus2
|
|
193
|
+
).toLowerCase();
|
|
194
|
+
const verificationVerdict2 = String(
|
|
195
|
+
result.verificationVerdict ?? raw.verification_verdict ?? verificationStatus2
|
|
196
|
+
).toLowerCase();
|
|
197
|
+
const billingMetadata2 = customerEmailBillingMetadata(
|
|
198
|
+
Object.keys(record(result.billingMetadata)).length > 0 ? result.billingMetadata : raw.billing_metadata
|
|
199
|
+
);
|
|
200
|
+
const historicalBillingMetadata2 = customerEmailBillingMetadata(
|
|
201
|
+
Object.keys(record(result.historicalBillingMetadata)).length > 0 ? result.historicalBillingMetadata : raw.historical_billing_metadata
|
|
202
|
+
);
|
|
203
|
+
const cacheHit2 = typeof raw.cache_hit === "boolean" ? raw.cache_hit : result.cacheHit === true;
|
|
204
|
+
const negativeCacheHit2 = typeof raw.negative_cache_hit === "boolean" ? raw.negative_cache_hit : result.negativeCacheHit === true;
|
|
205
|
+
const resultReturnedFrom = result.resultReturnedFrom ?? raw.result_returned_from ?? null;
|
|
206
|
+
const freshEnrichmentUsed = typeof raw.fresh_enrichment_used === "boolean" ? raw.fresh_enrichment_used : result.freshEnrichmentUsed === true;
|
|
207
|
+
const liveProviderCalled = typeof raw.live_provider_called === "boolean" ? raw.live_provider_called : result.liveProviderCalled === true;
|
|
208
|
+
const normalizedBillingMetadata = {
|
|
209
|
+
...billingMetadata2,
|
|
210
|
+
...resultReturnedFrom ? { result_returned_from: resultReturnedFrom } : {},
|
|
211
|
+
cache_hit: cacheHit2,
|
|
212
|
+
fresh_enrichment_used: freshEnrichmentUsed,
|
|
213
|
+
credits_used: base.credits_used,
|
|
214
|
+
live_provider_called: liveProviderCalled
|
|
215
|
+
};
|
|
216
|
+
const estimatedExternalCostUsd2 = safeNonNegativeNumber(
|
|
217
|
+
result.estimatedExternalCostUsd ?? raw.estimated_external_cost_usd
|
|
218
|
+
);
|
|
219
|
+
return {
|
|
220
|
+
...base,
|
|
221
|
+
is_valid: verifiedForSending2,
|
|
222
|
+
verification_status: verificationStatus2,
|
|
223
|
+
deliverability_status: deliverabilityStatus2,
|
|
224
|
+
verification_verdict: verificationVerdict2,
|
|
225
|
+
verified_for_sending: verifiedForSending2,
|
|
226
|
+
is_deliverable: typeof result.isDeliverable === "boolean" ? result.isDeliverable && verifiedForSending2 : verifiedForSending2,
|
|
227
|
+
email_is_catch_all: isCatchAll2,
|
|
228
|
+
is_catch_all: isCatchAll2,
|
|
229
|
+
verification_source: result.verificationSource ?? raw.verification_source ?? result.providerUsed ?? "email_finder",
|
|
230
|
+
...result.verificationObservedAt ?? raw.verification_observed_at ? { verification_observed_at: result.verificationObservedAt ?? raw.verification_observed_at } : {},
|
|
231
|
+
failure_reason: result.failureReason ?? raw.failure_reason ?? (verifiedForSending2 ? "none" : "no_verified_email_found"),
|
|
232
|
+
cache_hit: cacheHit2,
|
|
233
|
+
negative_cache_hit: negativeCacheHit2,
|
|
234
|
+
negative_cache_ttl_seconds: safeNonNegativeNumber(
|
|
235
|
+
result.negativeCacheTtlSeconds ?? raw.negative_cache_ttl_seconds
|
|
236
|
+
),
|
|
237
|
+
cache_tier: result.cacheTier ?? raw.cache_tier ?? null,
|
|
238
|
+
result_returned_from: resultReturnedFrom,
|
|
239
|
+
fresh_enrichment_used: freshEnrichmentUsed,
|
|
240
|
+
live_provider_called: liveProviderCalled,
|
|
241
|
+
billing_metadata: normalizedBillingMetadata,
|
|
242
|
+
...Object.keys(historicalBillingMetadata2).length > 0 ? { historical_billing_metadata: historicalBillingMetadata2 } : {},
|
|
243
|
+
...estimatedExternalCostUsd2 !== null ? { estimated_external_cost_usd: estimatedExternalCostUsd2 } : {},
|
|
244
|
+
...result.runId ?? raw.run_id ? { run_id: result.runId ?? raw.run_id } : {},
|
|
245
|
+
...raw.cache_publication_status ? {
|
|
246
|
+
cache_publication_status: raw.cache_publication_status,
|
|
247
|
+
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
248
|
+
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
249
|
+
} : {}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const verificationStatus = String(
|
|
253
|
+
result.verificationStatus ?? raw.verification_status ?? result.verificationVerdict ?? raw.verification_verdict ?? raw.deliverability_status ?? "unknown"
|
|
254
|
+
).toLowerCase();
|
|
255
|
+
const deliverabilityStatus = String(
|
|
256
|
+
result.deliverabilityStatus ?? raw.deliverability_status ?? verificationStatus
|
|
257
|
+
).toLowerCase();
|
|
258
|
+
const verificationVerdict = String(
|
|
259
|
+
result.verificationVerdict ?? raw.verification_verdict ?? verificationStatus
|
|
260
|
+
).toLowerCase();
|
|
261
|
+
const verifiedForSending = typeof result.verifiedForSending === "boolean" ? result.verifiedForSending : raw.verified_for_sending === true;
|
|
262
|
+
const isDeliverable = typeof result.isDeliverable === "boolean" ? result.isDeliverable : raw.is_deliverable === true;
|
|
263
|
+
const isCatchAll = typeof result.isCatchAll === "boolean" ? result.isCatchAll : raw.email_is_catch_all === true || raw.is_catch_all === true;
|
|
264
|
+
const isRoleAccount = typeof result.isRoleAccount === "boolean" ? result.isRoleAccount : raw.is_role_account === true;
|
|
265
|
+
const isMalformed = typeof result.isMalformed === "boolean" ? result.isMalformed : raw.is_malformed === true;
|
|
266
|
+
const quality = typeof result.quality === "string" ? result.quality : typeof raw.quality === "string" ? raw.quality : null;
|
|
267
|
+
const recommendation = typeof result.recommendation === "string" ? result.recommendation : typeof raw.recommendation === "string" ? raw.recommendation : verifiedForSending ? "send" : ["unknown", "verifier_error"].includes(verificationStatus) ? "manual_review" : "do_not_send";
|
|
268
|
+
const cacheHit = typeof raw.cache_hit === "boolean" ? raw.cache_hit : result.cacheHit === true;
|
|
269
|
+
const negativeCacheHit = typeof raw.negative_cache_hit === "boolean" ? raw.negative_cache_hit : result.negativeCacheHit === true;
|
|
270
|
+
const negativeCacheTtlSeconds = safeNonNegativeNumber(
|
|
271
|
+
result.negativeCacheTtlSeconds ?? raw.negative_cache_ttl_seconds
|
|
272
|
+
);
|
|
273
|
+
const billingMetadata = customerEmailBillingMetadata(
|
|
274
|
+
Object.keys(record(result.billingMetadata)).length > 0 ? result.billingMetadata : raw.billing_metadata
|
|
275
|
+
);
|
|
276
|
+
const historicalBillingMetadata = customerEmailBillingMetadata(
|
|
277
|
+
Object.keys(record(result.historicalBillingMetadata)).length > 0 ? result.historicalBillingMetadata : raw.historical_billing_metadata
|
|
278
|
+
);
|
|
279
|
+
const verificationRunId = result.verificationRunId ?? raw.verification_run_id ?? raw.run_id;
|
|
280
|
+
const runId = result.runId ?? raw.run_id ?? verificationRunId;
|
|
281
|
+
const estimatedExternalCostUsd = safeNonNegativeNumber(
|
|
282
|
+
result.estimatedExternalCostUsd ?? raw.estimated_external_cost_usd
|
|
283
|
+
);
|
|
284
|
+
return {
|
|
285
|
+
...base,
|
|
286
|
+
verification_status: verificationStatus,
|
|
287
|
+
deliverability_status: deliverabilityStatus,
|
|
288
|
+
verification_verdict: verificationVerdict,
|
|
289
|
+
verified_for_sending: verifiedForSending,
|
|
290
|
+
is_deliverable: isDeliverable,
|
|
291
|
+
email_is_catch_all: isCatchAll,
|
|
292
|
+
is_catch_all: isCatchAll,
|
|
293
|
+
is_role_account: isRoleAccount,
|
|
294
|
+
is_malformed: isMalformed,
|
|
295
|
+
quality,
|
|
296
|
+
recommendation,
|
|
297
|
+
smtp_status: result.smtpStatus ?? raw.smtp_status ?? (isCatchAll ? "accept_all" : verifiedForSending ? "accepted" : "not_checked"),
|
|
298
|
+
provider_status: result.providerStatus ?? raw.provider_status ?? verificationStatus,
|
|
299
|
+
verification_source: result.verificationSource ?? raw.verification_source ?? "email_verification",
|
|
300
|
+
...result.verificationObservedAt ?? raw.verification_observed_at ? { verification_observed_at: result.verificationObservedAt ?? raw.verification_observed_at } : {},
|
|
301
|
+
failure_reason: result.failureReason ?? raw.failure_reason ?? (verifiedForSending ? "none" : isCatchAll ? "catch_all_domain_not_send_safe" : "verification_not_send_safe"),
|
|
302
|
+
cache_hit: cacheHit,
|
|
303
|
+
negative_cache_hit: negativeCacheHit,
|
|
304
|
+
negative_cache_ttl_seconds: negativeCacheTtlSeconds,
|
|
305
|
+
cache_tier: result.cacheTier ?? raw.cache_tier ?? null,
|
|
306
|
+
result_returned_from: result.resultReturnedFrom ?? raw.result_returned_from ?? null,
|
|
307
|
+
fresh_enrichment_used: typeof raw.fresh_enrichment_used === "boolean" ? raw.fresh_enrichment_used : result.freshEnrichmentUsed === true,
|
|
308
|
+
live_provider_called: typeof raw.live_provider_called === "boolean" ? raw.live_provider_called : result.liveProviderCalled === true,
|
|
309
|
+
billing_replayed: typeof raw.billing_replayed === "boolean" ? raw.billing_replayed : result.billingReplayed === true,
|
|
310
|
+
billing_metadata: billingMetadata,
|
|
311
|
+
...Object.keys(historicalBillingMetadata).length > 0 ? { historical_billing_metadata: historicalBillingMetadata } : {},
|
|
312
|
+
...estimatedExternalCostUsd !== null ? { estimated_external_cost_usd: estimatedExternalCostUsd } : {},
|
|
313
|
+
...verificationRunId ? { verification_run_id: verificationRunId } : {},
|
|
314
|
+
...runId ? { run_id: runId } : {},
|
|
315
|
+
...raw.cache_publication_status ? {
|
|
316
|
+
cache_publication_status: raw.cache_publication_status,
|
|
317
|
+
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
318
|
+
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
319
|
+
} : {}
|
|
320
|
+
};
|
|
154
321
|
}
|
|
155
|
-
function customerEmailBatch(value) {
|
|
322
|
+
function customerEmailBatch(value, kind) {
|
|
156
323
|
return {
|
|
157
324
|
...value,
|
|
158
325
|
results: value.results.map((item) => {
|
|
159
326
|
const row = record(item);
|
|
160
|
-
return promoteBatchRecoveryMetadata(row.data ? { ...row, data: customerEmailResult(row.data) } : row);
|
|
327
|
+
return promoteBatchRecoveryMetadata(row.data ? { ...row, data: customerEmailResult(row.data, kind) } : row);
|
|
161
328
|
})
|
|
162
329
|
};
|
|
163
330
|
}
|
|
@@ -199,14 +366,40 @@ function batchOptions() {
|
|
|
199
366
|
return {
|
|
200
367
|
concurrency: numberFlag("concurrency"),
|
|
201
368
|
idempotencyKey: flag("idempotency-key"),
|
|
202
|
-
compactDuplicates: !hasFlag("expand-duplicates")
|
|
369
|
+
compactDuplicates: !hasFlag("expand-duplicates"),
|
|
370
|
+
maxWaitMs: numberFlag("max-wait-ms"),
|
|
371
|
+
pollIntervalMs: numberFlag("poll-interval-ms")
|
|
203
372
|
};
|
|
204
373
|
}
|
|
205
|
-
function
|
|
206
|
-
if (hasFlag("no-wait")
|
|
207
|
-
|
|
374
|
+
function rejectDurableNoWaitPollingFlags(label) {
|
|
375
|
+
if (!hasFlag("no-wait")) return;
|
|
376
|
+
const conflicts = ["max-wait-ms", "poll-interval-ms", "concurrency"].filter(hasFlag);
|
|
377
|
+
if (conflicts.length > 0) {
|
|
378
|
+
fail(`${label} --no-wait cannot be combined with ${conflicts.map((name) => `--${name}`).join(", ")}.`);
|
|
208
379
|
}
|
|
209
380
|
}
|
|
381
|
+
function recoverableJobOutput(value, command) {
|
|
382
|
+
const resumeCommand = `signaliz ${command} --job-id ${value.jobId} --idempotency-key ${value.idempotencyKey}`;
|
|
383
|
+
const payload = {
|
|
384
|
+
success: true,
|
|
385
|
+
status: value.status,
|
|
386
|
+
capability: value.capability,
|
|
387
|
+
job_id: value.jobId,
|
|
388
|
+
idempotency_key: value.idempotencyKey,
|
|
389
|
+
total: value.total,
|
|
390
|
+
next_poll_after_seconds: value.nextPollAfterSeconds,
|
|
391
|
+
suggested_action: "check_job_status",
|
|
392
|
+
resume_command: resumeCommand
|
|
393
|
+
};
|
|
394
|
+
output(payload, () => {
|
|
395
|
+
process.stdout.write(`Durable ${command} batch submitted: ${value.jobId}
|
|
396
|
+
`);
|
|
397
|
+
process.stdout.write(`Idempotency key: ${value.idempotencyKey}
|
|
398
|
+
`);
|
|
399
|
+
process.stdout.write(`Resume with: ${resumeCommand}
|
|
400
|
+
`);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
210
403
|
function batchOutput(value) {
|
|
211
404
|
if (hasFlag("jsonl")) {
|
|
212
405
|
for (const result of value.results) {
|
|
@@ -493,12 +686,41 @@ async function auth(args) {
|
|
|
493
686
|
fail("Usage: signaliz auth <login|set-key|workspace|status>");
|
|
494
687
|
}
|
|
495
688
|
async function findEmail() {
|
|
689
|
+
const jobId = flag("job-id");
|
|
690
|
+
if (jobId) {
|
|
691
|
+
const conflicts = [
|
|
692
|
+
"input",
|
|
693
|
+
"dry-run",
|
|
694
|
+
"company-domain",
|
|
695
|
+
"domain",
|
|
696
|
+
"full-name",
|
|
697
|
+
"first-name",
|
|
698
|
+
"last-name",
|
|
699
|
+
"linkedin-url",
|
|
700
|
+
"company-name",
|
|
701
|
+
"run-id",
|
|
702
|
+
"skip-cache"
|
|
703
|
+
].filter(hasFlag);
|
|
704
|
+
if (conflicts.length > 0) {
|
|
705
|
+
fail(`Find Email --job-id cannot be combined with ${conflicts.map((name) => `--${name}`).join(", ")}.`);
|
|
706
|
+
}
|
|
707
|
+
const result2 = await createClient().resumeFindEmailBatch(jobId, {
|
|
708
|
+
pageSize: numberFlag("page-size"),
|
|
709
|
+
maxWaitMs: numberFlag("max-wait-ms"),
|
|
710
|
+
pollIntervalMs: numberFlag("poll-interval-ms"),
|
|
711
|
+
compactDuplicates: !hasFlag("expand-duplicates"),
|
|
712
|
+
idempotencyKey: flag("idempotency-key")
|
|
713
|
+
});
|
|
714
|
+
batchOutput(customerEmailBatch(result2, "find"));
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
496
717
|
const rows = readBatchInput();
|
|
497
718
|
if (rows) {
|
|
498
719
|
const requests = rows.map((value) => {
|
|
499
720
|
const row = record(value);
|
|
500
721
|
const runId2 = row.runId || row.run_id;
|
|
501
|
-
|
|
722
|
+
const idempotencyKey = row.idempotencyKey || row.idempotency_key;
|
|
723
|
+
if (runId2) return { runId: runId2, idempotencyKey };
|
|
502
724
|
return {
|
|
503
725
|
companyDomain: row.companyDomain || row.company_domain || row.domain,
|
|
504
726
|
fullName: row.fullName || row.full_name || row.name,
|
|
@@ -506,7 +728,8 @@ async function findEmail() {
|
|
|
506
728
|
lastName: row.lastName || row.last_name,
|
|
507
729
|
linkedinUrl: row.linkedinUrl || row.linkedin_url || row.linkedin,
|
|
508
730
|
companyName: row.companyName || row.company_name,
|
|
509
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache")
|
|
731
|
+
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
732
|
+
idempotencyKey
|
|
510
733
|
};
|
|
511
734
|
});
|
|
512
735
|
if (hasFlag("dry-run")) {
|
|
@@ -515,7 +738,7 @@ async function findEmail() {
|
|
|
515
738
|
return;
|
|
516
739
|
}
|
|
517
740
|
const result2 = await createClient().findEmails(requests, batchOptions());
|
|
518
|
-
batchOutput(customerEmailBatch(result2));
|
|
741
|
+
batchOutput(customerEmailBatch(result2, "find"));
|
|
519
742
|
return;
|
|
520
743
|
}
|
|
521
744
|
const companyDomain = flag("company-domain") || flag("domain");
|
|
@@ -543,7 +766,7 @@ async function findEmail() {
|
|
|
543
766
|
return;
|
|
544
767
|
}
|
|
545
768
|
const result = await createClient().findEmail(request);
|
|
546
|
-
const publicResult = customerEmailResult(result);
|
|
769
|
+
const publicResult = customerEmailResult(result, "find");
|
|
547
770
|
if (outputFailedCoreProduct(publicResult, "No verified email found")) return;
|
|
548
771
|
output(publicResult, () => {
|
|
549
772
|
if (result.status === "processing" && result.runId) {
|
|
@@ -566,9 +789,45 @@ async function findEmail() {
|
|
|
566
789
|
});
|
|
567
790
|
}
|
|
568
791
|
async function verifyEmail(args) {
|
|
792
|
+
const jobId = flag("job-id");
|
|
793
|
+
if (jobId) {
|
|
794
|
+
const positionalEmail = args[0] && !args[0].startsWith("--");
|
|
795
|
+
const conflicts = [
|
|
796
|
+
"input",
|
|
797
|
+
"dry-run",
|
|
798
|
+
"email",
|
|
799
|
+
"verification-run-id",
|
|
800
|
+
"skip-cache",
|
|
801
|
+
"no-wait"
|
|
802
|
+
].filter(hasFlag);
|
|
803
|
+
if (positionalEmail || conflicts.length > 0) {
|
|
804
|
+
const conflictList = [
|
|
805
|
+
...positionalEmail ? ["email argument"] : [],
|
|
806
|
+
...conflicts.map((name) => `--${name}`)
|
|
807
|
+
];
|
|
808
|
+
fail(`Verify Email --job-id cannot be combined with ${conflictList.join(", ")}.`);
|
|
809
|
+
}
|
|
810
|
+
const result2 = await createClient().resumeVerifyEmailBatch(jobId, {
|
|
811
|
+
pageSize: numberFlag("page-size"),
|
|
812
|
+
maxWaitMs: numberFlag("max-wait-ms"),
|
|
813
|
+
pollIntervalMs: numberFlag("poll-interval-ms"),
|
|
814
|
+
compactDuplicates: !hasFlag("expand-duplicates"),
|
|
815
|
+
idempotencyKey: flag("idempotency-key")
|
|
816
|
+
});
|
|
817
|
+
batchOutput(customerEmailBatch(result2, "verify"));
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
569
820
|
const rows = readBatchInput();
|
|
570
821
|
if (rows) {
|
|
571
|
-
const emails = rows.map((value) =>
|
|
822
|
+
const emails = rows.map((value) => {
|
|
823
|
+
if (typeof value === "string") return value;
|
|
824
|
+
const row = record(value);
|
|
825
|
+
return {
|
|
826
|
+
email: String(row.email || ""),
|
|
827
|
+
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
828
|
+
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
829
|
+
};
|
|
830
|
+
});
|
|
572
831
|
if (hasFlag("dry-run")) {
|
|
573
832
|
const result3 = await createClient().verifyEmails(emails, {
|
|
574
833
|
...batchOptions(),
|
|
@@ -582,7 +841,7 @@ async function verifyEmail(args) {
|
|
|
582
841
|
...batchOptions(),
|
|
583
842
|
skipCache: hasFlag("skip-cache")
|
|
584
843
|
});
|
|
585
|
-
batchOutput(customerEmailBatch(result2));
|
|
844
|
+
batchOutput(customerEmailBatch(result2, "verify"));
|
|
586
845
|
return;
|
|
587
846
|
}
|
|
588
847
|
const email = args[0] && !args[0].startsWith("--") ? args[0] : flag("email");
|
|
@@ -602,7 +861,7 @@ async function verifyEmail(args) {
|
|
|
602
861
|
return;
|
|
603
862
|
}
|
|
604
863
|
const result = await createClient().verifyEmail(email, options);
|
|
605
|
-
const publicResult = customerEmailResult(result);
|
|
864
|
+
const publicResult = customerEmailResult(result, "verify");
|
|
606
865
|
if (outputFailedCoreProduct(publicResult, "Email verification failed")) return;
|
|
607
866
|
output(publicResult, () => {
|
|
608
867
|
if (result.status === "processing") {
|
|
@@ -619,15 +878,62 @@ async function verifyEmail(args) {
|
|
|
619
878
|
process.stdout.write(`Success: ${publicResult.success}
|
|
620
879
|
`);
|
|
621
880
|
process.stdout.write(`Valid: ${publicResult.is_valid}
|
|
881
|
+
`);
|
|
882
|
+
process.stdout.write(`Verdict: ${publicResult.verification_status}
|
|
883
|
+
`);
|
|
884
|
+
process.stdout.write(`Recommendation: ${publicResult.recommendation}
|
|
885
|
+
`);
|
|
886
|
+
process.stdout.write(`Source: ${publicResult.verification_source}${publicResult.cache_hit === true ? " (cache)" : ""}
|
|
887
|
+
`);
|
|
888
|
+
if (publicResult.run_id) process.stdout.write(`Run ID: ${publicResult.run_id}
|
|
622
889
|
`);
|
|
623
890
|
process.stdout.write(`Credits used: ${publicResult.credits_used}
|
|
624
891
|
`);
|
|
625
892
|
});
|
|
626
893
|
}
|
|
627
894
|
async function companySignals() {
|
|
628
|
-
|
|
895
|
+
const jobId = flag("job-id");
|
|
896
|
+
if (jobId) {
|
|
897
|
+
const conflicts = [
|
|
898
|
+
"input",
|
|
899
|
+
"dry-run",
|
|
900
|
+
"domain",
|
|
901
|
+
"company-domain",
|
|
902
|
+
"company-name",
|
|
903
|
+
"signal-run-id",
|
|
904
|
+
"research-prompt",
|
|
905
|
+
"prompt",
|
|
906
|
+
"signal-types",
|
|
907
|
+
"target-signal-count",
|
|
908
|
+
"lookback-days",
|
|
909
|
+
"offline",
|
|
910
|
+
"shallow",
|
|
911
|
+
"search-mode",
|
|
912
|
+
"no-summary",
|
|
913
|
+
"outreach-intelligence",
|
|
914
|
+
"predictive-intelligence",
|
|
915
|
+
"skip-cache",
|
|
916
|
+
"include-candidate-evidence",
|
|
917
|
+
"no-wait",
|
|
918
|
+
"concurrency"
|
|
919
|
+
].filter(hasFlag);
|
|
920
|
+
if (conflicts.length > 0) {
|
|
921
|
+
fail(`Company Signals --job-id cannot be combined with ${conflicts.map((name) => `--${name}`).join(", ")}.`);
|
|
922
|
+
}
|
|
923
|
+
const result2 = await createClient().resumeCompanySignalBatch(jobId, {
|
|
924
|
+
pageSize: numberFlag("page-size"),
|
|
925
|
+
maxWaitMs: numberFlag("max-wait-ms"),
|
|
926
|
+
pollIntervalMs: numberFlag("poll-interval-ms"),
|
|
927
|
+
idempotencyKey: flag("idempotency-key"),
|
|
928
|
+
compactDuplicates: !hasFlag("expand-duplicates")
|
|
929
|
+
});
|
|
930
|
+
batchOutput(customerSignalBatch(result2));
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
rejectDurableNoWaitPollingFlags("Company Signals");
|
|
629
934
|
const rows = readBatchInput();
|
|
630
935
|
if (rows) {
|
|
936
|
+
const durableBatch = rows.length > 25;
|
|
631
937
|
const requests = rows.map((value) => {
|
|
632
938
|
const row = record(value);
|
|
633
939
|
const online = row.online ?? !hasFlag("offline");
|
|
@@ -637,8 +943,8 @@ async function companySignals() {
|
|
|
637
943
|
companyName: row.companyName || row.company_name || row.name,
|
|
638
944
|
researchPrompt: row.researchPrompt || row.research_prompt || flag("research-prompt") || flag("prompt"),
|
|
639
945
|
signalTypes: row.signalTypes || row.signal_types || csvFlag("signal-types"),
|
|
640
|
-
targetSignalCount: row.targetSignalCount
|
|
641
|
-
lookbackDays: row.lookbackDays
|
|
946
|
+
targetSignalCount: row.targetSignalCount ?? row.target_signal_count ?? numberFlag("target-signal-count"),
|
|
947
|
+
lookbackDays: row.lookbackDays ?? row.lookback_days ?? numberFlag("lookback-days"),
|
|
642
948
|
online,
|
|
643
949
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? (online && !hasFlag("shallow")),
|
|
644
950
|
searchMode: companySignalSearchMode(row.searchMode ?? row.search_mode ?? flag("search-mode")),
|
|
@@ -647,18 +953,34 @@ async function companySignals() {
|
|
|
647
953
|
enablePredictiveIntelligence: row.enablePredictiveIntelligence ?? row.enable_predictive_intelligence,
|
|
648
954
|
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
649
955
|
includeCandidateEvidence: row.includeCandidateEvidence ?? row.include_candidate_evidence ?? hasFlag("include-candidate-evidence"),
|
|
650
|
-
maxWaitMs: row.maxWaitMs
|
|
956
|
+
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
957
|
+
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
651
958
|
};
|
|
652
959
|
});
|
|
960
|
+
for (const request2 of requests) {
|
|
961
|
+
requireIntegerInRange(request2.targetSignalCount, "targetSignalCount", 1, 15);
|
|
962
|
+
requireIntegerInRange(request2.lookbackDays, "lookbackDays", 1, 365);
|
|
963
|
+
}
|
|
653
964
|
if (hasFlag("dry-run")) {
|
|
965
|
+
if (hasFlag("no-wait")) fail("Company Signals --no-wait cannot be combined with --dry-run.");
|
|
654
966
|
const result3 = await createClient().enrichCompanies(requests, { ...batchOptions(), dryRun: true });
|
|
655
967
|
dryRunOutput(result3);
|
|
656
968
|
return;
|
|
657
969
|
}
|
|
970
|
+
if (hasFlag("no-wait")) {
|
|
971
|
+
const job = await createClient().enrichCompanies(requests, {
|
|
972
|
+
...batchOptions(),
|
|
973
|
+
waitForResult: false
|
|
974
|
+
});
|
|
975
|
+
recoverableJobOutput(job, "company-signals");
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
658
978
|
const result2 = await createClient().enrichCompanies(requests, batchOptions());
|
|
659
979
|
batchOutput(customerSignalBatch(result2));
|
|
660
980
|
return;
|
|
661
981
|
}
|
|
982
|
+
if (hasFlag("no-wait")) fail("Company Signals --no-wait requires --input with more than 25 homogeneous rows.");
|
|
983
|
+
if (hasFlag("poll-interval-ms")) fail("Company Signals --poll-interval-ms requires --input or --job-id.");
|
|
662
984
|
const companyDomain = flag("domain") || flag("company-domain");
|
|
663
985
|
const companyName = flag("company-name");
|
|
664
986
|
const signalRunId = flag("signal-run-id");
|
|
@@ -807,7 +1129,7 @@ async function signals(args) {
|
|
|
807
1129
|
const identityCost = guardrail.identityResolutionCostUsd === null ? "unavailable" : `$${guardrail.identityResolutionCostUsd}`;
|
|
808
1130
|
const identityRequests = guardrail.identityProviderRequests;
|
|
809
1131
|
process.stdout.write(
|
|
810
|
-
`Identity resolution cost: ${identityCost}${identityRequests === void 0 ? "" : ` across ${identityRequests}
|
|
1132
|
+
`Identity resolution cost: ${identityCost}${identityRequests === void 0 ? "" : ` across ${identityRequests} identity lookup request${identityRequests === 1 ? "" : "s"}`}${guardrail.identityCostSource ? ` (${guardrail.identityCostSource})` : ""}.
|
|
811
1133
|
`
|
|
812
1134
|
);
|
|
813
1135
|
}
|
|
@@ -824,9 +1146,43 @@ async function signals(args) {
|
|
|
824
1146
|
});
|
|
825
1147
|
}
|
|
826
1148
|
async function signalToCopy() {
|
|
827
|
-
|
|
1149
|
+
const jobId = flag("job-id");
|
|
1150
|
+
if (jobId) {
|
|
1151
|
+
const conflicts = [
|
|
1152
|
+
"input",
|
|
1153
|
+
"dry-run",
|
|
1154
|
+
"company-domain",
|
|
1155
|
+
"domain",
|
|
1156
|
+
"person-name",
|
|
1157
|
+
"title",
|
|
1158
|
+
"campaign-offer",
|
|
1159
|
+
"offer",
|
|
1160
|
+
"research-prompt",
|
|
1161
|
+
"prompt",
|
|
1162
|
+
"lookback-days",
|
|
1163
|
+
"signal-run-id",
|
|
1164
|
+
"skip-cache",
|
|
1165
|
+
"deep-search",
|
|
1166
|
+
"no-wait",
|
|
1167
|
+
"concurrency"
|
|
1168
|
+
].filter(hasFlag);
|
|
1169
|
+
if (conflicts.length > 0) {
|
|
1170
|
+
fail(`Signal to Copy --job-id cannot be combined with ${conflicts.map((name) => `--${name}`).join(", ")}.`);
|
|
1171
|
+
}
|
|
1172
|
+
const result2 = await createClient().resumeSignalCopyBatch(jobId, {
|
|
1173
|
+
pageSize: numberFlag("page-size"),
|
|
1174
|
+
maxWaitMs: numberFlag("max-wait-ms"),
|
|
1175
|
+
pollIntervalMs: numberFlag("poll-interval-ms"),
|
|
1176
|
+
idempotencyKey: flag("idempotency-key"),
|
|
1177
|
+
compactDuplicates: !hasFlag("expand-duplicates")
|
|
1178
|
+
});
|
|
1179
|
+
batchOutput(customerSignalBatch(result2));
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
rejectDurableNoWaitPollingFlags("Signal to Copy");
|
|
828
1183
|
const rows = readBatchInput();
|
|
829
1184
|
if (rows) {
|
|
1185
|
+
const durableBatch = rows.length > 25;
|
|
830
1186
|
const requests = rows.map((value) => {
|
|
831
1187
|
const row = record(value);
|
|
832
1188
|
return {
|
|
@@ -835,22 +1191,34 @@ async function signalToCopy() {
|
|
|
835
1191
|
title: row.title,
|
|
836
1192
|
campaignOffer: row.campaignOffer || row.campaign_offer || row.offer,
|
|
837
1193
|
researchPrompt: row.researchPrompt || row.research_prompt || flag("research-prompt") || flag("prompt"),
|
|
838
|
-
lookbackDays: row.lookbackDays
|
|
1194
|
+
lookbackDays: row.lookbackDays ?? row.lookback_days ?? numberFlag("lookback-days"),
|
|
839
1195
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
840
1196
|
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
841
1197
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? hasFlag("deep-search"),
|
|
842
|
-
maxWaitMs: row.maxWaitMs
|
|
1198
|
+
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
1199
|
+
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
843
1200
|
};
|
|
844
1201
|
});
|
|
845
1202
|
if (hasFlag("dry-run")) {
|
|
1203
|
+
if (hasFlag("no-wait")) fail("Signal to Copy --no-wait cannot be combined with --dry-run.");
|
|
846
1204
|
const result3 = await createClient().createSignalCopyBatch(requests, { ...batchOptions(), dryRun: true });
|
|
847
1205
|
dryRunOutput(result3);
|
|
848
1206
|
return;
|
|
849
1207
|
}
|
|
1208
|
+
if (hasFlag("no-wait")) {
|
|
1209
|
+
const job = await createClient().createSignalCopyBatch(requests, {
|
|
1210
|
+
...batchOptions(),
|
|
1211
|
+
waitForResult: false
|
|
1212
|
+
});
|
|
1213
|
+
recoverableJobOutput(job, "signal-to-copy");
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
850
1216
|
const result2 = await createClient().createSignalCopyBatch(requests, batchOptions());
|
|
851
1217
|
batchOutput(customerSignalBatch(result2));
|
|
852
1218
|
return;
|
|
853
1219
|
}
|
|
1220
|
+
if (hasFlag("no-wait")) fail("Signal to Copy --no-wait requires --input with more than 25 available-data-only rows.");
|
|
1221
|
+
if (hasFlag("poll-interval-ms")) fail("Signal to Copy --poll-interval-ms requires --input or --job-id.");
|
|
854
1222
|
const companyDomain = flag("company-domain") || flag("domain");
|
|
855
1223
|
const personName = flag("person-name");
|
|
856
1224
|
const title = flag("title");
|
|
@@ -988,6 +1356,7 @@ main().catch((error) => {
|
|
|
988
1356
|
...typeof signalizError?.details?.run_id === "string" ? { run_id: signalizError.details.run_id } : {},
|
|
989
1357
|
...typeof signalizError?.details?.verification_run_id === "string" ? { verification_run_id: signalizError.details.verification_run_id } : {},
|
|
990
1358
|
...typeof signalizError?.details?.job_id === "string" ? { job_id: signalizError.details.job_id } : {},
|
|
1359
|
+
...typeof signalizError?.details?.idempotency_key === "string" ? { idempotency_key: signalizError.details.idempotency_key } : {},
|
|
991
1360
|
...typeof signalizError?.details?.suggested_action === "string" ? { suggested_action: signalizError.details.suggested_action } : {},
|
|
992
1361
|
...signalizError?.errorType ? { error_type: signalizError.errorType } : {},
|
|
993
1362
|
...signalizError?.details ? { details: signalizError.details } : {}
|
|
@@ -1028,6 +1397,13 @@ No automatic retry is recommended; review the provider outcome or contact suppor
|
|
|
1028
1397
|
if (error instanceof import_sdk.SignalizError && typeof error.details?.job_id === "string") {
|
|
1029
1398
|
const jobId = error.details.job_id;
|
|
1030
1399
|
if (error.details.suggested_action === "check_job_status") {
|
|
1400
|
+
if (["find-email", "verify-email", "company-signals", "signal-to-copy"].includes(process.argv[2])) {
|
|
1401
|
+
const idempotencyKey = typeof error.details.idempotency_key === "string" ? error.details.idempotency_key : "";
|
|
1402
|
+
const keyFlag = idempotencyKey ? ` --idempotency-key ${idempotencyKey}` : "";
|
|
1403
|
+
fail(`${message}
|
|
1404
|
+
Recoverable job: ${jobId}
|
|
1405
|
+
Retry with: signaliz ${process.argv[2]} --job-id ${jobId}${keyFlag}`);
|
|
1406
|
+
}
|
|
1031
1407
|
fail(`${message}
|
|
1032
1408
|
Recoverable job: ${jobId}
|
|
1033
1409
|
Resume this job through the REST API or SDK using job_id ${jobId}, or use --json for structured recovery metadata.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaliz/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
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"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"node": ">=18"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@signaliz/sdk": "^1.0.
|
|
32
|
+
"@signaliz/sdk": "^1.0.63"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"tsup": "^8.0.0",
|