@signaliz/cli 1.0.62 → 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 +707 -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,10 @@ 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
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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,
|
|
526
|
+
billing_replayed: typeof raw.billing_replayed === "boolean" ? raw.billing_replayed : result.billingReplayed === true,
|
|
527
|
+
...typeof raw.idempotency_replayed === "boolean" || typeof result.idempotencyReplayed === "boolean" ? {
|
|
528
|
+
idempotency_replayed: typeof raw.idempotency_replayed === "boolean" ? raw.idempotency_replayed : result.idempotencyReplayed === true
|
|
529
|
+
} : {},
|
|
300
530
|
billing_metadata: normalizedBillingMetadata,
|
|
301
531
|
...Object.keys(historicalBillingMetadata2).length > 0 ? { historical_billing_metadata: historicalBillingMetadata2 } : {},
|
|
302
532
|
...estimatedExternalCostUsd2 !== null ? { estimated_external_cost_usd: estimatedExternalCostUsd2 } : {},
|
|
@@ -305,11 +535,6 @@ function customerEmailResult(value, kind) {
|
|
|
305
535
|
recovery_mode: raw.recovery_mode,
|
|
306
536
|
recovery_status: raw.recovery_status ?? "completed"
|
|
307
537
|
} : {},
|
|
308
|
-
...raw.cache_publication_status ? {
|
|
309
|
-
cache_publication_status: raw.cache_publication_status,
|
|
310
|
-
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
311
|
-
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
312
|
-
} : {},
|
|
313
538
|
...terminalErrorCode ? {
|
|
314
539
|
email: null,
|
|
315
540
|
success: false,
|
|
@@ -344,11 +569,6 @@ function customerEmailResult(value, kind) {
|
|
|
344
569
|
const isMalformed = typeof result.isMalformed === "boolean" ? result.isMalformed : raw.is_malformed === true;
|
|
345
570
|
const quality = typeof result.quality === "string" ? result.quality : typeof raw.quality === "string" ? raw.quality : null;
|
|
346
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";
|
|
347
|
-
const cacheHit = typeof raw.cache_hit === "boolean" ? raw.cache_hit : result.cacheHit === true;
|
|
348
|
-
const negativeCacheHit = typeof raw.negative_cache_hit === "boolean" ? raw.negative_cache_hit : result.negativeCacheHit === true;
|
|
349
|
-
const negativeCacheTtlSeconds = safeNonNegativeNumber(
|
|
350
|
-
result.negativeCacheTtlSeconds ?? raw.negative_cache_ttl_seconds
|
|
351
|
-
);
|
|
352
572
|
const billingMetadata = customerEmailBillingMetadata(
|
|
353
573
|
Object.keys(record(result.billingMetadata)).length > 0 ? result.billingMetadata : raw.billing_metadata
|
|
354
574
|
);
|
|
@@ -378,24 +598,15 @@ function customerEmailResult(value, kind) {
|
|
|
378
598
|
verification_source: result.verificationSource ?? raw.verification_source ?? "email_verification",
|
|
379
599
|
...result.verificationObservedAt ?? raw.verification_observed_at ? { verification_observed_at: result.verificationObservedAt ?? raw.verification_observed_at } : {},
|
|
380
600
|
failure_reason: result.failureReason ?? raw.failure_reason ?? (verifiedForSending ? "none" : isCatchAll ? "catch_all_domain_not_send_safe" : "verification_not_send_safe"),
|
|
381
|
-
cache_hit: cacheHit,
|
|
382
|
-
negative_cache_hit: negativeCacheHit,
|
|
383
|
-
negative_cache_ttl_seconds: negativeCacheTtlSeconds,
|
|
384
|
-
cache_tier: result.cacheTier ?? raw.cache_tier ?? null,
|
|
385
|
-
result_returned_from: result.resultReturnedFrom ?? raw.result_returned_from ?? null,
|
|
386
|
-
fresh_enrichment_used: typeof raw.fresh_enrichment_used === "boolean" ? raw.fresh_enrichment_used : result.freshEnrichmentUsed === true,
|
|
387
|
-
live_provider_called: typeof raw.live_provider_called === "boolean" ? raw.live_provider_called : result.liveProviderCalled === true,
|
|
388
601
|
billing_replayed: typeof raw.billing_replayed === "boolean" ? raw.billing_replayed : result.billingReplayed === true,
|
|
602
|
+
...typeof raw.idempotency_replayed === "boolean" || typeof result.idempotencyReplayed === "boolean" ? {
|
|
603
|
+
idempotency_replayed: typeof raw.idempotency_replayed === "boolean" ? raw.idempotency_replayed : result.idempotencyReplayed === true
|
|
604
|
+
} : {},
|
|
389
605
|
billing_metadata: billingMetadata,
|
|
390
606
|
...Object.keys(historicalBillingMetadata).length > 0 ? { historical_billing_metadata: historicalBillingMetadata } : {},
|
|
391
607
|
...estimatedExternalCostUsd !== null ? { estimated_external_cost_usd: estimatedExternalCostUsd } : {},
|
|
392
608
|
...verificationRunId ? { verification_run_id: verificationRunId } : {},
|
|
393
|
-
...runId ? { run_id: runId } : {}
|
|
394
|
-
...raw.cache_publication_status ? {
|
|
395
|
-
cache_publication_status: raw.cache_publication_status,
|
|
396
|
-
cache_publication_retry_eligible: raw.cache_publication_retry_eligible === true,
|
|
397
|
-
...raw.suggested_action ? { suggested_action: raw.suggested_action } : {}
|
|
398
|
-
} : {}
|
|
609
|
+
...runId ? { run_id: runId } : {}
|
|
399
610
|
};
|
|
400
611
|
}
|
|
401
612
|
function customerEmailBatch(value, kind) {
|
|
@@ -423,15 +634,39 @@ function customerSignalResult(value) {
|
|
|
423
634
|
return {
|
|
424
635
|
...result,
|
|
425
636
|
...Object.keys(billingMetadata).length > 0 ? { billingMetadata } : {},
|
|
426
|
-
resultReturnedFrom: result.resultReturnedFrom ?? raw.result_returned_from,
|
|
427
|
-
cacheHit: result.cacheHit ?? raw.cache_hit,
|
|
428
|
-
freshEnrichmentUsed: result.freshEnrichmentUsed ?? raw.fresh_enrichment_used,
|
|
429
637
|
creditsUsed: result.creditsUsed ?? raw.credits_used,
|
|
430
|
-
liveProviderCalled: result.liveProviderCalled ?? raw.live_provider_called,
|
|
431
638
|
aiProviderCalled: result.aiProviderCalled ?? raw.ai_provider_called,
|
|
432
639
|
byoAiUsed: result.byoAiUsed ?? raw.byo_ai_used
|
|
433
640
|
};
|
|
434
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
|
+
}
|
|
435
670
|
function customerSignalBatch(value) {
|
|
436
671
|
return {
|
|
437
672
|
...value,
|
|
@@ -441,6 +676,31 @@ function customerSignalBatch(value) {
|
|
|
441
676
|
})
|
|
442
677
|
};
|
|
443
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
|
+
}
|
|
444
704
|
function batchOptions() {
|
|
445
705
|
return {
|
|
446
706
|
concurrency: numberFlag("concurrency"),
|
|
@@ -546,12 +806,40 @@ function numberValue(value) {
|
|
|
546
806
|
const number = Number(value);
|
|
547
807
|
return Number.isFinite(number) ? number : void 0;
|
|
548
808
|
}
|
|
549
|
-
function nullableNumberValue(value) {
|
|
550
|
-
return value === null ? null : numberValue(value);
|
|
551
|
-
}
|
|
552
809
|
function stringValue(value) {
|
|
553
810
|
return typeof value === "string" ? value.trim() : "";
|
|
554
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
|
+
}
|
|
555
843
|
function hasFindEmailLinkedInIdentity(value) {
|
|
556
844
|
const linkedinUrl = stringValue(value);
|
|
557
845
|
if (!linkedinUrl) return false;
|
|
@@ -575,35 +863,11 @@ function signalsEverythingErrorType(status) {
|
|
|
575
863
|
}
|
|
576
864
|
function normalizeSignalsEverythingResult(request, value) {
|
|
577
865
|
const rawSignals = Array.isArray(value.signals) ? value.signals : [];
|
|
578
|
-
const
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
if (!name || !domain) {
|
|
584
|
-
throw new Error("Signals Everything response violated the company attribution contract.");
|
|
585
|
-
}
|
|
586
|
-
const evidence = Array.isArray(signal.evidence) ? signal.evidence.map((rawEvidence) => {
|
|
587
|
-
const item = record(rawEvidence);
|
|
588
|
-
return {
|
|
589
|
-
url: stringValue(item.url),
|
|
590
|
-
publishedAt: stringValue(item.published_at || item.publishedAt),
|
|
591
|
-
source: stringValue(item.source)
|
|
592
|
-
};
|
|
593
|
-
}).filter((item) => Boolean(item.url)) : [];
|
|
594
|
-
const eventDate = stringValue(signal.event_date || signal.date);
|
|
595
|
-
const sourceUrl = stringValue(signal.source_url || signal.url);
|
|
596
|
-
if (!eventDate || !sourceUrl || !evidence.some((item) => item.url === sourceUrl && item.publishedAt === eventDate)) {
|
|
597
|
-
throw new Error("Signals Everything response violated the dated-evidence and source-URL contract.");
|
|
598
|
-
}
|
|
599
|
-
return {
|
|
600
|
-
company: { name, domain },
|
|
601
|
-
title: stringValue(signal.title || signal.summary || signal.content),
|
|
602
|
-
eventDate,
|
|
603
|
-
sourceUrl,
|
|
604
|
-
evidence
|
|
605
|
-
};
|
|
606
|
-
});
|
|
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
|
+
);
|
|
607
871
|
const statusValue = stringValue(value.status).toLowerCase();
|
|
608
872
|
const statuses = /* @__PURE__ */ new Set([
|
|
609
873
|
"planned",
|
|
@@ -614,52 +878,24 @@ function normalizeSignalsEverythingResult(request, value) {
|
|
|
614
878
|
"failed"
|
|
615
879
|
]);
|
|
616
880
|
const status = statuses.has(statusValue) ? statusValue : signals2.length > 0 ? "completed" : "failed";
|
|
617
|
-
const
|
|
618
|
-
const
|
|
619
|
-
const
|
|
620
|
-
const identityCostSource = stringValue(guardrail.identity_cost_source);
|
|
621
|
-
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;
|
|
622
884
|
return {
|
|
623
885
|
success: value.success !== false,
|
|
624
886
|
status,
|
|
625
887
|
signalSearchRunId: stringValue(value.signal_search_run_id || request.signalSearchRunId),
|
|
626
888
|
query: stringValue(value.query || request.query),
|
|
627
|
-
requestedCount
|
|
889
|
+
...requestedCount === void 0 ? {} : { requestedCount },
|
|
628
890
|
nextPollAfterSeconds: numberValue(value.next_poll_after_seconds),
|
|
629
891
|
signals: signals2,
|
|
630
892
|
signalCount: signals2.length,
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
},
|
|
634
|
-
...
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
projectedSourceCostUsd: nullableNumberValue(guardrail.projected_source_cost_usd),
|
|
638
|
-
maxSourceCostUsd: nullableNumberValue(guardrail.max_source_cost_usd),
|
|
639
|
-
projectedCostPerRequestedCompanySignalUsd: nullableNumberValue(
|
|
640
|
-
guardrail.projected_cost_per_requested_company_signal_usd
|
|
641
|
-
),
|
|
642
|
-
sourceCostUsd: nullableNumberValue(guardrail.source_cost_usd),
|
|
643
|
-
costSource: ["observed", "catalog_preflight", "catalog_bounded", "mixed", "unavailable"].includes(costSource) ? costSource : void 0,
|
|
644
|
-
costPerQualifiedSignalUsd: nullableNumberValue(guardrail.cost_per_qualified_signal_usd),
|
|
645
|
-
identityResolutionCostUsd: nullableNumberValue(guardrail.identity_resolution_cost_usd),
|
|
646
|
-
identityCostSource: [
|
|
647
|
-
"observed_zero_credit_receipts",
|
|
648
|
-
"contractual_zero_cost",
|
|
649
|
-
"not_used",
|
|
650
|
-
"unavailable"
|
|
651
|
-
].includes(identityCostSource) ? identityCostSource : void 0,
|
|
652
|
-
identityProviderRequests: numberValue(guardrail.identity_provider_requests),
|
|
653
|
-
qualifiedCompanySignalCount: numberValue(guardrail.qualified_company_signal_count),
|
|
654
|
-
returnedCompanySignalCount: numberValue(guardrail.returned_company_signal_count),
|
|
655
|
-
availableCompanySignalCount: numberValue(guardrail.available_company_signal_count),
|
|
656
|
-
acquisitionCandidateLimit: numberValue(guardrail.acquisition_candidate_limit),
|
|
657
|
-
minimumQualifiedCompanySignals: numberValue(guardrail.minimum_qualified_company_signals),
|
|
658
|
-
withinLimit: guardrail.within_limit === true
|
|
659
|
-
}
|
|
660
|
-
},
|
|
661
|
-
...warnings?.length ? { warnings } : {},
|
|
662
|
-
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 } : {}
|
|
663
899
|
};
|
|
664
900
|
}
|
|
665
901
|
async function discoverSignalsEverything(request) {
|
|
@@ -674,6 +910,8 @@ async function discoverSignalsEverything(request) {
|
|
|
674
910
|
limit: request.limit ?? 100,
|
|
675
911
|
...request.sources ? { sources: request.sources } : {},
|
|
676
912
|
...request.lookbackDays === void 0 ? {} : { lookback_days: request.lookbackDays },
|
|
913
|
+
...request.afterDate ? { after_date: request.afterDate } : {},
|
|
914
|
+
...request.beforeDate ? { before_date: request.beforeDate } : {},
|
|
677
915
|
...request.dryRun === void 0 ? {} : { dry_run: request.dryRun },
|
|
678
916
|
...request.idempotencyKey ? { idempotency_key: request.idempotencyKey } : {}
|
|
679
917
|
};
|
|
@@ -690,14 +928,19 @@ async function discoverSignalsEverything(request) {
|
|
|
690
928
|
const responseBody = record(responseValue);
|
|
691
929
|
if (!response.ok) {
|
|
692
930
|
const error = record(responseBody.error);
|
|
693
|
-
const
|
|
694
|
-
|
|
931
|
+
const publicFailure = publicSignalDiscoveryFailure(
|
|
932
|
+
error.code || responseBody.error_code || `HTTP_${response.status}`
|
|
933
|
+
);
|
|
695
934
|
throw new import_sdk.SignalizError({
|
|
696
|
-
code,
|
|
697
|
-
message,
|
|
935
|
+
code: publicFailure.errorCode,
|
|
936
|
+
message: publicFailure.error,
|
|
698
937
|
errorType: signalsEverythingErrorType(response.status),
|
|
699
938
|
retryAfter: numberValue(responseBody.retry_after_seconds || responseBody.retry_after),
|
|
700
|
-
details:
|
|
939
|
+
details: normalizeSignalsEverythingResult(request, {
|
|
940
|
+
...responseBody,
|
|
941
|
+
success: false,
|
|
942
|
+
error_code: publicFailure.errorCode
|
|
943
|
+
})
|
|
701
944
|
});
|
|
702
945
|
}
|
|
703
946
|
return normalizeSignalsEverythingResult(request, responseBody);
|
|
@@ -709,10 +952,39 @@ function output(value, human) {
|
|
|
709
952
|
} else if (human) {
|
|
710
953
|
human();
|
|
711
954
|
} else {
|
|
712
|
-
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
955
|
+
process.stdout.write(`${JSON.stringify(publicCliValue(value), null, 2)}
|
|
713
956
|
`);
|
|
714
957
|
}
|
|
715
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
|
+
}
|
|
716
988
|
function outputFailedCoreProduct(value, fallbackMessage) {
|
|
717
989
|
const result = record(value);
|
|
718
990
|
if (result.success !== false) return false;
|
|
@@ -726,7 +998,7 @@ function outputFailedCoreProduct(value, fallbackMessage) {
|
|
|
726
998
|
}
|
|
727
999
|
function stringifyMachineJson(value, space) {
|
|
728
1000
|
const omitRaw = hasFlag("omit-raw");
|
|
729
|
-
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);
|
|
730
1002
|
}
|
|
731
1003
|
function fail(message) {
|
|
732
1004
|
process.stderr.write(`${message}
|
|
@@ -807,7 +1079,7 @@ async function findEmail() {
|
|
|
807
1079
|
"linkedin-url",
|
|
808
1080
|
"company-name",
|
|
809
1081
|
"run-id",
|
|
810
|
-
"
|
|
1082
|
+
"no-wait"
|
|
811
1083
|
].filter(hasFlag);
|
|
812
1084
|
if (conflicts.length > 0) {
|
|
813
1085
|
throw new CliInputError(
|
|
@@ -826,6 +1098,9 @@ async function findEmail() {
|
|
|
826
1098
|
}
|
|
827
1099
|
const rows = readBatchInput();
|
|
828
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
|
+
}
|
|
829
1104
|
const requests = rows.map((value) => {
|
|
830
1105
|
const row = record(value);
|
|
831
1106
|
const runId2 = row.runId || row.run_id;
|
|
@@ -838,7 +1113,6 @@ async function findEmail() {
|
|
|
838
1113
|
lastName: row.lastName || row.last_name,
|
|
839
1114
|
linkedinUrl: row.linkedinUrl || row.linkedin_url || row.linkedin,
|
|
840
1115
|
companyName: row.companyName || row.company_name,
|
|
841
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
842
1116
|
idempotencyKey
|
|
843
1117
|
};
|
|
844
1118
|
});
|
|
@@ -877,7 +1151,7 @@ async function findEmail() {
|
|
|
877
1151
|
lastName,
|
|
878
1152
|
linkedinUrl,
|
|
879
1153
|
companyName: flag("company-name"),
|
|
880
|
-
|
|
1154
|
+
waitForResult: hasFlag("no-wait") ? false : void 0,
|
|
881
1155
|
idempotencyKey: flag("idempotency-key")
|
|
882
1156
|
};
|
|
883
1157
|
if (hasFlag("dry-run")) {
|
|
@@ -917,7 +1191,6 @@ async function verifyEmail(args) {
|
|
|
917
1191
|
"dry-run",
|
|
918
1192
|
"email",
|
|
919
1193
|
"verification-run-id",
|
|
920
|
-
"skip-cache",
|
|
921
1194
|
"no-wait"
|
|
922
1195
|
].filter(hasFlag);
|
|
923
1196
|
if (positionalEmail || conflicts.length > 0) {
|
|
@@ -944,22 +1217,19 @@ async function verifyEmail(args) {
|
|
|
944
1217
|
const row = record(value);
|
|
945
1218
|
return {
|
|
946
1219
|
email: String(row.email || ""),
|
|
947
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
948
1220
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
949
1221
|
};
|
|
950
1222
|
});
|
|
951
1223
|
if (hasFlag("dry-run")) {
|
|
952
1224
|
const result3 = await createClient().verifyEmails(emails, {
|
|
953
1225
|
...batchOptions(),
|
|
954
|
-
skipCache: hasFlag("skip-cache"),
|
|
955
1226
|
dryRun: true
|
|
956
1227
|
});
|
|
957
1228
|
dryRunOutput(result3);
|
|
958
1229
|
return;
|
|
959
1230
|
}
|
|
960
1231
|
const result2 = await createClient().verifyEmails(emails, {
|
|
961
|
-
...batchOptions()
|
|
962
|
-
skipCache: hasFlag("skip-cache")
|
|
1232
|
+
...batchOptions()
|
|
963
1233
|
});
|
|
964
1234
|
batchOutput(customerEmailBatch(result2, "verify"));
|
|
965
1235
|
return;
|
|
@@ -970,7 +1240,6 @@ async function verifyEmail(args) {
|
|
|
970
1240
|
throw new CliInputError("Usage: signaliz verify-email [jane@example.com] [--verification-run-id run_...]");
|
|
971
1241
|
}
|
|
972
1242
|
const options = {
|
|
973
|
-
skipCache: hasFlag("skip-cache"),
|
|
974
1243
|
verificationRunId,
|
|
975
1244
|
waitForResult: !hasFlag("no-wait"),
|
|
976
1245
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
@@ -1005,7 +1274,7 @@ async function verifyEmail(args) {
|
|
|
1005
1274
|
`);
|
|
1006
1275
|
process.stdout.write(`Recommendation: ${publicResult.recommendation}
|
|
1007
1276
|
`);
|
|
1008
|
-
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}
|
|
1009
1278
|
`);
|
|
1010
1279
|
if (publicResult.run_id) process.stdout.write(`Run ID: ${publicResult.run_id}
|
|
1011
1280
|
`);
|
|
@@ -1015,6 +1284,39 @@ async function verifyEmail(args) {
|
|
|
1015
1284
|
}
|
|
1016
1285
|
async function companySignals() {
|
|
1017
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
|
+
}
|
|
1018
1320
|
if (jobId) {
|
|
1019
1321
|
const conflicts = [
|
|
1020
1322
|
"input",
|
|
@@ -1024,18 +1326,7 @@ async function companySignals() {
|
|
|
1024
1326
|
"company-name",
|
|
1025
1327
|
"signal-run-id",
|
|
1026
1328
|
"research-prompt",
|
|
1027
|
-
"prompt",
|
|
1028
|
-
"signal-types",
|
|
1029
|
-
"target-signal-count",
|
|
1030
1329
|
"lookback-days",
|
|
1031
|
-
"offline",
|
|
1032
|
-
"shallow",
|
|
1033
|
-
"search-mode",
|
|
1034
|
-
"no-summary",
|
|
1035
|
-
"outreach-intelligence",
|
|
1036
|
-
"predictive-intelligence",
|
|
1037
|
-
"skip-cache",
|
|
1038
|
-
"include-candidate-evidence",
|
|
1039
1330
|
"no-wait",
|
|
1040
1331
|
"concurrency"
|
|
1041
1332
|
].filter(hasFlag);
|
|
@@ -1051,7 +1342,7 @@ async function companySignals() {
|
|
|
1051
1342
|
idempotencyKey: flag("idempotency-key"),
|
|
1052
1343
|
compactDuplicates: !hasFlag("expand-duplicates")
|
|
1053
1344
|
});
|
|
1054
|
-
batchOutput(
|
|
1345
|
+
batchOutput(customerCompanySignalBatch(result2));
|
|
1055
1346
|
return;
|
|
1056
1347
|
}
|
|
1057
1348
|
rejectDurableNoWaitPollingFlags("Company Signals");
|
|
@@ -1060,59 +1351,20 @@ async function companySignals() {
|
|
|
1060
1351
|
const durableBatch = rows.length > 25;
|
|
1061
1352
|
const requests = rows.map((value) => {
|
|
1062
1353
|
const row = record(value);
|
|
1063
|
-
const online = row.online ?? !hasFlag("offline");
|
|
1064
1354
|
return {
|
|
1065
1355
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
1066
1356
|
companyDomain: row.companyDomain || row.company_domain || row.domain,
|
|
1067
|
-
|
|
1068
|
-
researchPrompt: row.researchPrompt || row.research_prompt || flag("research-prompt") || flag("prompt"),
|
|
1069
|
-
signalTypes: row.signalTypes || row.signal_types || csvFlag("signal-types"),
|
|
1070
|
-
targetSignalCount: row.targetSignalCount ?? row.target_signal_count ?? numberFlag("target-signal-count"),
|
|
1071
|
-
lookbackDays: row.lookbackDays ?? row.lookback_days ?? numberFlag("lookback-days"),
|
|
1072
|
-
online,
|
|
1073
|
-
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? (online && !hasFlag("shallow")),
|
|
1074
|
-
searchMode: companySignalSearchMode(row.searchMode ?? row.search_mode ?? flag("search-mode")),
|
|
1075
|
-
includeSummary: row.includeSummary ?? row.include_summary ?? !hasFlag("no-summary"),
|
|
1076
|
-
enableOutreachIntelligence: row.enableOutreachIntelligence ?? row.enable_outreach_intelligence,
|
|
1077
|
-
enablePredictiveIntelligence: row.enablePredictiveIntelligence ?? row.enable_predictive_intelligence,
|
|
1078
|
-
skipCache: row.skipCache ?? row.skip_cache ?? hasFlag("skip-cache"),
|
|
1079
|
-
includeCandidateEvidence: row.includeCandidateEvidence ?? row.include_candidate_evidence ?? hasFlag("include-candidate-evidence"),
|
|
1080
|
-
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
1357
|
+
domain: row.domain || row.companyDomain || row.company_domain,
|
|
1081
1358
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
1082
1359
|
};
|
|
1083
1360
|
});
|
|
1084
|
-
for (const request2 of requests) {
|
|
1085
|
-
requireIntegerInRange(request2.targetSignalCount, "targetSignalCount", 1, 15);
|
|
1086
|
-
requireIntegerInRange(request2.lookbackDays, "lookbackDays", 1, 365);
|
|
1087
|
-
requireIntegerInRange(request2.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1088
|
-
}
|
|
1089
|
-
if (durableBatch && requests.some((request2) => request2.includeCandidateEvidence === true)) {
|
|
1090
|
-
throw new CliInputError(
|
|
1091
|
-
"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."
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
1361
|
if (durableBatch) {
|
|
1095
|
-
const controlKey = (request2) => JSON.stringify({
|
|
1096
|
-
researchPrompt: request2.researchPrompt,
|
|
1097
|
-
signalTypes: request2.signalTypes,
|
|
1098
|
-
targetSignalCount: request2.targetSignalCount,
|
|
1099
|
-
lookbackDays: request2.lookbackDays,
|
|
1100
|
-
online: request2.online,
|
|
1101
|
-
enableDeepSearch: request2.enableDeepSearch,
|
|
1102
|
-
searchMode: request2.searchMode ?? "balanced",
|
|
1103
|
-
includeSummary: request2.includeSummary,
|
|
1104
|
-
enableOutreachIntelligence: request2.enableOutreachIntelligence,
|
|
1105
|
-
enablePredictiveIntelligence: request2.enablePredictiveIntelligence,
|
|
1106
|
-
skipCache: request2.skipCache,
|
|
1107
|
-
includeCandidateEvidence: request2.includeCandidateEvidence
|
|
1108
|
-
});
|
|
1109
|
-
const firstControlKey = controlKey(requests[0]);
|
|
1110
1362
|
const incompatible = requests.some(
|
|
1111
|
-
(request2) => Boolean(stringValue(request2.signalRunId)) || Boolean(stringValue(request2.idempotencyKey)) || !stringValue(request2.
|
|
1363
|
+
(request2) => Boolean(stringValue(request2.signalRunId)) || Boolean(stringValue(request2.idempotencyKey)) || !stringValue(request2.domain)
|
|
1112
1364
|
);
|
|
1113
1365
|
if (incompatible) {
|
|
1114
1366
|
throw new CliInputError(
|
|
1115
|
-
"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."
|
|
1116
1368
|
);
|
|
1117
1369
|
}
|
|
1118
1370
|
} else if (hasFlag("no-wait") && !hasFlag("dry-run")) {
|
|
@@ -1137,7 +1389,7 @@ async function companySignals() {
|
|
|
1137
1389
|
return;
|
|
1138
1390
|
}
|
|
1139
1391
|
const result2 = await createClient().enrichCompanies(requests, batchOptions());
|
|
1140
|
-
batchOutput(
|
|
1392
|
+
batchOutput(customerCompanySignalBatch(result2));
|
|
1141
1393
|
return;
|
|
1142
1394
|
}
|
|
1143
1395
|
if (hasFlag("no-wait")) {
|
|
@@ -1147,49 +1399,30 @@ async function companySignals() {
|
|
|
1147
1399
|
throw new CliInputError("Company Signals --poll-interval-ms requires --input or --job-id.");
|
|
1148
1400
|
}
|
|
1149
1401
|
const companyDomain = flag("domain") || flag("company-domain");
|
|
1150
|
-
const companyName = flag("company-name");
|
|
1151
1402
|
const signalRunId = flag("signal-run-id");
|
|
1152
|
-
if (!companyDomain && !
|
|
1403
|
+
if (!companyDomain && !signalRunId) {
|
|
1153
1404
|
throw new CliInputError("Usage: signaliz company-signals --domain example.com");
|
|
1154
1405
|
}
|
|
1155
1406
|
const request = {
|
|
1156
1407
|
signalRunId,
|
|
1157
|
-
companyDomain,
|
|
1158
|
-
companyName,
|
|
1159
|
-
researchPrompt: flag("research-prompt") || flag("prompt"),
|
|
1160
|
-
signalTypes: csvFlag("signal-types"),
|
|
1161
|
-
targetSignalCount: numberFlag("target-signal-count"),
|
|
1162
|
-
lookbackDays: numberFlag("lookback-days"),
|
|
1163
|
-
online: !hasFlag("offline"),
|
|
1164
|
-
enableDeepSearch: !hasFlag("offline") && !hasFlag("shallow"),
|
|
1165
|
-
searchMode: companySignalSearchMode(flag("search-mode")),
|
|
1166
|
-
includeSummary: !hasFlag("no-summary"),
|
|
1167
|
-
enableOutreachIntelligence: hasFlag("outreach-intelligence") || void 0,
|
|
1168
|
-
enablePredictiveIntelligence: hasFlag("predictive-intelligence") || void 0,
|
|
1169
|
-
skipCache: hasFlag("skip-cache"),
|
|
1170
|
-
includeCandidateEvidence: hasFlag("include-candidate-evidence"),
|
|
1171
|
-
maxWaitMs: numberFlag("max-wait-ms"),
|
|
1408
|
+
domain: companyDomain,
|
|
1172
1409
|
idempotencyKey: flag("idempotency-key")
|
|
1173
1410
|
};
|
|
1174
|
-
requireIntegerInRange(request.targetSignalCount, "targetSignalCount", 1, 15);
|
|
1175
|
-
requireIntegerInRange(request.lookbackDays, "lookbackDays", 1, 365);
|
|
1176
|
-
requireIntegerInRange(request.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1177
1411
|
if (hasFlag("dry-run")) {
|
|
1178
1412
|
const result2 = await createClient().enrichCompanySignals({ ...request, dryRun: true });
|
|
1179
1413
|
dryRunOutput(result2);
|
|
1180
1414
|
return;
|
|
1181
1415
|
}
|
|
1182
|
-
const result =
|
|
1416
|
+
const result = customerCompanySignalResult(await createClient().enrichCompanySignals(request));
|
|
1183
1417
|
if (outputFailedCoreProduct(result, "Company Signal enrichment failed")) return;
|
|
1184
1418
|
output(result, () => {
|
|
1185
1419
|
process.stdout.write(`Company: ${result.company.name || result.company.domain}
|
|
1186
1420
|
Signals: ${result.signalCount}
|
|
1187
1421
|
`);
|
|
1188
|
-
process.stdout.write(`
|
|
1189
|
-
Credits used: ${result.creditsUsed || 0}
|
|
1422
|
+
process.stdout.write(`Credits used: ${result.creditsUsed || 0}
|
|
1190
1423
|
`);
|
|
1191
|
-
for (const signal of result.signals.slice(0,
|
|
1192
|
-
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}
|
|
1193
1426
|
`);
|
|
1194
1427
|
}
|
|
1195
1428
|
});
|
|
@@ -1201,6 +1434,8 @@ function signalQueryFromArgs(args) {
|
|
|
1201
1434
|
"--limit",
|
|
1202
1435
|
"--sources",
|
|
1203
1436
|
"--lookback-days",
|
|
1437
|
+
"--after-date",
|
|
1438
|
+
"--before-date",
|
|
1204
1439
|
"--icp-context",
|
|
1205
1440
|
"--signal-search-run-id",
|
|
1206
1441
|
"--idempotency-key",
|
|
@@ -1246,9 +1481,12 @@ async function signals(args) {
|
|
|
1246
1481
|
limit: numberFlag("limit"),
|
|
1247
1482
|
sources: sourceValues,
|
|
1248
1483
|
lookbackDays: numberFlag("lookback-days"),
|
|
1484
|
+
afterDate: flag("after-date"),
|
|
1485
|
+
beforeDate: flag("before-date"),
|
|
1249
1486
|
idempotencyKey: flag("idempotency-key"),
|
|
1250
1487
|
dryRun: hasFlag("dry-run")
|
|
1251
1488
|
};
|
|
1489
|
+
validateSignalDateWindow(request.afterDate, request.beforeDate, request.lookbackDays);
|
|
1252
1490
|
let result = await discoverSignalsEverything(request);
|
|
1253
1491
|
if (hasFlag("wait") && !request.dryRun) {
|
|
1254
1492
|
const maxWaitMs = numberFlag("max-wait-ms") ?? 15 * 6e4;
|
|
@@ -1264,57 +1502,135 @@ async function signals(args) {
|
|
|
1264
1502
|
}
|
|
1265
1503
|
output(result, () => {
|
|
1266
1504
|
if (result.status === "planned") {
|
|
1267
|
-
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.
|
|
1268
1506
|
`);
|
|
1269
1507
|
return;
|
|
1270
1508
|
}
|
|
1271
1509
|
if (signalDiscoveryIsPending(result.status)) {
|
|
1272
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.
|
|
1273
1513
|
`);
|
|
1274
1514
|
process.stdout.write(`Resume with --signal-search-run-id ${result.signalSearchRunId}${hasFlag("wait") ? " after the current wait window" : ""}.
|
|
1275
1515
|
`);
|
|
1276
1516
|
return;
|
|
1277
1517
|
}
|
|
1278
1518
|
if (!result.success || result.status === "failed") {
|
|
1279
|
-
process.stdout.write(`${
|
|
1519
|
+
process.stdout.write(`${result.error || "Signals Everything failed."}
|
|
1280
1520
|
`);
|
|
1281
1521
|
return;
|
|
1282
1522
|
}
|
|
1283
|
-
const available = result.availableCompanySignalCount ?? result.signalCount;
|
|
1284
1523
|
process.stdout.write(`Qualified companies returned: ${result.signalCount}
|
|
1285
1524
|
`);
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
`
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1292
|
-
const guardrail = result.costGuardrail;
|
|
1293
|
-
if (guardrail) {
|
|
1294
|
-
process.stdout.write(
|
|
1295
|
-
`Source cost per qualified company: ${guardrail.costPerQualifiedSignalUsd ?? "n/a"} (must be < $${guardrail.maxCostPerQualifiedSignalUsd})
|
|
1296
|
-
`
|
|
1297
|
-
);
|
|
1298
|
-
if (guardrail.identityResolutionCostUsd !== void 0) {
|
|
1299
|
-
const identityCost = guardrail.identityResolutionCostUsd === null ? "unavailable" : `$${guardrail.identityResolutionCostUsd}`;
|
|
1300
|
-
const identityRequests = guardrail.identityProviderRequests;
|
|
1301
|
-
process.stdout.write(
|
|
1302
|
-
`Identity resolution cost: ${identityCost}${identityRequests === void 0 ? "" : ` across ${identityRequests} identity lookup request${identityRequests === 1 ? "" : "s"}`}${guardrail.identityCostSource ? ` (${guardrail.identityCostSource})` : ""}.
|
|
1303
|
-
`
|
|
1304
|
-
);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
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");
|
|
1307
1528
|
for (const signal of result.signals.slice(0, 20)) {
|
|
1308
|
-
process.stdout.write(`- ${signal.
|
|
1309
|
-
${signal.
|
|
1529
|
+
process.stdout.write(`- ${signal.company_name} (${signal.domain}) \u2014 ${signal.date} \u2014 ${signal.signal_type}
|
|
1530
|
+
${signal.source}
|
|
1310
1531
|
`);
|
|
1311
1532
|
}
|
|
1312
1533
|
if (result.signalCount > 20) process.stdout.write(`Showing 20 of ${result.signalCount}; use --json for the full result.
|
|
1313
|
-
`);
|
|
1314
|
-
for (const warning of result.warnings || []) process.stdout.write(`Warning: ${warning}
|
|
1315
1534
|
`);
|
|
1316
1535
|
});
|
|
1317
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
|
+
}
|
|
1318
1634
|
async function signalToCopy() {
|
|
1319
1635
|
const jobId = flag("job-id");
|
|
1320
1636
|
if (jobId) {
|
|
@@ -1330,8 +1646,12 @@ async function signalToCopy() {
|
|
|
1330
1646
|
"research-prompt",
|
|
1331
1647
|
"prompt",
|
|
1332
1648
|
"lookback-days",
|
|
1649
|
+
"copy-evidence-mode",
|
|
1650
|
+
"without-signals",
|
|
1333
1651
|
"signal-run-id",
|
|
1334
|
-
"
|
|
1652
|
+
"signal-search-run-id",
|
|
1653
|
+
"fact-id",
|
|
1654
|
+
"event-id",
|
|
1335
1655
|
"deep-search",
|
|
1336
1656
|
"no-wait",
|
|
1337
1657
|
"concurrency"
|
|
@@ -1362,27 +1682,28 @@ async function signalToCopy() {
|
|
|
1362
1682
|
personName: row.personName || row.person_name,
|
|
1363
1683
|
title: row.title,
|
|
1364
1684
|
campaignOffer: row.campaignOffer || row.campaign_offer || row.offer,
|
|
1365
|
-
|
|
1366
|
-
lookbackDays:
|
|
1685
|
+
copyEvidenceMode: row.copyEvidenceMode || row.copy_evidence_mode || flag("copy-evidence-mode") || (hasFlag("without-signals") ? "firmographic" : void 0),
|
|
1686
|
+
lookbackDays: 365,
|
|
1367
1687
|
signalRunId: row.signalRunId || row.signal_run_id,
|
|
1368
|
-
|
|
1688
|
+
signalSearchRunId: row.signalSearchRunId || row.signal_search_run_id,
|
|
1689
|
+
factId: row.factId || row.fact_id,
|
|
1690
|
+
eventId: row.eventId || row.event_id,
|
|
1369
1691
|
enableDeepSearch: row.enableDeepSearch ?? row.enable_deep_search ?? hasFlag("deep-search"),
|
|
1370
1692
|
maxWaitMs: row.maxWaitMs ?? row.max_wait_ms ?? (durableBatch ? void 0 : numberFlag("max-wait-ms")),
|
|
1371
1693
|
idempotencyKey: row.idempotencyKey || row.idempotency_key
|
|
1372
1694
|
};
|
|
1373
1695
|
});
|
|
1374
1696
|
for (const request2 of requests) {
|
|
1375
|
-
requireIntegerInRange(request2.lookbackDays, "lookbackDays", 1, 365);
|
|
1376
1697
|
requireIntegerInRange(request2.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1377
1698
|
requireSignalToCopyIdentity(request2);
|
|
1378
1699
|
}
|
|
1379
1700
|
if (durableBatch) {
|
|
1380
1701
|
const invalidIndex = requests.findIndex(
|
|
1381
|
-
(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)
|
|
1382
1703
|
);
|
|
1383
1704
|
if (invalidIndex >= 0) {
|
|
1384
1705
|
throw new CliInputError(
|
|
1385
|
-
`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.`
|
|
1386
1707
|
);
|
|
1387
1708
|
}
|
|
1388
1709
|
} else if (hasFlag("no-wait") && !hasFlag("dry-run")) {
|
|
@@ -1409,7 +1730,7 @@ async function signalToCopy() {
|
|
|
1409
1730
|
return;
|
|
1410
1731
|
}
|
|
1411
1732
|
if (hasFlag("no-wait")) {
|
|
1412
|
-
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.");
|
|
1413
1734
|
}
|
|
1414
1735
|
if (hasFlag("poll-interval-ms")) {
|
|
1415
1736
|
throw new CliInputError("Signal to Copy --poll-interval-ms requires --input or --job-id.");
|
|
@@ -1424,15 +1745,16 @@ async function signalToCopy() {
|
|
|
1424
1745
|
personName,
|
|
1425
1746
|
title,
|
|
1426
1747
|
campaignOffer,
|
|
1427
|
-
|
|
1428
|
-
lookbackDays:
|
|
1748
|
+
copyEvidenceMode: flag("copy-evidence-mode") || (hasFlag("without-signals") ? "firmographic" : void 0),
|
|
1749
|
+
lookbackDays: 365,
|
|
1429
1750
|
signalRunId,
|
|
1430
|
-
|
|
1751
|
+
signalSearchRunId: flag("signal-search-run-id"),
|
|
1752
|
+
factId: flag("fact-id"),
|
|
1753
|
+
eventId: flag("event-id"),
|
|
1431
1754
|
enableDeepSearch: hasFlag("deep-search"),
|
|
1432
1755
|
maxWaitMs: numberFlag("max-wait-ms"),
|
|
1433
1756
|
idempotencyKey: flag("idempotency-key")
|
|
1434
1757
|
};
|
|
1435
|
-
requireIntegerInRange(request.lookbackDays, "lookbackDays", 1, 365);
|
|
1436
1758
|
requireIntegerInRange(request.maxWaitMs, "maxWaitMs", 1e4, 12e4);
|
|
1437
1759
|
requireSignalToCopyIdentity(request);
|
|
1438
1760
|
if (hasFlag("dry-run")) {
|
|
@@ -1452,8 +1774,16 @@ async function signalToCopy() {
|
|
|
1452
1774
|
Confidence: ${result.confidence}
|
|
1453
1775
|
Evidence: ${result.evidenceUrl}
|
|
1454
1776
|
`);
|
|
1455
|
-
|
|
1456
|
-
|
|
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}
|
|
1457
1787
|
`);
|
|
1458
1788
|
for (const variation of result.variations) {
|
|
1459
1789
|
process.stdout.write(`
|
|
@@ -1503,6 +1833,108 @@ Import this file into your MCP client.
|
|
|
1503
1833
|
`);
|
|
1504
1834
|
});
|
|
1505
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
|
+
}
|
|
1506
1938
|
async function main() {
|
|
1507
1939
|
const [, , command, ...args] = process.argv;
|
|
1508
1940
|
if (!command || ["help", "--help", "-h"].includes(command)) {
|
|
@@ -1520,6 +1952,12 @@ async function main() {
|
|
|
1520
1952
|
return companySignals();
|
|
1521
1953
|
case "signals":
|
|
1522
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();
|
|
1523
1961
|
case "signal-to-copy":
|
|
1524
1962
|
return signalToCopy();
|
|
1525
1963
|
case "health":
|