@signaliz/cli 1.0.63 → 1.0.64
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 +45 -24
- package/dist/bin.js +700 -269
- package/package.json +6 -6
package/dist/bin.js
CHANGED
|
@@ -17,25 +17,35 @@ var CONFIG_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".sig
|
|
|
17
17
|
var CONFIG_FILE = (0, import_node_path.join)(CONFIG_DIR, "config.json");
|
|
18
18
|
var HELP = `Signaliz CLI
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
signaliz find-email --linkedin-url https://www.linkedin.com/in/jane-doe [--
|
|
22
|
-
signaliz find-email --company-domain example.com --full-name "Jane Doe" [--
|
|
20
|
+
Six product commands:
|
|
21
|
+
signaliz find-email --linkedin-url https://www.linkedin.com/in/jane-doe [--no-wait]
|
|
22
|
+
signaliz find-email --company-domain example.com --full-name "Jane Doe" [--no-wait]
|
|
23
23
|
signaliz find-email --run-id run_... Resume an existing Find Email run without duplicate spend
|
|
24
24
|
signaliz find-email --job-id job_... Resume an existing Find Email batch without redispatch
|
|
25
25
|
signaliz verify-email [jane@example.com] [--verification-run-id run_...] [--no-wait] [--max-wait-ms 600000]
|
|
26
26
|
signaliz verify-email --job-id job_... Resume an existing Verify Email batch without redispatch
|
|
27
|
-
signaliz company-signals --domain example.com
|
|
27
|
+
signaliz company-signals --domain example.com
|
|
28
28
|
signaliz company-signals --input companies.json --no-wait Submit a durable >25-row batch and return its job
|
|
29
29
|
signaliz company-signals --job-id job_... Resume an existing Company Signals batch without redispatch
|
|
30
30
|
signaliz company-signals --signal-run-id run_... Read a completed run without duplicate spend
|
|
31
31
|
signaliz signal-to-copy --company-domain example.com --person-name "Jane Doe" \\
|
|
32
32
|
--title "VP Sales" --campaign-offer "pipeline intelligence" [--signal-run-id run_...] \\
|
|
33
|
-
[--
|
|
33
|
+
[--signal-search-run-id run_... | --fact-id <sha256> | --event-id <sha256>] \\
|
|
34
|
+
[--copy-evidence-mode signal_led|firmographic] [--deep-search] [--max-wait-ms 120000]
|
|
34
35
|
signaliz signal-to-copy --signal-run-id copy_... Reuse a completed signal run
|
|
35
|
-
signaliz signal-to-copy --
|
|
36
|
+
signaliz signal-to-copy --fact-id <sha256> --company-domain example.com --person-name "Jane Doe" --title "VP Sales" --campaign-offer "pipeline intelligence" Reuse one canonical signal without rediscovery
|
|
37
|
+
signaliz signal-to-copy --input recipients.json --no-wait Submit a durable >25-row batch
|
|
36
38
|
signaliz signal-to-copy --job-id job_... Resume an existing Signal to Copy batch without redispatch
|
|
37
|
-
signaliz signals "companies that just got funded" [--icp-context "..."] [--limit 100] [--sources web,news] [--wait]
|
|
39
|
+
signaliz signals "companies that just got funded" [--icp-context "..."] [--limit 100] [--sources web,news] [--after-date YYYY-MM-DD --before-date YYYY-MM-DD] [--wait]
|
|
40
|
+
signaliz signals-first "companies that just got funded" [--limit 100] [--lookback-days 30] [--wait]
|
|
38
41
|
signaliz signals --signal-search-run-id run_... Resume an existing company-attributed signal search
|
|
42
|
+
signaliz awareness create --company-name "Acme" --domain acme.com [--schedule daily] [--monthly-credit-cap 100]
|
|
43
|
+
signaliz awareness list [--limit 100] [--offset 0]
|
|
44
|
+
signaliz awareness run --monitor-id <uuid> --idempotency-key <key>
|
|
45
|
+
signaliz awareness signals [--monitor-id <uuid>]
|
|
46
|
+
signaliz awareness pause|resume|delete --monitor-id <uuid>
|
|
47
|
+
signaliz flow --signal-query "companies with recent hiring" --campaign-offer "..." [--limit 5] [--lookback-days 90] [--people-titles "CEO,VP Sales"]
|
|
48
|
+
signaliz flow --run-id run_... Read a durable Flow checkpoint without dispatching new work
|
|
39
49
|
|
|
40
50
|
Access and connection:
|
|
41
51
|
signaliz auth login
|
|
@@ -56,12 +66,17 @@ Common flags:
|
|
|
56
66
|
--input - Read a JSON array or JSONL batch from stdin
|
|
57
67
|
--concurrency <1-50> Simultaneous API requests for batch input (default: 10)
|
|
58
68
|
--idempotency-key <key> Reuse after an ambiguous response to recover the same request or job
|
|
69
|
+
--no-wait Return the durable Find Email run ID immediately; resume with --run-id
|
|
70
|
+
--copy-evidence-mode <mode> Use signals, or draft from offer and research context without signal claims
|
|
59
71
|
--run-id <run_...> Resume one existing Find Email run without dispatching new work
|
|
60
72
|
--job-id <job_...> Resume an existing core-product batch without dispatching new work
|
|
61
73
|
--icp-context <text> Optional ICP, product, or pain context that returned signals must support
|
|
74
|
+
--signal-search-run-id <id> Resume Signals First, or pin its immutable snapshot in Signal to Copy
|
|
75
|
+
--fact-id <sha256> Pin one active canonical signal fact in Signal to Copy
|
|
76
|
+
--event-id <sha256> Pin one canonical signal event in Signal to Copy
|
|
62
77
|
--dry-run Return a no-spend plan without provider calls, jobs, or writes
|
|
63
78
|
|
|
64
|
-
Company Signals
|
|
79
|
+
Company Signals accepts only --domain. Signaliz checks its cache, runs one type-agnostic Parallel Advanced search plus at most one first-party hub Extract, and returns the newest distinct events that pass its deterministic date, source, company, evidence, and duplicate gates. For a durable batch larger than 25 rows, provide domain-only rows with --no-wait and resume with --job-id. Signal to Copy canonical references remain separate. Signals Everything is asynchronous by default; use --wait to poll until it completes.
|
|
65
80
|
`;
|
|
66
81
|
function loadConfig() {
|
|
67
82
|
if (!(0, import_node_fs.existsSync)(CONFIG_FILE)) return {};
|
|
@@ -108,6 +123,25 @@ function requireIntegerInRange(value, name, minimum, maximum) {
|
|
|
108
123
|
throw new CliInputError(`${name} must be an integer between ${minimum} and ${maximum}`);
|
|
109
124
|
}
|
|
110
125
|
}
|
|
126
|
+
function validateSignalDateWindow(afterDate, beforeDate, lookbackDays, flagPrefix = "--") {
|
|
127
|
+
if ((afterDate || beforeDate) && lookbackDays !== void 0) {
|
|
128
|
+
throw new CliInputError(`${flagPrefix}after-date/--before-date cannot be combined with --lookback-days`);
|
|
129
|
+
}
|
|
130
|
+
const parseDate = (value, name) => {
|
|
131
|
+
if (value === void 0) return void 0;
|
|
132
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) throw new CliInputError(`${name} must use YYYY-MM-DD format`);
|
|
133
|
+
const timestamp = Date.parse(`${value}T00:00:00Z`);
|
|
134
|
+
if (!Number.isFinite(timestamp) || new Date(timestamp).toISOString().slice(0, 10) !== value) {
|
|
135
|
+
throw new CliInputError(`${name} must be a valid calendar date`);
|
|
136
|
+
}
|
|
137
|
+
return timestamp;
|
|
138
|
+
};
|
|
139
|
+
const afterTimestamp = parseDate(afterDate, `${flagPrefix}after-date`);
|
|
140
|
+
const beforeTimestamp = parseDate(beforeDate, `${flagPrefix}before-date`);
|
|
141
|
+
if (afterTimestamp !== void 0 && beforeTimestamp !== void 0 && beforeTimestamp < afterTimestamp) {
|
|
142
|
+
throw new CliInputError(`${flagPrefix}before-date must be on or after ${flagPrefix}after-date`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
111
145
|
function requireSignalToCopyIdentity(request) {
|
|
112
146
|
if (stringValue(request.signalRunId)) return;
|
|
113
147
|
const missing = [
|
|
@@ -124,11 +158,6 @@ function csvFlag(name) {
|
|
|
124
158
|
const value = flag(name);
|
|
125
159
|
return value?.split(",").map((item) => item.trim()).filter(Boolean);
|
|
126
160
|
}
|
|
127
|
-
function companySignalSearchMode(value) {
|
|
128
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
129
|
-
if (value === "fast" || value === "balanced" || value === "coverage") return value;
|
|
130
|
-
throw new CliInputError("--search-mode must be fast, balanced, or coverage");
|
|
131
|
-
}
|
|
132
161
|
function readBatchInput() {
|
|
133
162
|
const path = flag("input");
|
|
134
163
|
if (!path) return null;
|
|
@@ -164,6 +193,221 @@ function readBatchInput() {
|
|
|
164
193
|
function record(value) {
|
|
165
194
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
166
195
|
}
|
|
196
|
+
function signalText(value) {
|
|
197
|
+
return typeof value === "string" ? value.trim() : "";
|
|
198
|
+
}
|
|
199
|
+
function signalDate(value) {
|
|
200
|
+
const match = signalText(value).match(/^\d{4}-\d{2}-\d{2}/);
|
|
201
|
+
if (!match) return "";
|
|
202
|
+
const parsed = /* @__PURE__ */ new Date(`${match[0]}T00:00:00.000Z`);
|
|
203
|
+
return Number.isFinite(parsed.getTime()) && parsed.toISOString().slice(0, 10) === match[0] ? match[0] : "";
|
|
204
|
+
}
|
|
205
|
+
function signalClassification(value) {
|
|
206
|
+
const direct = signalText(value);
|
|
207
|
+
if (direct) return direct;
|
|
208
|
+
const classification = record(value);
|
|
209
|
+
return signalText(classification.slug || classification.type || classification.name);
|
|
210
|
+
}
|
|
211
|
+
function publicSignalType(signal) {
|
|
212
|
+
const raw = record(signal.raw_data);
|
|
213
|
+
const generic = /* @__PURE__ */ new Set(["unclassified", "unknown", "other", "news", "signal"]);
|
|
214
|
+
for (const value of [
|
|
215
|
+
signal.signal_type,
|
|
216
|
+
signal.signalType,
|
|
217
|
+
signalClassification(signal.signal_classification || signal.signalClassification),
|
|
218
|
+
signalClassification(signal.classification),
|
|
219
|
+
raw.signal_type,
|
|
220
|
+
raw.signalType,
|
|
221
|
+
signalClassification(raw.signal_classification || raw.signalClassification),
|
|
222
|
+
signalClassification(raw.classification),
|
|
223
|
+
signal.type,
|
|
224
|
+
signal.category,
|
|
225
|
+
signal.event_type,
|
|
226
|
+
raw.type,
|
|
227
|
+
raw.category,
|
|
228
|
+
raw.event_type
|
|
229
|
+
]) {
|
|
230
|
+
const candidate = signalText(value);
|
|
231
|
+
if (candidate && !generic.has(candidate.toLowerCase())) return candidate;
|
|
232
|
+
}
|
|
233
|
+
return "";
|
|
234
|
+
}
|
|
235
|
+
function verifiedHttpsSource(value) {
|
|
236
|
+
const source = signalText(value);
|
|
237
|
+
if (!source || /\s/.test(source)) return "";
|
|
238
|
+
try {
|
|
239
|
+
const url = new URL(source);
|
|
240
|
+
return url.protocol === "https:" && Boolean(url.hostname) && !url.username && !url.password ? source : "";
|
|
241
|
+
} catch {
|
|
242
|
+
return "";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function normalizedSignalDomain(value) {
|
|
246
|
+
const normalized = signalText(value).toLowerCase().replace(/^https?:\/\//, "").replace(/^www\./, "").split(/[/?#]/)[0].replace(/\.$/, "");
|
|
247
|
+
return /^(?=.{3,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(normalized) ? normalized : "";
|
|
248
|
+
}
|
|
249
|
+
function firstValidSignalValue(values, normalize) {
|
|
250
|
+
for (const value of values) {
|
|
251
|
+
const normalized = normalize(value);
|
|
252
|
+
if (normalized) return normalized;
|
|
253
|
+
}
|
|
254
|
+
return "";
|
|
255
|
+
}
|
|
256
|
+
function publicSignalRow(value, fallbackCompany) {
|
|
257
|
+
const signal = record(value);
|
|
258
|
+
const raw = record(signal.raw_data);
|
|
259
|
+
const company = record(signal.company);
|
|
260
|
+
const rawCompany = record(raw.company);
|
|
261
|
+
const fallback = record(fallbackCompany);
|
|
262
|
+
const row = {
|
|
263
|
+
signal_type: publicSignalType(signal),
|
|
264
|
+
signal_title: firstValidSignalValue([
|
|
265
|
+
signal.signal_title,
|
|
266
|
+
signal.signalTitle,
|
|
267
|
+
raw.signal_title,
|
|
268
|
+
raw.signalTitle,
|
|
269
|
+
signal.title,
|
|
270
|
+
raw.title,
|
|
271
|
+
signal.headline,
|
|
272
|
+
raw.headline,
|
|
273
|
+
signal.name,
|
|
274
|
+
raw.name
|
|
275
|
+
], signalText),
|
|
276
|
+
signal_summary: firstValidSignalValue([
|
|
277
|
+
signal.signal_summary,
|
|
278
|
+
signal.signalSummary,
|
|
279
|
+
raw.signal_summary,
|
|
280
|
+
raw.signalSummary,
|
|
281
|
+
signal.summary,
|
|
282
|
+
raw.summary,
|
|
283
|
+
signal.signal_content,
|
|
284
|
+
signal.signalContent,
|
|
285
|
+
raw.signal_content,
|
|
286
|
+
raw.signalContent,
|
|
287
|
+
signal.content,
|
|
288
|
+
raw.content,
|
|
289
|
+
signal.description,
|
|
290
|
+
raw.description
|
|
291
|
+
], signalText),
|
|
292
|
+
source: firstValidSignalValue([
|
|
293
|
+
signal.canonical_source_url,
|
|
294
|
+
signal.canonicalSourceUrl,
|
|
295
|
+
signal.source_url,
|
|
296
|
+
signal.sourceUrl,
|
|
297
|
+
signal.verified_source_url,
|
|
298
|
+
signal.verifiedSourceUrl,
|
|
299
|
+
signal.signal_source,
|
|
300
|
+
signal.signalSource,
|
|
301
|
+
signal.source,
|
|
302
|
+
signal.url,
|
|
303
|
+
raw.canonical_source_url,
|
|
304
|
+
raw.canonicalSourceUrl,
|
|
305
|
+
raw.source_url,
|
|
306
|
+
raw.sourceUrl,
|
|
307
|
+
raw.verified_source_url,
|
|
308
|
+
raw.verifiedSourceUrl,
|
|
309
|
+
raw.signal_source,
|
|
310
|
+
raw.signalSource,
|
|
311
|
+
raw.source,
|
|
312
|
+
raw.url
|
|
313
|
+
], verifiedHttpsSource),
|
|
314
|
+
date: firstValidSignalValue([
|
|
315
|
+
signal.date,
|
|
316
|
+
signal.event_date,
|
|
317
|
+
signal.eventDate,
|
|
318
|
+
signal.signal_date,
|
|
319
|
+
signal.signalDate,
|
|
320
|
+
signal.published_date,
|
|
321
|
+
signal.publishedDate,
|
|
322
|
+
signal.published_at,
|
|
323
|
+
signal.publishedAt,
|
|
324
|
+
signal.detected_at,
|
|
325
|
+
signal.detectedAt,
|
|
326
|
+
signal.observed_at,
|
|
327
|
+
signal.observedAt,
|
|
328
|
+
raw.date,
|
|
329
|
+
raw.event_date,
|
|
330
|
+
raw.eventDate,
|
|
331
|
+
raw.signal_date,
|
|
332
|
+
raw.signalDate,
|
|
333
|
+
raw.published_date,
|
|
334
|
+
raw.publishedDate,
|
|
335
|
+
raw.published_at,
|
|
336
|
+
raw.publishedAt,
|
|
337
|
+
raw.detected_at,
|
|
338
|
+
raw.detectedAt,
|
|
339
|
+
raw.observed_at,
|
|
340
|
+
raw.observedAt
|
|
341
|
+
], signalDate),
|
|
342
|
+
company_name: signalText(
|
|
343
|
+
signal.company_name || signal.companyName || company.name || company.company_name || raw.company_name || raw.companyName || rawCompany.name || rawCompany.company_name || fallback.company_name || fallback.companyName || fallback.name
|
|
344
|
+
),
|
|
345
|
+
domain: firstValidSignalValue([
|
|
346
|
+
signal.company_domain,
|
|
347
|
+
signal.companyDomain,
|
|
348
|
+
signal.domain,
|
|
349
|
+
company.domain,
|
|
350
|
+
company.company_domain,
|
|
351
|
+
raw.company_domain,
|
|
352
|
+
raw.companyDomain,
|
|
353
|
+
raw.domain,
|
|
354
|
+
rawCompany.domain,
|
|
355
|
+
rawCompany.company_domain,
|
|
356
|
+
fallback.company_domain,
|
|
357
|
+
fallback.companyDomain,
|
|
358
|
+
fallback.domain
|
|
359
|
+
], normalizedSignalDomain)
|
|
360
|
+
};
|
|
361
|
+
return row.signal_type && row.source && row.date && row.company_name && row.domain ? row : null;
|
|
362
|
+
}
|
|
363
|
+
function publicSignalRows(value, fallbackCompany) {
|
|
364
|
+
if (!Array.isArray(value)) return [];
|
|
365
|
+
return value.flatMap((item) => {
|
|
366
|
+
const row = publicSignalRow(item, fallbackCompany);
|
|
367
|
+
return row ? [row] : [];
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function oneSignalPerCompany(rows) {
|
|
371
|
+
const seen = /* @__PURE__ */ new Set();
|
|
372
|
+
return rows.filter((row) => {
|
|
373
|
+
if (seen.has(row.domain)) return false;
|
|
374
|
+
seen.add(row.domain);
|
|
375
|
+
return true;
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
var PUBLIC_COMPANY_SIGNAL_MAX_COVERAGE_COUNT = 10;
|
|
379
|
+
function publicCompanySignalRows(value, fallbackCompany) {
|
|
380
|
+
const candidates = Array.isArray(value) ? value : [];
|
|
381
|
+
const seenEvents = /* @__PURE__ */ new Set();
|
|
382
|
+
const rows = [];
|
|
383
|
+
for (const candidate of candidates) {
|
|
384
|
+
const row = publicSignalRow(candidate, fallbackCompany);
|
|
385
|
+
if (!row) continue;
|
|
386
|
+
const signal = record(candidate);
|
|
387
|
+
const raw = record(signal.raw_data);
|
|
388
|
+
const eventId = signalText(
|
|
389
|
+
signal.event_id || signal.eventId || signal.fact_id || signal.factId || raw.event_id || raw.eventId || raw.fact_id || raw.factId
|
|
390
|
+
).toLowerCase();
|
|
391
|
+
const identities = [
|
|
392
|
+
...eventId ? [`event:${eventId}`] : [],
|
|
393
|
+
`source:${row.source.toLowerCase()}`
|
|
394
|
+
];
|
|
395
|
+
if (identities.some((identity) => seenEvents.has(identity))) continue;
|
|
396
|
+
identities.forEach((identity) => seenEvents.add(identity));
|
|
397
|
+
rows.push(row);
|
|
398
|
+
if (rows.length >= PUBLIC_COMPANY_SIGNAL_MAX_COVERAGE_COUNT) break;
|
|
399
|
+
}
|
|
400
|
+
return rows;
|
|
401
|
+
}
|
|
402
|
+
function companySignalOutputRow(signal) {
|
|
403
|
+
return {
|
|
404
|
+
date: signal.date,
|
|
405
|
+
signal_type: signal.signal_type,
|
|
406
|
+
signal_title: signal.signal_title,
|
|
407
|
+
signal_summary: signal.signal_summary,
|
|
408
|
+
source: signal.source
|
|
409
|
+
};
|
|
410
|
+
}
|
|
167
411
|
function safeNonNegativeNumber(value) {
|
|
168
412
|
if (value === null || value === void 0 || value === "") return null;
|
|
169
413
|
const numeric = Number(value);
|
|
@@ -173,7 +417,7 @@ function customerEmailBillingMetadata(value) {
|
|
|
173
417
|
const source = record(value);
|
|
174
418
|
const safe = {};
|
|
175
419
|
if (typeof source.result_returned_from === "string") safe.result_returned_from = source.result_returned_from;
|
|
176
|
-
for (const field of ["
|
|
420
|
+
for (const field of ["openrouter_called", "byo_openrouter_used"]) {
|
|
177
421
|
if (typeof source[field] === "boolean") safe[field] = source[field];
|
|
178
422
|
}
|
|
179
423
|
for (const field of ["credits_used", "credits_charged", "estimated_external_cost_usd"]) {
|
|
@@ -241,19 +485,10 @@ function customerEmailResult(value, kind) {
|
|
|
241
485
|
const historicalBillingMetadata2 = customerEmailBillingMetadata(
|
|
242
486
|
Object.keys(record(result.historicalBillingMetadata)).length > 0 ? result.historicalBillingMetadata : raw.historical_billing_metadata
|
|
243
487
|
);
|
|
244
|
-
const cacheHit2 = typeof raw.cache_hit === "boolean" ? raw.cache_hit : result.cacheHit === true;
|
|
245
|
-
const negativeCacheHit2 = typeof raw.negative_cache_hit === "boolean" ? raw.negative_cache_hit : result.negativeCacheHit === true;
|
|
246
|
-
const resultReturnedFrom = result.resultReturnedFrom ?? raw.result_returned_from ?? null;
|
|
247
|
-
const freshEnrichmentUsed = typeof raw.fresh_enrichment_used === "boolean" ? raw.fresh_enrichment_used : result.freshEnrichmentUsed === true;
|
|
248
|
-
const liveProviderCalled = typeof raw.live_provider_called === "boolean" ? raw.live_provider_called : result.liveProviderCalled === true;
|
|
249
488
|
const normalizedBillingMetadata = {
|
|
250
489
|
...billingMetadata2,
|
|
251
|
-
...resultReturnedFrom ? { result_returned_from: resultReturnedFrom } : {},
|
|
252
|
-
cache_hit: cacheHit2,
|
|
253
|
-
fresh_enrichment_used: freshEnrichmentUsed,
|
|
254
490
|
credits_used: base.credits_used,
|
|
255
|
-
credits_charged: base.credits_charged
|
|
256
|
-
live_provider_called: liveProviderCalled
|
|
491
|
+
credits_charged: base.credits_charged
|
|
257
492
|
};
|
|
258
493
|
const estimatedExternalCostUsd2 = safeNonNegativeNumber(
|
|
259
494
|
result.estimatedExternalCostUsd ?? raw.estimated_external_cost_usd
|
|
@@ -288,15 +523,6 @@ function customerEmailResult(value, kind) {
|
|
|
288
523
|
verification_source: result.verificationSource ?? raw.verification_source ?? result.providerUsed ?? "email_finder",
|
|
289
524
|
...result.verificationObservedAt ?? raw.verification_observed_at ? { verification_observed_at: result.verificationObservedAt ?? raw.verification_observed_at } : {},
|
|
290
525
|
failure_reason: result.failureReason ?? raw.failure_reason ?? (verifiedForSending2 ? "none" : "no_verified_email_found"),
|
|
291
|
-
cache_hit: cacheHit2,
|
|
292
|
-
negative_cache_hit: negativeCacheHit2,
|
|
293
|
-
negative_cache_ttl_seconds: safeNonNegativeNumber(
|
|
294
|
-
result.negativeCacheTtlSeconds ?? raw.negative_cache_ttl_seconds
|
|
295
|
-
),
|
|
296
|
-
cache_tier: result.cacheTier ?? raw.cache_tier ?? null,
|
|
297
|
-
result_returned_from: resultReturnedFrom,
|
|
298
|
-
fresh_enrichment_used: freshEnrichmentUsed,
|
|
299
|
-
live_provider_called: liveProviderCalled,
|
|
300
526
|
billing_replayed: typeof raw.billing_replayed === "boolean" ? raw.billing_replayed : result.billingReplayed === true,
|
|
301
527
|
...typeof raw.idempotency_replayed === "boolean" || typeof result.idempotencyReplayed === "boolean" ? {
|
|
302
528
|
idempotency_replayed: typeof raw.idempotency_replayed === "boolean" ? raw.idempotency_replayed : result.idempotencyReplayed === true
|
|
@@ -309,11 +535,6 @@ function customerEmailResult(value, kind) {
|
|
|
309
535
|
recovery_mode: raw.recovery_mode,
|
|
310
536
|
recovery_status: raw.recovery_status ?? "completed"
|
|
311
537
|
} : {},
|
|
312
|
-
...raw.cache_publication_status ? {
|
|
313
|
-
cache_publication_status: raw.cache_publication_status,
|
|
314
|
-
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
315
|
-
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
316
|
-
} : {},
|
|
317
538
|
...terminalErrorCode ? {
|
|
318
539
|
email: null,
|
|
319
540
|
success: false,
|
|
@@ -348,11 +569,6 @@ function customerEmailResult(value, kind) {
|
|
|
348
569
|
const isMalformed = typeof result.isMalformed === "boolean" ? result.isMalformed : raw.is_malformed === true;
|
|
349
570
|
const quality = typeof result.quality === "string" ? result.quality : typeof raw.quality === "string" ? raw.quality : null;
|
|
350
571
|
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";
|
|
351
|
-
const cacheHit = typeof raw.cache_hit === "boolean" ? raw.cache_hit : result.cacheHit === true;
|
|
352
|
-
const negativeCacheHit = typeof raw.negative_cache_hit === "boolean" ? raw.negative_cache_hit : result.negativeCacheHit === true;
|
|
353
|
-
const negativeCacheTtlSeconds = safeNonNegativeNumber(
|
|
354
|
-
result.negativeCacheTtlSeconds ?? raw.negative_cache_ttl_seconds
|
|
355
|
-
);
|
|
356
572
|
const billingMetadata = customerEmailBillingMetadata(
|
|
357
573
|
Object.keys(record(result.billingMetadata)).length > 0 ? result.billingMetadata : raw.billing_metadata
|
|
358
574
|
);
|
|
@@ -382,13 +598,6 @@ function customerEmailResult(value, kind) {
|
|
|
382
598
|
verification_source: result.verificationSource ?? raw.verification_source ?? "email_verification",
|
|
383
599
|
...result.verificationObservedAt ?? raw.verification_observed_at ? { verification_observed_at: result.verificationObservedAt ?? raw.verification_observed_at } : {},
|
|
384
600
|
failure_reason: result.failureReason ?? raw.failure_reason ?? (verifiedForSending ? "none" : isCatchAll ? "catch_all_domain_not_send_safe" : "verification_not_send_safe"),
|
|
385
|
-
cache_hit: cacheHit,
|
|
386
|
-
negative_cache_hit: negativeCacheHit,
|
|
387
|
-
negative_cache_ttl_seconds: negativeCacheTtlSeconds,
|
|
388
|
-
cache_tier: result.cacheTier ?? raw.cache_tier ?? null,
|
|
389
|
-
result_returned_from: result.resultReturnedFrom ?? raw.result_returned_from ?? null,
|
|
390
|
-
fresh_enrichment_used: typeof raw.fresh_enrichment_used === "boolean" ? raw.fresh_enrichment_used : result.freshEnrichmentUsed === true,
|
|
391
|
-
live_provider_called: typeof raw.live_provider_called === "boolean" ? raw.live_provider_called : result.liveProviderCalled === true,
|
|
392
601
|
billing_replayed: typeof raw.billing_replayed === "boolean" ? raw.billing_replayed : result.billingReplayed === true,
|
|
393
602
|
...typeof raw.idempotency_replayed === "boolean" || typeof result.idempotencyReplayed === "boolean" ? {
|
|
394
603
|
idempotency_replayed: typeof raw.idempotency_replayed === "boolean" ? raw.idempotency_replayed : result.idempotencyReplayed === true
|
|
@@ -397,12 +606,7 @@ function customerEmailResult(value, kind) {
|
|
|
397
606
|
...Object.keys(historicalBillingMetadata).length > 0 ? { historical_billing_metadata: historicalBillingMetadata } : {},
|
|
398
607
|
...estimatedExternalCostUsd !== null ? { estimated_external_cost_usd: estimatedExternalCostUsd } : {},
|
|
399
608
|
...verificationRunId ? { verification_run_id: verificationRunId } : {},
|
|
400
|
-
...runId ? { run_id: runId } : {}
|
|
401
|
-
...raw.cache_publication_status ? {
|
|
402
|
-
cache_publication_status: raw.cache_publication_status,
|
|
403
|
-
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
404
|
-
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
405
|
-
} : {}
|
|
609
|
+
...runId ? { run_id: runId } : {}
|
|
406
610
|
};
|
|
407
611
|
}
|
|
408
612
|
function customerEmailBatch(value, kind) {
|
|
@@ -430,15 +634,39 @@ function customerSignalResult(value) {
|
|
|
430
634
|
return {
|
|
431
635
|
...result,
|
|
432
636
|
...Object.keys(billingMetadata).length > 0 ? { billingMetadata } : {},
|
|
433
|
-
resultReturnedFrom: result.resultReturnedFrom ?? raw.result_returned_from,
|
|
434
|
-
cacheHit: result.cacheHit ?? raw.cache_hit,
|
|
435
|
-
freshEnrichmentUsed: result.freshEnrichmentUsed ?? raw.fresh_enrichment_used,
|
|
436
637
|
creditsUsed: result.creditsUsed ?? raw.credits_used,
|
|
437
|
-
liveProviderCalled: result.liveProviderCalled ?? raw.live_provider_called,
|
|
438
638
|
aiProviderCalled: result.aiProviderCalled ?? raw.ai_provider_called,
|
|
439
639
|
byoAiUsed: result.byoAiUsed ?? raw.byo_ai_used
|
|
440
640
|
};
|
|
441
641
|
}
|
|
642
|
+
function customerCompanySignalResult(value) {
|
|
643
|
+
const result = record(value);
|
|
644
|
+
const raw = record(result.raw);
|
|
645
|
+
const company = record(result.company);
|
|
646
|
+
const rawCompany = record(raw.company);
|
|
647
|
+
const normalizedCompany = {
|
|
648
|
+
name: signalText(result.companyName || result.company_name || company.name || raw.company_name || rawCompany.name) || null,
|
|
649
|
+
domain: normalizedSignalDomain(
|
|
650
|
+
result.companyDomain || result.company_domain || result.domain || company.domain || raw.company_domain || raw.domain || rawCompany.domain
|
|
651
|
+
) || null
|
|
652
|
+
};
|
|
653
|
+
const rawSignals = Array.isArray(raw.signals) ? raw.signals : Array.isArray(raw.signal_feed) ? raw.signal_feed : result.signals;
|
|
654
|
+
const signals2 = publicCompanySignalRows(rawSignals, normalizedCompany).map(companySignalOutputRow);
|
|
655
|
+
const {
|
|
656
|
+
raw: _raw,
|
|
657
|
+
signals: _signals,
|
|
658
|
+
signalCount: _signalCount,
|
|
659
|
+
company: _company,
|
|
660
|
+
...publicResult
|
|
661
|
+
} = result;
|
|
662
|
+
return {
|
|
663
|
+
...publicResult,
|
|
664
|
+
company: normalizedCompany,
|
|
665
|
+
signals: signals2,
|
|
666
|
+
signalCount: signals2.length,
|
|
667
|
+
creditsUsed: result.creditsUsed ?? raw.credits_used
|
|
668
|
+
};
|
|
669
|
+
}
|
|
442
670
|
function customerSignalBatch(value) {
|
|
443
671
|
return {
|
|
444
672
|
...value,
|
|
@@ -448,6 +676,31 @@ function customerSignalBatch(value) {
|
|
|
448
676
|
})
|
|
449
677
|
};
|
|
450
678
|
}
|
|
679
|
+
function customerCompanySignalBatch(value) {
|
|
680
|
+
const batch = record(value);
|
|
681
|
+
const { raw: _raw, results: _results, ...publicBatch } = batch;
|
|
682
|
+
const results = Array.isArray(batch.results) ? batch.results.map((item) => {
|
|
683
|
+
const row = record(item);
|
|
684
|
+
const { raw: _rowRaw, ...publicRow } = row;
|
|
685
|
+
if (row.data) {
|
|
686
|
+
return promoteBatchRecoveryMetadata({ ...publicRow, data: customerCompanySignalResult(row.data) });
|
|
687
|
+
}
|
|
688
|
+
if (Array.isArray(row.signals) || row.company) {
|
|
689
|
+
return promoteBatchRecoveryMetadata(customerCompanySignalResult(publicRow));
|
|
690
|
+
}
|
|
691
|
+
return promoteBatchRecoveryMetadata(publicRow);
|
|
692
|
+
}) : [];
|
|
693
|
+
return { ...publicBatch, results };
|
|
694
|
+
}
|
|
695
|
+
function customerSignalAwarenessResult(value) {
|
|
696
|
+
const result = record(value);
|
|
697
|
+
const { raw: _raw, signals: _signals, ...publicResult } = result;
|
|
698
|
+
const signals2 = Array.isArray(result.signals) ? oneSignalPerCompany(publicSignalRows(result.signals)) : void 0;
|
|
699
|
+
return {
|
|
700
|
+
...publicResult,
|
|
701
|
+
...signals2 ? { signals: signals2 } : {}
|
|
702
|
+
};
|
|
703
|
+
}
|
|
451
704
|
function batchOptions() {
|
|
452
705
|
return {
|
|
453
706
|
concurrency: numberFlag("concurrency"),
|
|
@@ -553,12 +806,40 @@ function numberValue(value) {
|
|
|
553
806
|
const number = Number(value);
|
|
554
807
|
return Number.isFinite(number) ? number : void 0;
|
|
555
808
|
}
|
|
556
|
-
function nullableNumberValue(value) {
|
|
557
|
-
return value === null ? null : numberValue(value);
|
|
558
|
-
}
|
|
559
809
|
function stringValue(value) {
|
|
560
810
|
return typeof value === "string" ? value.trim() : "";
|
|
561
811
|
}
|
|
812
|
+
function publicSignalDiscoveryFailure(value) {
|
|
813
|
+
const requestedCode = stringValue(value).toUpperCase();
|
|
814
|
+
if (requestedCode === "NO_QUALIFIED_SIGNALS") {
|
|
815
|
+
return {
|
|
816
|
+
errorCode: requestedCode,
|
|
817
|
+
error: "No company signal met the dated-evidence, company-identity, and query requirements."
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
if (requestedCode === "SOURCE_EMPTY") {
|
|
821
|
+
return {
|
|
822
|
+
errorCode: requestedCode,
|
|
823
|
+
error: "The selected source lanes returned no candidates for this query and time window."
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
if (requestedCode === "IDEMPOTENCY_CONFLICT") {
|
|
827
|
+
return {
|
|
828
|
+
errorCode: requestedCode,
|
|
829
|
+
error: "This recovery key belongs to a different Signals Everything request."
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
if (requestedCode === "PERSISTENCE_UNAVAILABLE") {
|
|
833
|
+
return {
|
|
834
|
+
errorCode: requestedCode,
|
|
835
|
+
error: "The result is still being finalized. Retry with the same signal search run ID."
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
errorCode: "SOURCE_UNAVAILABLE",
|
|
840
|
+
error: "Signals Everything could not complete this search."
|
|
841
|
+
};
|
|
842
|
+
}
|
|
562
843
|
function hasFindEmailLinkedInIdentity(value) {
|
|
563
844
|
const linkedinUrl = stringValue(value);
|
|
564
845
|
if (!linkedinUrl) return false;
|
|
@@ -582,35 +863,11 @@ function signalsEverythingErrorType(status) {
|
|
|
582
863
|
}
|
|
583
864
|
function normalizeSignalsEverythingResult(request, value) {
|
|
584
865
|
const rawSignals = Array.isArray(value.signals) ? value.signals : [];
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
if (!name || !domain) {
|
|
591
|
-
throw new Error("Signals Everything response violated the company attribution contract.");
|
|
592
|
-
}
|
|
593
|
-
const evidence = Array.isArray(signal.evidence) ? signal.evidence.map((rawEvidence) => {
|
|
594
|
-
const item = record(rawEvidence);
|
|
595
|
-
return {
|
|
596
|
-
url: stringValue(item.url),
|
|
597
|
-
publishedAt: stringValue(item.published_at || item.publishedAt),
|
|
598
|
-
source: stringValue(item.source)
|
|
599
|
-
};
|
|
600
|
-
}).filter((item) => Boolean(item.url)) : [];
|
|
601
|
-
const eventDate = stringValue(signal.event_date || signal.date);
|
|
602
|
-
const sourceUrl = stringValue(signal.source_url || signal.url);
|
|
603
|
-
if (!eventDate || !sourceUrl || !evidence.some((item) => item.url === sourceUrl && item.publishedAt === eventDate)) {
|
|
604
|
-
throw new Error("Signals Everything response violated the dated-evidence and source-URL contract.");
|
|
605
|
-
}
|
|
606
|
-
return {
|
|
607
|
-
company: { name, domain },
|
|
608
|
-
title: stringValue(signal.title || signal.summary || signal.content),
|
|
609
|
-
eventDate,
|
|
610
|
-
sourceUrl,
|
|
611
|
-
evidence
|
|
612
|
-
};
|
|
613
|
-
});
|
|
866
|
+
const requestedCount = numberValue(value.requested_count) ?? request.limit;
|
|
867
|
+
const signals2 = oneSignalPerCompany(publicSignalRows(rawSignals)).slice(
|
|
868
|
+
0,
|
|
869
|
+
requestedCount !== void 0 && requestedCount > 0 ? requestedCount : void 0
|
|
870
|
+
);
|
|
614
871
|
const statusValue = stringValue(value.status).toLowerCase();
|
|
615
872
|
const statuses = /* @__PURE__ */ new Set([
|
|
616
873
|
"planned",
|
|
@@ -621,52 +878,24 @@ function normalizeSignalsEverythingResult(request, value) {
|
|
|
621
878
|
"failed"
|
|
622
879
|
]);
|
|
623
880
|
const status = statuses.has(statusValue) ? statusValue : signals2.length > 0 ? "completed" : "failed";
|
|
624
|
-
const
|
|
625
|
-
const
|
|
626
|
-
const
|
|
627
|
-
const identityCostSource = stringValue(guardrail.identity_cost_source);
|
|
628
|
-
const warnings = Array.isArray(value.warnings) ? value.warnings.filter((warning) => typeof warning === "string") : void 0;
|
|
881
|
+
const error = record(value.error);
|
|
882
|
+
const hasFailure = value.success === false || Boolean(stringValue(value.error_code || error.code));
|
|
883
|
+
const publicFailure = hasFailure ? publicSignalDiscoveryFailure(value.error_code || error.code) : void 0;
|
|
629
884
|
return {
|
|
630
885
|
success: value.success !== false,
|
|
631
886
|
status,
|
|
632
887
|
signalSearchRunId: stringValue(value.signal_search_run_id || request.signalSearchRunId),
|
|
633
888
|
query: stringValue(value.query || request.query),
|
|
634
|
-
requestedCount
|
|
889
|
+
...requestedCount === void 0 ? {} : { requestedCount },
|
|
635
890
|
nextPollAfterSeconds: numberValue(value.next_poll_after_seconds),
|
|
636
891
|
signals: signals2,
|
|
637
892
|
signalCount: signals2.length,
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
},
|
|
641
|
-
...
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
projectedSourceCostUsd: nullableNumberValue(guardrail.projected_source_cost_usd),
|
|
645
|
-
maxSourceCostUsd: nullableNumberValue(guardrail.max_source_cost_usd),
|
|
646
|
-
projectedCostPerRequestedCompanySignalUsd: nullableNumberValue(
|
|
647
|
-
guardrail.projected_cost_per_requested_company_signal_usd
|
|
648
|
-
),
|
|
649
|
-
sourceCostUsd: nullableNumberValue(guardrail.source_cost_usd),
|
|
650
|
-
costSource: ["observed", "catalog_preflight", "catalog_bounded", "mixed", "unavailable"].includes(costSource) ? costSource : void 0,
|
|
651
|
-
costPerQualifiedSignalUsd: nullableNumberValue(guardrail.cost_per_qualified_signal_usd),
|
|
652
|
-
identityResolutionCostUsd: nullableNumberValue(guardrail.identity_resolution_cost_usd),
|
|
653
|
-
identityCostSource: [
|
|
654
|
-
"observed_zero_credit_receipts",
|
|
655
|
-
"contractual_zero_cost",
|
|
656
|
-
"not_used",
|
|
657
|
-
"unavailable"
|
|
658
|
-
].includes(identityCostSource) ? identityCostSource : void 0,
|
|
659
|
-
identityProviderRequests: numberValue(guardrail.identity_provider_requests),
|
|
660
|
-
qualifiedCompanySignalCount: numberValue(guardrail.qualified_company_signal_count),
|
|
661
|
-
returnedCompanySignalCount: numberValue(guardrail.returned_company_signal_count),
|
|
662
|
-
availableCompanySignalCount: numberValue(guardrail.available_company_signal_count),
|
|
663
|
-
acquisitionCandidateLimit: numberValue(guardrail.acquisition_candidate_limit),
|
|
664
|
-
minimumQualifiedCompanySignals: numberValue(guardrail.minimum_qualified_company_signals),
|
|
665
|
-
withinLimit: guardrail.within_limit === true
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
...warnings?.length ? { warnings } : {},
|
|
669
|
-
raw: value
|
|
893
|
+
creditsUsed: numberValue(value.credits_used) ?? 0,
|
|
894
|
+
creditsCharged: numberValue(value.credits_charged) ?? 0,
|
|
895
|
+
...value.billing_status === "included" ? { billingStatus: "included" } : {},
|
|
896
|
+
...typeof value.idempotency_replayed === "boolean" ? { idempotencyReplayed: value.idempotency_replayed } : {},
|
|
897
|
+
...publicFailure ? publicFailure : {},
|
|
898
|
+
...typeof value.retry_eligible === "boolean" ? { retryEligible: value.retry_eligible } : {}
|
|
670
899
|
};
|
|
671
900
|
}
|
|
672
901
|
async function discoverSignalsEverything(request) {
|
|
@@ -681,6 +910,8 @@ async function discoverSignalsEverything(request) {
|
|
|
681
910
|
limit: request.limit ?? 100,
|
|
682
911
|
...request.sources ? { sources: request.sources } : {},
|
|
683
912
|
...request.lookbackDays === void 0 ? {} : { lookback_days: request.lookbackDays },
|
|
913
|
+
...request.afterDate ? { after_date: request.afterDate } : {},
|
|
914
|
+
...request.beforeDate ? { before_date: request.beforeDate } : {},
|
|
684
915
|
...request.dryRun === void 0 ? {} : { dry_run: request.dryRun },
|
|
685
916
|
...request.idempotencyKey ? { idempotency_key: request.idempotencyKey } : {}
|
|
686
917
|
};
|
|
@@ -697,14 +928,19 @@ async function discoverSignalsEverything(request) {
|
|
|
697
928
|
const responseBody = record(responseValue);
|
|
698
929
|
if (!response.ok) {
|
|
699
930
|
const error = record(responseBody.error);
|
|
700
|
-
const
|
|
701
|
-
|
|
931
|
+
const publicFailure = publicSignalDiscoveryFailure(
|
|
932
|
+
error.code || responseBody.error_code || `HTTP_${response.status}`
|
|
933
|
+
);
|
|
702
934
|
throw new import_sdk.SignalizError({
|
|
703
|
-
code,
|
|
704
|
-
message,
|
|
935
|
+
code: publicFailure.errorCode,
|
|
936
|
+
message: publicFailure.error,
|
|
705
937
|
errorType: signalsEverythingErrorType(response.status),
|
|
706
938
|
retryAfter: numberValue(responseBody.retry_after_seconds || responseBody.retry_after),
|
|
707
|
-
details:
|
|
939
|
+
details: normalizeSignalsEverythingResult(request, {
|
|
940
|
+
...responseBody,
|
|
941
|
+
success: false,
|
|
942
|
+
error_code: publicFailure.errorCode
|
|
943
|
+
})
|
|
708
944
|
});
|
|
709
945
|
}
|
|
710
946
|
return normalizeSignalsEverythingResult(request, responseBody);
|
|
@@ -716,10 +952,39 @@ function output(value, human) {
|
|
|
716
952
|
} else if (human) {
|
|
717
953
|
human();
|
|
718
954
|
} else {
|
|
719
|
-
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
955
|
+
process.stdout.write(`${JSON.stringify(publicCliValue(value), null, 2)}
|
|
720
956
|
`);
|
|
721
957
|
}
|
|
722
958
|
}
|
|
959
|
+
var INTERNAL_PRODUCT_OUTPUT_KEYS = /* @__PURE__ */ new Set([
|
|
960
|
+
"billingmetadata",
|
|
961
|
+
"historicalbillingmetadata",
|
|
962
|
+
"resultreturnedfrom",
|
|
963
|
+
"freshenrichmentused",
|
|
964
|
+
"liveprovidercalled",
|
|
965
|
+
"openroutercalled",
|
|
966
|
+
"byoopenrouterused",
|
|
967
|
+
"aiprovidercalled",
|
|
968
|
+
"byoaiused",
|
|
969
|
+
"estimatedexternalcostusd"
|
|
970
|
+
]);
|
|
971
|
+
function publicCliValue(value) {
|
|
972
|
+
if (Array.isArray(value)) return value.map(publicCliValue);
|
|
973
|
+
if (!value || typeof value !== "object") return value;
|
|
974
|
+
const output2 = {};
|
|
975
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
976
|
+
const normalizedKey = key.toLowerCase().replace(/_/g, "");
|
|
977
|
+
if (normalizedKey.includes("cache") || INTERNAL_PRODUCT_OUTPUT_KEYS.has(normalizedKey)) continue;
|
|
978
|
+
if (typeof raw === "string" && (raw.toLowerCase().includes("cache") || raw === "available_data")) {
|
|
979
|
+
if (["source", "emailsource", "emailsourcelabel", "verificationsource", "providerstatus"].includes(normalizedKey)) {
|
|
980
|
+
output2[key] = normalizedKey === "verificationsource" ? "email_verification" : "email_finder";
|
|
981
|
+
}
|
|
982
|
+
continue;
|
|
983
|
+
}
|
|
984
|
+
output2[key] = publicCliValue(raw);
|
|
985
|
+
}
|
|
986
|
+
return output2;
|
|
987
|
+
}
|
|
723
988
|
function outputFailedCoreProduct(value, fallbackMessage) {
|
|
724
989
|
const result = record(value);
|
|
725
990
|
if (result.success !== false) return false;
|
|
@@ -733,7 +998,7 @@ function outputFailedCoreProduct(value, fallbackMessage) {
|
|
|
733
998
|
}
|
|
734
999
|
function stringifyMachineJson(value, space) {
|
|
735
1000
|
const omitRaw = hasFlag("omit-raw");
|
|
736
|
-
return JSON.stringify(value, omitRaw ? (key, item) => key === "raw" ? void 0 : item : void 0, space);
|
|
1001
|
+
return JSON.stringify(publicCliValue(value), omitRaw ? (key, item) => key === "raw" ? void 0 : item : void 0, space);
|
|
737
1002
|
}
|
|
738
1003
|
function fail(message) {
|
|
739
1004
|
process.stderr.write(`${message}
|
|
@@ -814,7 +1079,7 @@ async function findEmail() {
|
|
|
814
1079
|
"linkedin-url",
|
|
815
1080
|
"company-name",
|
|
816
1081
|
"run-id",
|
|
817
|
-
"
|
|
1082
|
+
"no-wait"
|
|
818
1083
|
].filter(hasFlag);
|
|
819
1084
|
if (conflicts.length > 0) {
|
|
820
1085
|
throw new CliInputError(
|
|
@@ -833,6 +1098,9 @@ async function findEmail() {
|
|
|
833
1098
|
}
|
|
834
1099
|
const rows = readBatchInput();
|
|
835
1100
|
if (rows) {
|
|
1101
|
+
if (hasFlag("no-wait")) {
|
|
1102
|
+
throw new CliInputError("Find Email --no-wait supports one contact. Batch submissions are already durable and return a recoverable job.");
|
|
1103
|
+
}
|
|
836
1104
|
const requests = rows.map((value) => {
|
|
837
1105
|
const row = record(value);
|
|
838
1106
|
const runId2 = row.runId || row.run_id;
|
|
@@ -845,7 +1113,6 @@ async function findEmail() {
|
|
|
845
1113
|
lastName: row.lastName || row.last_name,
|
|
846
1114
|
linkedinUrl: row.linkedinUrl || row.linkedin_url || row.linkedin,
|
|
847
1115
|
companyName: row.companyName || row.company_name,
|
|
848
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
849
1116
|
idempotencyKey
|
|
850
1117
|
};
|
|
851
1118
|
});
|
|
@@ -884,7 +1151,7 @@ async function findEmail() {
|
|
|
884
1151
|
lastName,
|
|
885
1152
|
linkedinUrl,
|
|
886
1153
|
companyName: flag("company-name"),
|
|
887
|
-
|
|
1154
|
+
waitForResult: hasFlag("no-wait") ? false : void 0,
|
|
888
1155
|
idempotencyKey: flag("idempotency-key")
|
|
889
1156
|
};
|
|
890
1157
|
if (hasFlag("dry-run")) {
|
|
@@ -924,7 +1191,6 @@ async function verifyEmail(args) {
|
|
|
924
1191
|
"dry-run",
|
|
925
1192
|
"email",
|
|
926
1193
|
"verification-run-id",
|
|
927
|
-
"skip-cache",
|
|
928
1194
|
"no-wait"
|
|
929
1195
|
].filter(hasFlag);
|
|
930
1196
|
if (positionalEmail || conflicts.length > 0) {
|
|
@@ -951,22 +1217,19 @@ async function verifyEmail(args) {
|
|
|
951
1217
|
const row = record(value);
|
|
952
1218
|
return {
|
|
953
1219
|
email: String(row.email || ""),
|
|
954
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
955
1220
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
956
1221
|
};
|
|
957
1222
|
});
|
|
958
1223
|
if (hasFlag("dry-run")) {
|
|
959
1224
|
const result3 = await createClient().verifyEmails(emails, {
|
|
960
1225
|
...batchOptions(),
|
|
961
|
-
skipCache: hasFlag("skip-cache"),
|
|
962
1226
|
dryRun: true
|
|
963
1227
|
});
|
|
964
1228
|
dryRunOutput(result3);
|
|
965
1229
|
return;
|
|
966
1230
|
}
|
|
967
1231
|
const result2 = await createClient().verifyEmails(emails, {
|
|
968
|
-
...batchOptions()
|
|
969
|
-
skipCache: hasFlag("skip-cache")
|
|
1232
|
+
...batchOptions()
|
|
970
1233
|
});
|
|
971
1234
|
batchOutput(customerEmailBatch(result2, "verify"));
|
|
972
1235
|
return;
|
|
@@ -977,7 +1240,6 @@ async function verifyEmail(args) {
|
|
|
977
1240
|
throw new CliInputError("Usage: signaliz verify-email [jane@example.com] [--verification-run-id run_...]");
|
|
978
1241
|
}
|
|
979
1242
|
const options = {
|
|
980
|
-
skipCache: hasFlag("skip-cache"),
|
|
981
1243
|
verificationRunId,
|
|
982
1244
|
waitForResult: !hasFlag("no-wait"),
|
|
983
1245
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
@@ -1012,7 +1274,7 @@ async function verifyEmail(args) {
|
|
|
1012
1274
|
`);
|
|
1013
1275
|
process.stdout.write(`Recommendation: ${publicResult.recommendation}
|
|
1014
1276
|
`);
|
|
1015
|
-
process.stdout.write(`Source: ${publicResult.verification_source
|
|
1277
|
+
process.stdout.write(`Source: ${String(publicResult.verification_source || "email_verification").toLowerCase().includes("cache") ? "email_verification" : publicResult.verification_source}
|
|
1016
1278
|
`);
|
|
1017
1279
|
if (publicResult.run_id) process.stdout.write(`Run ID: ${publicResult.run_id}
|
|
1018
1280
|
`);
|
|
@@ -1022,6 +1284,39 @@ async function verifyEmail(args) {
|
|
|
1022
1284
|
}
|
|
1023
1285
|
async function companySignals() {
|
|
1024
1286
|
const jobId = flag("job-id");
|
|
1287
|
+
const removedControlFlags = [
|
|
1288
|
+
"prompt",
|
|
1289
|
+
"signal-types",
|
|
1290
|
+
"after-date",
|
|
1291
|
+
"before-date",
|
|
1292
|
+
"include-candidate-evidence",
|
|
1293
|
+
"search-mode",
|
|
1294
|
+
"model",
|
|
1295
|
+
"online",
|
|
1296
|
+
"offline",
|
|
1297
|
+
"shallow",
|
|
1298
|
+
"deep-search",
|
|
1299
|
+
"enable-deep-search",
|
|
1300
|
+
"no-summary",
|
|
1301
|
+
"outreach-intelligence",
|
|
1302
|
+
"predictive-intelligence",
|
|
1303
|
+
"credit-free-grounding-only",
|
|
1304
|
+
"skip-cache",
|
|
1305
|
+
"bypass-cache",
|
|
1306
|
+
"fresh-only",
|
|
1307
|
+
"cache-ttl-hours",
|
|
1308
|
+
"cache-ttl-seconds",
|
|
1309
|
+
"cache-enabled",
|
|
1310
|
+
"cache-policy",
|
|
1311
|
+
"target-signal-count",
|
|
1312
|
+
"provider-target-signal-count",
|
|
1313
|
+
...jobId ? [] : ["max-wait-ms"]
|
|
1314
|
+
].filter(hasFlag);
|
|
1315
|
+
if (removedControlFlags.length > 0) {
|
|
1316
|
+
throw new CliInputError(
|
|
1317
|
+
`Company Signals manages provider routing, coverage, and classifications internally; ${removedControlFlags.map((name) => `--${name}`).join(", ")} is no longer supported. Use --domain only.`
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1025
1320
|
if (jobId) {
|
|
1026
1321
|
const conflicts = [
|
|
1027
1322
|
"input",
|
|
@@ -1031,18 +1326,7 @@ async function companySignals() {
|
|
|
1031
1326
|
"company-name",
|
|
1032
1327
|
"signal-run-id",
|
|
1033
1328
|
"research-prompt",
|
|
1034
|
-
"prompt",
|
|
1035
|
-
"signal-types",
|
|
1036
|
-
"target-signal-count",
|
|
1037
1329
|
"lookback-days",
|
|
1038
|
-
"offline",
|
|
1039
|
-
"shallow",
|
|
1040
|
-
"search-mode",
|
|
1041
|
-
"no-summary",
|
|
1042
|
-
"outreach-intelligence",
|
|
1043
|
-
"predictive-intelligence",
|
|
1044
|
-
"skip-cache",
|
|
1045
|
-
"include-candidate-evidence",
|
|
1046
1330
|
"no-wait",
|
|
1047
1331
|
"concurrency"
|
|
1048
1332
|
].filter(hasFlag);
|
|
@@ -1058,7 +1342,7 @@ async function companySignals() {
|
|
|
1058
1342
|
idempotencyKey: flag("idempotency-key"),
|
|
1059
1343
|
compactDuplicates: !hasFlag("expand-duplicates")
|
|
1060
1344
|
});
|
|
1061
|
-
batchOutput(
|
|
1345
|
+
batchOutput(customerCompanySignalBatch(result2));
|
|
1062
1346
|
return;
|
|
1063
1347
|
}
|
|
1064
1348
|
rejectDurableNoWaitPollingFlags("Company Signals");
|
|
@@ -1067,59 +1351,20 @@ async function companySignals() {
|
|
|
1067
1351
|
const durableBatch = rows.length > 25;
|
|
1068
1352
|
const requests = rows.map((value) => {
|
|
1069
1353
|
const row = record(value);
|
|
1070
|
-
const online = row.online ?? !hasFlag("offline");
|
|
1071
1354
|
return {
|
|
1072
1355
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
1073
1356
|
companyDomain: row.companyDomain || row.company_domain || row.domain,
|
|
1074
|
-
|
|
1075
|
-
researchPrompt: row.researchPrompt || row.research_prompt || flag("research-prompt") || flag("prompt"),
|
|
1076
|
-
signalTypes: row.signalTypes || row.signal_types || csvFlag("signal-types"),
|
|
1077
|
-
targetSignalCount: row.targetSignalCount ?? row.target_signal_count ?? numberFlag("target-signal-count"),
|
|
1078
|
-
lookbackDays: row.lookbackDays ?? row.lookback_days ?? numberFlag("lookback-days"),
|
|
1079
|
-
online,
|
|
1080
|
-
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? (online && !hasFlag("shallow")),
|
|
1081
|
-
searchMode: companySignalSearchMode(row.searchMode ?? row.search_mode ?? flag("search-mode")),
|
|
1082
|
-
includeSummary: row.includeSummary ?? row.include_summary ?? !hasFlag("no-summary"),
|
|
1083
|
-
enableOutreachIntelligence: row.enableOutreachIntelligence ?? row.enable_outreach_intelligence,
|
|
1084
|
-
enablePredictiveIntelligence: row.enablePredictiveIntelligence ?? row.enable_predictive_intelligence,
|
|
1085
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
1086
|
-
includeCandidateEvidence: row.includeCandidateEvidence ?? row.include_candidate_evidence ?? hasFlag("include-candidate-evidence"),
|
|
1087
|
-
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
1357
|
+
domain: row.domain || row.companyDomain || row.company_domain,
|
|
1088
1358
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
1089
1359
|
};
|
|
1090
1360
|
});
|
|
1091
|
-
for (const request2 of requests) {
|
|
1092
|
-
requireIntegerInRange(request2.targetSignalCount, "targetSignalCount", 1, 15);
|
|
1093
|
-
requireIntegerInRange(request2.lookbackDays, "lookbackDays", 1, 365);
|
|
1094
|
-
requireIntegerInRange(request2.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1095
|
-
}
|
|
1096
|
-
if (durableBatch && requests.some((request2) => request2.includeCandidateEvidence === true)) {
|
|
1097
|
-
throw new CliInputError(
|
|
1098
|
-
"includeCandidateEvidence is not supported in Company Signals batches larger than 25 because rejected evidence diagnostics are intentionally excluded from durable scale storage; split diagnostic requests into batches of at most 25."
|
|
1099
|
-
);
|
|
1100
|
-
}
|
|
1101
1361
|
if (durableBatch) {
|
|
1102
|
-
const controlKey = (request2) => JSON.stringify({
|
|
1103
|
-
researchPrompt: request2.researchPrompt,
|
|
1104
|
-
signalTypes: request2.signalTypes,
|
|
1105
|
-
targetSignalCount: request2.targetSignalCount,
|
|
1106
|
-
lookbackDays: request2.lookbackDays,
|
|
1107
|
-
online: request2.online,
|
|
1108
|
-
enableDeepSearch: request2.enableDeepSearch,
|
|
1109
|
-
searchMode: request2.searchMode ?? "balanced",
|
|
1110
|
-
includeSummary: request2.includeSummary,
|
|
1111
|
-
enableOutreachIntelligence: request2.enableOutreachIntelligence,
|
|
1112
|
-
enablePredictiveIntelligence: request2.enablePredictiveIntelligence,
|
|
1113
|
-
skipCache: request2.skipCache,
|
|
1114
|
-
includeCandidateEvidence: request2.includeCandidateEvidence
|
|
1115
|
-
});
|
|
1116
|
-
const firstControlKey = controlKey(requests[0]);
|
|
1117
1362
|
const incompatible = requests.some(
|
|
1118
|
-
(request2) => Boolean(stringValue(request2.signalRunId)) || Boolean(stringValue(request2.idempotencyKey)) || !stringValue(request2.
|
|
1363
|
+
(request2) => Boolean(stringValue(request2.signalRunId)) || Boolean(stringValue(request2.idempotencyKey)) || !stringValue(request2.domain)
|
|
1119
1364
|
);
|
|
1120
1365
|
if (incompatible) {
|
|
1121
1366
|
throw new CliInputError(
|
|
1122
|
-
"Company Signals batches larger than 25 require
|
|
1367
|
+
"Company Signals batches larger than 25 require domain-only rows without per-row controls or recovery IDs."
|
|
1123
1368
|
);
|
|
1124
1369
|
}
|
|
1125
1370
|
} else if (hasFlag("no-wait") && !hasFlag("dry-run")) {
|
|
@@ -1144,7 +1389,7 @@ async function companySignals() {
|
|
|
1144
1389
|
return;
|
|
1145
1390
|
}
|
|
1146
1391
|
const result2 = await createClient().enrichCompanies(requests, batchOptions());
|
|
1147
|
-
batchOutput(
|
|
1392
|
+
batchOutput(customerCompanySignalBatch(result2));
|
|
1148
1393
|
return;
|
|
1149
1394
|
}
|
|
1150
1395
|
if (hasFlag("no-wait")) {
|
|
@@ -1154,49 +1399,30 @@ async function companySignals() {
|
|
|
1154
1399
|
throw new CliInputError("Company Signals --poll-interval-ms requires --input or --job-id.");
|
|
1155
1400
|
}
|
|
1156
1401
|
const companyDomain = flag("domain") || flag("company-domain");
|
|
1157
|
-
const companyName = flag("company-name");
|
|
1158
1402
|
const signalRunId = flag("signal-run-id");
|
|
1159
|
-
if (!companyDomain && !
|
|
1403
|
+
if (!companyDomain && !signalRunId) {
|
|
1160
1404
|
throw new CliInputError("Usage: signaliz company-signals --domain example.com");
|
|
1161
1405
|
}
|
|
1162
1406
|
const request = {
|
|
1163
1407
|
signalRunId,
|
|
1164
|
-
companyDomain,
|
|
1165
|
-
companyName,
|
|
1166
|
-
researchPrompt: flag("research-prompt") || flag("prompt"),
|
|
1167
|
-
signalTypes: csvFlag("signal-types"),
|
|
1168
|
-
targetSignalCount: numberFlag("target-signal-count"),
|
|
1169
|
-
lookbackDays: numberFlag("lookback-days"),
|
|
1170
|
-
online: !hasFlag("offline"),
|
|
1171
|
-
enableDeepSearch: !hasFlag("offline") && !hasFlag("shallow"),
|
|
1172
|
-
searchMode: companySignalSearchMode(flag("search-mode")),
|
|
1173
|
-
includeSummary: !hasFlag("no-summary"),
|
|
1174
|
-
enableOutreachIntelligence: hasFlag("outreach-intelligence") || void 0,
|
|
1175
|
-
enablePredictiveIntelligence: hasFlag("predictive-intelligence") || void 0,
|
|
1176
|
-
skipCache: hasFlag("skip-cache"),
|
|
1177
|
-
includeCandidateEvidence: hasFlag("include-candidate-evidence"),
|
|
1178
|
-
maxWaitMs: numberFlag("max-wait-ms"),
|
|
1408
|
+
domain: companyDomain,
|
|
1179
1409
|
idempotencyKey: flag("idempotency-key")
|
|
1180
1410
|
};
|
|
1181
|
-
requireIntegerInRange(request.targetSignalCount, "targetSignalCount", 1, 15);
|
|
1182
|
-
requireIntegerInRange(request.lookbackDays, "lookbackDays", 1, 365);
|
|
1183
|
-
requireIntegerInRange(request.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1184
1411
|
if (hasFlag("dry-run")) {
|
|
1185
1412
|
const result2 = await createClient().enrichCompanySignals({ ...request, dryRun: true });
|
|
1186
1413
|
dryRunOutput(result2);
|
|
1187
1414
|
return;
|
|
1188
1415
|
}
|
|
1189
|
-
const result =
|
|
1416
|
+
const result = customerCompanySignalResult(await createClient().enrichCompanySignals(request));
|
|
1190
1417
|
if (outputFailedCoreProduct(result, "Company Signal enrichment failed")) return;
|
|
1191
1418
|
output(result, () => {
|
|
1192
1419
|
process.stdout.write(`Company: ${result.company.name || result.company.domain}
|
|
1193
1420
|
Signals: ${result.signalCount}
|
|
1194
1421
|
`);
|
|
1195
|
-
process.stdout.write(`
|
|
1196
|
-
Credits used: ${result.creditsUsed || 0}
|
|
1422
|
+
process.stdout.write(`Credits used: ${result.creditsUsed || 0}
|
|
1197
1423
|
`);
|
|
1198
|
-
for (const signal of result.signals.slice(0,
|
|
1199
|
-
process.stdout.write(
|
|
1424
|
+
for (const signal of result.signals.slice(0, PUBLIC_COMPANY_SIGNAL_MAX_COVERAGE_COUNT)) {
|
|
1425
|
+
process.stdout.write(`${signal.date} ${signal.signal_type} ${signal.signal_title} ${signal.signal_summary} ${signal.source}
|
|
1200
1426
|
`);
|
|
1201
1427
|
}
|
|
1202
1428
|
});
|
|
@@ -1208,6 +1434,8 @@ function signalQueryFromArgs(args) {
|
|
|
1208
1434
|
"--limit",
|
|
1209
1435
|
"--sources",
|
|
1210
1436
|
"--lookback-days",
|
|
1437
|
+
"--after-date",
|
|
1438
|
+
"--before-date",
|
|
1211
1439
|
"--icp-context",
|
|
1212
1440
|
"--signal-search-run-id",
|
|
1213
1441
|
"--idempotency-key",
|
|
@@ -1253,9 +1481,12 @@ async function signals(args) {
|
|
|
1253
1481
|
limit: numberFlag("limit"),
|
|
1254
1482
|
sources: sourceValues,
|
|
1255
1483
|
lookbackDays: numberFlag("lookback-days"),
|
|
1484
|
+
afterDate: flag("after-date"),
|
|
1485
|
+
beforeDate: flag("before-date"),
|
|
1256
1486
|
idempotencyKey: flag("idempotency-key"),
|
|
1257
1487
|
dryRun: hasFlag("dry-run")
|
|
1258
1488
|
};
|
|
1489
|
+
validateSignalDateWindow(request.afterDate, request.beforeDate, request.lookbackDays);
|
|
1259
1490
|
let result = await discoverSignalsEverything(request);
|
|
1260
1491
|
if (hasFlag("wait") && !request.dryRun) {
|
|
1261
1492
|
const maxWaitMs = numberFlag("max-wait-ms") ?? 15 * 6e4;
|
|
@@ -1271,57 +1502,135 @@ async function signals(args) {
|
|
|
1271
1502
|
}
|
|
1272
1503
|
output(result, () => {
|
|
1273
1504
|
if (result.status === "planned") {
|
|
1274
|
-
process.stdout.write(`Signals Everything plan: ${result.requestedCount} distinct companies. No source acquisition was launched.
|
|
1505
|
+
process.stdout.write(`Signals Everything plan: ${result.requestedCount} distinct companies. No source acquisition was launched. Included on plan; 0 Signaliz credits charged.
|
|
1275
1506
|
`);
|
|
1276
1507
|
return;
|
|
1277
1508
|
}
|
|
1278
1509
|
if (signalDiscoveryIsPending(result.status)) {
|
|
1279
1510
|
process.stdout.write(`Signals Everything ${result.status}: ${result.signalSearchRunId}
|
|
1511
|
+
`);
|
|
1512
|
+
process.stdout.write(`Billing: included on plan \xB7 ${result.creditsCharged} Signaliz credits charged.
|
|
1280
1513
|
`);
|
|
1281
1514
|
process.stdout.write(`Resume with --signal-search-run-id ${result.signalSearchRunId}${hasFlag("wait") ? " after the current wait window" : ""}.
|
|
1282
1515
|
`);
|
|
1283
1516
|
return;
|
|
1284
1517
|
}
|
|
1285
1518
|
if (!result.success || result.status === "failed") {
|
|
1286
|
-
process.stdout.write(`${
|
|
1519
|
+
process.stdout.write(`${result.error || "Signals Everything failed."}
|
|
1287
1520
|
`);
|
|
1288
1521
|
return;
|
|
1289
1522
|
}
|
|
1290
|
-
const available = result.availableCompanySignalCount ?? result.signalCount;
|
|
1291
1523
|
process.stdout.write(`Qualified companies returned: ${result.signalCount}
|
|
1292
1524
|
`);
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
`
|
|
1297
|
-
);
|
|
1298
|
-
}
|
|
1299
|
-
const guardrail = result.costGuardrail;
|
|
1300
|
-
if (guardrail) {
|
|
1301
|
-
process.stdout.write(
|
|
1302
|
-
`Source cost per qualified company: ${guardrail.costPerQualifiedSignalUsd ?? "n/a"} (must be < $${guardrail.maxCostPerQualifiedSignalUsd})
|
|
1303
|
-
`
|
|
1304
|
-
);
|
|
1305
|
-
if (guardrail.identityResolutionCostUsd !== void 0) {
|
|
1306
|
-
const identityCost = guardrail.identityResolutionCostUsd === null ? "unavailable" : `$${guardrail.identityResolutionCostUsd}`;
|
|
1307
|
-
const identityRequests = guardrail.identityProviderRequests;
|
|
1308
|
-
process.stdout.write(
|
|
1309
|
-
`Identity resolution cost: ${identityCost}${identityRequests === void 0 ? "" : ` across ${identityRequests} identity lookup request${identityRequests === 1 ? "" : "s"}`}${guardrail.identityCostSource ? ` (${guardrail.identityCostSource})` : ""}.
|
|
1310
|
-
`
|
|
1311
|
-
);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1525
|
+
process.stdout.write(`Billing: ${result.billingStatus === "included" ? "included on plan" : "receipt unavailable"} \xB7 ${result.creditsCharged} Signaliz credits charged.
|
|
1526
|
+
`);
|
|
1527
|
+
if (result.idempotencyReplayed) process.stdout.write("Retained result reused; no new source acquisition.\n");
|
|
1314
1528
|
for (const signal of result.signals.slice(0, 20)) {
|
|
1315
|
-
process.stdout.write(`- ${signal.
|
|
1316
|
-
${signal.
|
|
1529
|
+
process.stdout.write(`- ${signal.company_name} (${signal.domain}) \u2014 ${signal.date} \u2014 ${signal.signal_type}
|
|
1530
|
+
${signal.source}
|
|
1317
1531
|
`);
|
|
1318
1532
|
}
|
|
1319
1533
|
if (result.signalCount > 20) process.stdout.write(`Showing 20 of ${result.signalCount}; use --json for the full result.
|
|
1320
|
-
`);
|
|
1321
|
-
for (const warning of result.warnings || []) process.stdout.write(`Warning: ${warning}
|
|
1322
1534
|
`);
|
|
1323
1535
|
});
|
|
1324
1536
|
}
|
|
1537
|
+
async function flow() {
|
|
1538
|
+
const runId = flag("run-id");
|
|
1539
|
+
if (runId) {
|
|
1540
|
+
const conflicts = [
|
|
1541
|
+
"signal-query",
|
|
1542
|
+
"query",
|
|
1543
|
+
"campaign-offer",
|
|
1544
|
+
"offer",
|
|
1545
|
+
"limit",
|
|
1546
|
+
"lookback-days",
|
|
1547
|
+
"after-date",
|
|
1548
|
+
"before-date",
|
|
1549
|
+
"people-titles",
|
|
1550
|
+
"people-per-company",
|
|
1551
|
+
"copy-research-prompt",
|
|
1552
|
+
"icp-context",
|
|
1553
|
+
"dry-run",
|
|
1554
|
+
"idempotency-key",
|
|
1555
|
+
"deep-search"
|
|
1556
|
+
].filter(hasFlag);
|
|
1557
|
+
if (conflicts.length > 0) {
|
|
1558
|
+
throw new CliInputError(`Flow --run-id cannot be combined with ${conflicts.map((name) => `--${name}`).join(", ")}.`);
|
|
1559
|
+
}
|
|
1560
|
+
const result2 = await createClient().getFlow(runId);
|
|
1561
|
+
output(result2, () => {
|
|
1562
|
+
const outcome = record(result2.result);
|
|
1563
|
+
process.stdout.write(`Signaliz Flow ${result2.status}: ${result2.runId}
|
|
1564
|
+
`);
|
|
1565
|
+
process.stdout.write(`Verified leads: ${Number(outcome.emails_verified || 0)} \xB7 Copy drafts: ${Number(outcome.copies_ready || 0)}
|
|
1566
|
+
`);
|
|
1567
|
+
const billing = record(outcome.billing);
|
|
1568
|
+
if (billing.creditsCharged !== void 0) process.stdout.write(`Credits charged: ${Number(billing.creditsCharged || 0)}
|
|
1569
|
+
`);
|
|
1570
|
+
});
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
const signalQuery = flag("signal-query") || flag("query");
|
|
1574
|
+
const campaignOffer = flag("campaign-offer") || flag("offer");
|
|
1575
|
+
if (!signalQuery || !campaignOffer) {
|
|
1576
|
+
fail('Usage: signaliz flow --signal-query "companies with recent hiring" --campaign-offer "your offer" [--limit 5]');
|
|
1577
|
+
}
|
|
1578
|
+
const removedFlowControls = [
|
|
1579
|
+
"after-date",
|
|
1580
|
+
"before-date",
|
|
1581
|
+
"deep-search",
|
|
1582
|
+
"enable-deep-search",
|
|
1583
|
+
"signal-types",
|
|
1584
|
+
"search-mode",
|
|
1585
|
+
"model",
|
|
1586
|
+
"online",
|
|
1587
|
+
"offline",
|
|
1588
|
+
"shallow",
|
|
1589
|
+
"skip-cache",
|
|
1590
|
+
"bypass-cache",
|
|
1591
|
+
"fresh-only",
|
|
1592
|
+
"cache-ttl-hours",
|
|
1593
|
+
"cache-ttl-seconds",
|
|
1594
|
+
"cache-enabled",
|
|
1595
|
+
"cache-policy",
|
|
1596
|
+
"target-signal-count",
|
|
1597
|
+
"provider-target-signal-count"
|
|
1598
|
+
].filter(hasFlag);
|
|
1599
|
+
if (removedFlowControls.length > 0) {
|
|
1600
|
+
throw new CliInputError(
|
|
1601
|
+
`Flow selects signal acquisition internally; ${removedFlowControls.map((name) => `--${name}`).join(", ")} is no longer supported. Use --lookback-days to set the maximum evidence age.`
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
const request = {
|
|
1605
|
+
signalQuery,
|
|
1606
|
+
campaignOffer,
|
|
1607
|
+
signalLimit: numberFlag("limit"),
|
|
1608
|
+
lookbackDays: numberFlag("lookback-days"),
|
|
1609
|
+
icpContext: flag("icp-context"),
|
|
1610
|
+
peopleTitles: csvFlag("people-titles"),
|
|
1611
|
+
peoplePerCompany: numberFlag("people-per-company"),
|
|
1612
|
+
copyResearchPrompt: flag("copy-research-prompt") || flag("research-prompt"),
|
|
1613
|
+
approvalRequired: true,
|
|
1614
|
+
idempotencyKey: flag("idempotency-key")
|
|
1615
|
+
};
|
|
1616
|
+
requireIntegerInRange(request.signalLimit, "limit", 1, 25);
|
|
1617
|
+
requireIntegerInRange(request.lookbackDays, "lookbackDays", 1, 365);
|
|
1618
|
+
requireIntegerInRange(request.peoplePerCompany, "peoplePerCompany", 1, 5);
|
|
1619
|
+
if (hasFlag("dry-run")) {
|
|
1620
|
+
const result2 = await createClient().startFlow({ ...request, dryRun: true });
|
|
1621
|
+
output(result2, () => {
|
|
1622
|
+
process.stdout.write(`Signaliz Flow plan: up to ${result2.plan.maximumReviewCandidates} review candidates. No work was dispatched.
|
|
1623
|
+
`);
|
|
1624
|
+
for (const safeguard of result2.plan.safeguards) process.stdout.write(`- ${safeguard}
|
|
1625
|
+
`);
|
|
1626
|
+
});
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
const result = await createClient().startFlow(request);
|
|
1630
|
+
output(result, () => process.stdout.write(`Signaliz Flow started: ${result.runId}
|
|
1631
|
+
Check status: signaliz flow --run-id ${result.runId}
|
|
1632
|
+
`));
|
|
1633
|
+
}
|
|
1325
1634
|
async function signalToCopy() {
|
|
1326
1635
|
const jobId = flag("job-id");
|
|
1327
1636
|
if (jobId) {
|
|
@@ -1337,8 +1646,12 @@ async function signalToCopy() {
|
|
|
1337
1646
|
"research-prompt",
|
|
1338
1647
|
"prompt",
|
|
1339
1648
|
"lookback-days",
|
|
1649
|
+
"copy-evidence-mode",
|
|
1650
|
+
"without-signals",
|
|
1340
1651
|
"signal-run-id",
|
|
1341
|
-
"
|
|
1652
|
+
"signal-search-run-id",
|
|
1653
|
+
"fact-id",
|
|
1654
|
+
"event-id",
|
|
1342
1655
|
"deep-search",
|
|
1343
1656
|
"no-wait",
|
|
1344
1657
|
"concurrency"
|
|
@@ -1369,27 +1682,28 @@ async function signalToCopy() {
|
|
|
1369
1682
|
personName: row.personName || row.person_name,
|
|
1370
1683
|
title: row.title,
|
|
1371
1684
|
campaignOffer: row.campaignOffer || row.campaign_offer || row.offer,
|
|
1372
|
-
|
|
1373
|
-
lookbackDays:
|
|
1685
|
+
copyEvidenceMode: row.copyEvidenceMode || row.copy_evidence_mode || flag("copy-evidence-mode") || (hasFlag("without-signals") ? "firmographic" : void 0),
|
|
1686
|
+
lookbackDays: 365,
|
|
1374
1687
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
1375
|
-
|
|
1688
|
+
signalSearchRunId: row.signalSearchRunId || row.signal_search_run_id,
|
|
1689
|
+
factId: row.factId || row.fact_id,
|
|
1690
|
+
eventId: row.eventId || row.event_id,
|
|
1376
1691
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? hasFlag("deep-search"),
|
|
1377
1692
|
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
1378
1693
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
1379
1694
|
};
|
|
1380
1695
|
});
|
|
1381
1696
|
for (const request2 of requests) {
|
|
1382
|
-
requireIntegerInRange(request2.lookbackDays, "lookbackDays", 1, 365);
|
|
1383
1697
|
requireIntegerInRange(request2.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1384
1698
|
requireSignalToCopyIdentity(request2);
|
|
1385
1699
|
}
|
|
1386
1700
|
if (durableBatch) {
|
|
1387
1701
|
const invalidIndex = requests.findIndex(
|
|
1388
|
-
(request2) => request2.
|
|
1702
|
+
(request2) => Boolean(stringValue(request2.idempotencyKey)) || request2.maxWaitMs !== void 0 || Boolean(stringValue(request2.signalSearchRunId)) || Boolean(stringValue(request2.factId)) || Boolean(stringValue(request2.eventId)) || !stringValue(request2.companyDomain) || !stringValue(request2.personName) || !stringValue(request2.title) || !stringValue(request2.campaignOffer)
|
|
1389
1703
|
);
|
|
1390
1704
|
if (invalidIndex >= 0) {
|
|
1391
1705
|
throw new CliInputError(
|
|
1392
|
-
`Signal to Copy
|
|
1706
|
+
`Signal to Copy batch row ${invalidIndex} uses canonical references (supported only in batches of 25 or fewer), uses unsupported row-level execution controls, or lacks required recipient fields. Put wait and idempotency controls on the batch command.`
|
|
1393
1707
|
);
|
|
1394
1708
|
}
|
|
1395
1709
|
} else if (hasFlag("no-wait") && !hasFlag("dry-run")) {
|
|
@@ -1416,7 +1730,7 @@ async function signalToCopy() {
|
|
|
1416
1730
|
return;
|
|
1417
1731
|
}
|
|
1418
1732
|
if (hasFlag("no-wait")) {
|
|
1419
|
-
throw new CliInputError("Signal to Copy --no-wait requires --input with more than 25
|
|
1733
|
+
throw new CliInputError("Signal to Copy --no-wait requires --input with more than 25 rows.");
|
|
1420
1734
|
}
|
|
1421
1735
|
if (hasFlag("poll-interval-ms")) {
|
|
1422
1736
|
throw new CliInputError("Signal to Copy --poll-interval-ms requires --input or --job-id.");
|
|
@@ -1431,15 +1745,16 @@ async function signalToCopy() {
|
|
|
1431
1745
|
personName,
|
|
1432
1746
|
title,
|
|
1433
1747
|
campaignOffer,
|
|
1434
|
-
|
|
1435
|
-
lookbackDays:
|
|
1748
|
+
copyEvidenceMode: flag("copy-evidence-mode") || (hasFlag("without-signals") ? "firmographic" : void 0),
|
|
1749
|
+
lookbackDays: 365,
|
|
1436
1750
|
signalRunId,
|
|
1437
|
-
|
|
1751
|
+
signalSearchRunId: flag("signal-search-run-id"),
|
|
1752
|
+
factId: flag("fact-id"),
|
|
1753
|
+
eventId: flag("event-id"),
|
|
1438
1754
|
enableDeepSearch: hasFlag("deep-search"),
|
|
1439
1755
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
1440
1756
|
idempotencyKey: flag("idempotency-key")
|
|
1441
1757
|
};
|
|
1442
|
-
requireIntegerInRange(request.lookbackDays, "lookbackDays", 1, 365);
|
|
1443
1758
|
requireIntegerInRange(request.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1444
1759
|
requireSignalToCopyIdentity(request);
|
|
1445
1760
|
if (hasFlag("dry-run")) {
|
|
@@ -1459,8 +1774,16 @@ async function signalToCopy() {
|
|
|
1459
1774
|
Confidence: ${result.confidence}
|
|
1460
1775
|
Evidence: ${result.evidenceUrl}
|
|
1461
1776
|
`);
|
|
1462
|
-
|
|
1463
|
-
|
|
1777
|
+
const canonicalPointers = [
|
|
1778
|
+
result.signalSearchRunId ? `snapshot=${result.signalSearchRunId}` : "",
|
|
1779
|
+
result.factId ? `fact=${result.factId}` : "",
|
|
1780
|
+
result.eventId ? `event=${result.eventId}` : ""
|
|
1781
|
+
].filter(Boolean);
|
|
1782
|
+
if (canonicalPointers.length > 0) {
|
|
1783
|
+
process.stdout.write(`Canonical evidence: ${canonicalPointers.join(" ")}
|
|
1784
|
+
`);
|
|
1785
|
+
}
|
|
1786
|
+
process.stdout.write(`Credits used: ${result.creditsUsed || 0}
|
|
1464
1787
|
`);
|
|
1465
1788
|
for (const variation of result.variations) {
|
|
1466
1789
|
process.stdout.write(`
|
|
@@ -1510,6 +1833,108 @@ Import this file into your MCP client.
|
|
|
1510
1833
|
`);
|
|
1511
1834
|
});
|
|
1512
1835
|
}
|
|
1836
|
+
function awarenessSchedule() {
|
|
1837
|
+
const direct = flag("schedule-cron");
|
|
1838
|
+
if (direct) return direct;
|
|
1839
|
+
const schedule = flag("schedule");
|
|
1840
|
+
if (!schedule) return void 0;
|
|
1841
|
+
const schedules = {
|
|
1842
|
+
every_6_hours: "0 */6 * * *",
|
|
1843
|
+
daily: "0 8 * * *",
|
|
1844
|
+
every_2_days: "0 8 */2 * *",
|
|
1845
|
+
weekly: "0 8 * * 1"
|
|
1846
|
+
};
|
|
1847
|
+
if (!schedules[schedule]) {
|
|
1848
|
+
throw new CliInputError("--schedule must be every_6_hours, daily, every_2_days, or weekly");
|
|
1849
|
+
}
|
|
1850
|
+
return schedules[schedule];
|
|
1851
|
+
}
|
|
1852
|
+
async function awareness(args) {
|
|
1853
|
+
const action = args[0];
|
|
1854
|
+
const monitorId = flag("monitor-id");
|
|
1855
|
+
if (!action || !["create", "list", "run", "signals", "pause", "resume", "delete"].includes(action)) {
|
|
1856
|
+
throw new CliInputError("Usage: signaliz awareness <create|list|run|signals|pause|resume|delete>");
|
|
1857
|
+
}
|
|
1858
|
+
const client = createClient();
|
|
1859
|
+
if (action === "create") {
|
|
1860
|
+
const companyName = flag("company-name");
|
|
1861
|
+
const domain = flag("domain");
|
|
1862
|
+
if (!companyName || !domain) {
|
|
1863
|
+
throw new CliInputError('Usage: signaliz awareness create --company-name "Acme" --domain acme.com');
|
|
1864
|
+
}
|
|
1865
|
+
const monthlyCreditCap = numberFlag("monthly-credit-cap");
|
|
1866
|
+
if (monthlyCreditCap !== void 0) requireIntegerInRange(monthlyCreditCap, "--monthly-credit-cap", 1, 1e4);
|
|
1867
|
+
const lookbackDays = numberFlag("lookback-days");
|
|
1868
|
+
if (lookbackDays !== void 0) requireIntegerInRange(lookbackDays, "--lookback-days", 1, 365);
|
|
1869
|
+
const signalTypes = csvFlag("signal-types");
|
|
1870
|
+
const result2 = await client.createSignalMonitor({
|
|
1871
|
+
companyName,
|
|
1872
|
+
domain,
|
|
1873
|
+
template: flag("template") === "basic" ? "basic" : "full_intelligence",
|
|
1874
|
+
scheduleCron: awarenessSchedule(),
|
|
1875
|
+
monthlyCreditCap,
|
|
1876
|
+
webhookUrl: flag("webhook-url"),
|
|
1877
|
+
signalConfig: {
|
|
1878
|
+
...lookbackDays !== void 0 ? { lookback_days: lookbackDays } : {},
|
|
1879
|
+
...signalTypes ? { signal_types: signalTypes } : {},
|
|
1880
|
+
...flag("research-prompt") ? { research_prompt: flag("research-prompt") } : {}
|
|
1881
|
+
}
|
|
1882
|
+
});
|
|
1883
|
+
output(result2, () => process.stdout.write(`Monitor created: ${String(result2.monitor?.id || "pending")}
|
|
1884
|
+
`));
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
if (action === "list") {
|
|
1888
|
+
const offset = numberFlag("offset");
|
|
1889
|
+
if (offset !== void 0) requireIntegerInRange(offset, "--offset", 0, 1e4);
|
|
1890
|
+
const result2 = await client.listSignalMonitors(numberFlag("limit"), offset);
|
|
1891
|
+
output(result2, () => {
|
|
1892
|
+
for (const monitor of result2.monitors || []) {
|
|
1893
|
+
process.stdout.write(`${String(monitor.company_name)} ${String(monitor.status)} ${String(monitor.next_run_at || "not scheduled")} ${String(monitor.id)}
|
|
1894
|
+
`);
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
if (action === "signals") {
|
|
1900
|
+
const offset = numberFlag("offset");
|
|
1901
|
+
if (offset !== void 0) requireIntegerInRange(offset, "--offset", 0, 1e4);
|
|
1902
|
+
const result2 = customerSignalAwarenessResult(await client.signalAwareness({
|
|
1903
|
+
action: "list_signals",
|
|
1904
|
+
monitorId,
|
|
1905
|
+
limit: numberFlag("limit"),
|
|
1906
|
+
offset
|
|
1907
|
+
}));
|
|
1908
|
+
output(result2, () => {
|
|
1909
|
+
for (const signal of result2.signals || []) {
|
|
1910
|
+
process.stdout.write(`${signal.signal_type} ${signal.signal_title} ${signal.signal_summary} ${signal.source} ${signal.date} ${signal.company_name} ${signal.domain}
|
|
1911
|
+
`);
|
|
1912
|
+
}
|
|
1913
|
+
});
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
if (!monitorId) throw new CliInputError(`signaliz awareness ${action} requires --monitor-id <uuid>`);
|
|
1917
|
+
if (action === "run") {
|
|
1918
|
+
if (hasFlag("dry-run")) {
|
|
1919
|
+
const result3 = await client.signalAwareness({ action: "manual_run", monitorId, idempotencyKey: flag("idempotency-key"), dryRun: true });
|
|
1920
|
+
output(result3);
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
const result2 = await client.runSignalMonitor(monitorId, flag("idempotency-key"));
|
|
1924
|
+
output(result2, () => {
|
|
1925
|
+
process.stdout.write(`Run: ${String(result2.run?.id || result2.runId || "pending")}
|
|
1926
|
+
Signals: ${String(result2.run?.signals_found || 0)}
|
|
1927
|
+
Credits used: ${result2.creditsUsed || 0}
|
|
1928
|
+
`);
|
|
1929
|
+
});
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
const result = await client.signalAwareness(
|
|
1933
|
+
action === "delete" ? { action: "delete", monitorId } : { action: "update", monitorId, updates: { status: action === "resume" ? "active" : "paused", ...action === "resume" ? { auto_paused: false, auto_pause_reason: null } : {} } }
|
|
1934
|
+
);
|
|
1935
|
+
output(result, () => process.stdout.write(`Monitor ${action === "delete" ? "deleted" : action === "resume" ? "resumed" : "paused"}: ${monitorId}
|
|
1936
|
+
`));
|
|
1937
|
+
}
|
|
1513
1938
|
async function main() {
|
|
1514
1939
|
const [, , command, ...args] = process.argv;
|
|
1515
1940
|
if (!command || ["help", "--help", "-h"].includes(command)) {
|
|
@@ -1527,6 +1952,12 @@ async function main() {
|
|
|
1527
1952
|
return companySignals();
|
|
1528
1953
|
case "signals":
|
|
1529
1954
|
return signals(args);
|
|
1955
|
+
case "signals-first":
|
|
1956
|
+
return signals(args);
|
|
1957
|
+
case "awareness":
|
|
1958
|
+
return awareness(args);
|
|
1959
|
+
case "flow":
|
|
1960
|
+
return flow();
|
|
1530
1961
|
case "signal-to-copy":
|
|
1531
1962
|
return signalToCopy();
|
|
1532
1963
|
case "health":
|