@audienti/cli 0.1.11 → 0.1.17
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/CHANGELOG.md +50 -0
- package/README.md +48 -0
- package/package.json +1 -1
- package/skills/audienti/SKILL.md +3 -0
- package/src/api-client.js +177 -0
- package/src/cli.js +1887 -156
package/src/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseArgs } from "node:util";
|
|
2
2
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
4
|
import { ApiError, AudientiClient, DEFAULT_HOST, normalizeHost } from "./api-client.js";
|
|
5
5
|
import { configPath, deleteConfig, maskToken, readConfig, writeConfig } from "./config.js";
|
|
6
6
|
|
|
@@ -17,6 +17,8 @@ const DEFAULT_LIST_LIMIT = 20;
|
|
|
17
17
|
const API_MAX_LIST_LIMIT = 100;
|
|
18
18
|
const DEFAULT_LOOKUP_TIMEOUT_SECONDS = 60;
|
|
19
19
|
const DEFAULT_LOOKUP_POLL_INTERVAL_SECONDS = 2;
|
|
20
|
+
const PACKAGE_NAME = "@audienti/cli";
|
|
21
|
+
const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
|
|
20
22
|
const DEFAULT_PROFILE_IDENTIFIERS = [
|
|
21
23
|
"linkedin/profile",
|
|
22
24
|
"linkedin/company",
|
|
@@ -26,22 +28,50 @@ const DEFAULT_PROFILE_IDENTIFIERS = [
|
|
|
26
28
|
];
|
|
27
29
|
const DELETE_CONFIRMATION_VALUES = new Set(["yes", "true", "y"]);
|
|
28
30
|
const MOTION_STATUS_VALUES = new Set(["draft", "preparing", "active", "paused", "archived"]);
|
|
31
|
+
const PROSPECT_STATUS_VALUES = new Set(["active", "nurture", "non_responsive", "not_fit", "rejected"]);
|
|
29
32
|
const PROSPECTS_ADD_NOTE_USAGE = "Usage: audienti prospects add-note <prsp_id> (--message <text> [--type <note|steer|voicemail_outreach|video_outreach>] [--engagement-type <key>] | --payload <file.json>) [--json] [--account <acct_id>]";
|
|
30
33
|
const PROSPECTS_ADD_STEER_USAGE = "Usage: audienti prospects add-steer <prsp_id> (--message <text> [--engagement-type <key>] | --payload <file.json>) [--json] [--account <acct_id>]";
|
|
31
34
|
const PROSPECTS_ADD_PROFILE_USAGE = "Usage: audienti prospects add-profile <prsp_id> --url <profile_url|email|phone> [--json] [--account <acct_id>]";
|
|
32
35
|
const PROSPECTS_REPORT_BAD_PROFILE_USAGE = "Usage: audienti prospects report-bad-profile <prsp_id> <prof_id|citation_id> [--json] [--account <acct_id>]";
|
|
33
36
|
const PROSPECTS_ASSIGN_USAGE = "Usage: audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json] [--account <acct_id>]";
|
|
37
|
+
const PROSPECTS_SET_STATUS_USAGE = "Usage: audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|rejected> [--json] [--account <acct_id>]";
|
|
38
|
+
const PROSPECTS_REJECT_USAGE = "Usage: audienti prospects reject <prsp_id> [--json] [--account <acct_id>]";
|
|
39
|
+
const PROSPECTS_NURTURE_USAGE = "Usage: audienti prospects nurture <prsp_id> [--reason <nurture|non_responsive|not_fit>] [--json] [--account <acct_id>]";
|
|
40
|
+
const PROSPECTS_RESTORE_USAGE = "Usage: audienti prospects restore <prsp_id> [--json] [--account <acct_id>]";
|
|
41
|
+
const PROSPECTS_LOCK_USAGE = "Usage: audienti prospects lock <prsp_id> [--note <text>] [--kind <protected_relationship|company_policy>] [--json] [--account <acct_id>]";
|
|
42
|
+
const PROSPECTS_UNLOCK_USAGE = "Usage: audienti prospects unlock <prsp_id> [--json] [--account <acct_id>]";
|
|
43
|
+
const PROSPECTS_CHECK_USAGE = "Usage: audienti prospects check [--json|--csv] [filters] [--account <acct_id>]";
|
|
34
44
|
const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
|
|
45
|
+
const DNC_ADD_USAGE = "Usage: audienti dnc add <email|citation_id|profile_url> [--json] [--account <acct_id>]";
|
|
46
|
+
const DNC_IMPORT_USAGE = "Usage: audienti dnc import --file <txt|csv> [--json] [--account <acct_id>]";
|
|
47
|
+
const DNC_REMOVE_USAGE = "Usage: audienti dnc remove <dnc_entry_id> [--json] [--account <acct_id>]";
|
|
48
|
+
const COMPANY_RULES_CREATE_USAGE = "Usage: audienti company-rules create (--linkedin-url <url> | --domain <domain>) --disposition <monitor|nurture|not_fit|reject> [--name <text>] [--user <account_user_id|email|me>] [--note <text>] [--json] [--account <acct_id>]";
|
|
49
|
+
const COMPANY_RULES_UPDATE_USAGE = "Usage: audienti company-rules update <rule_id> [--linkedin-url <url>] [--domain <domain>] [--disposition <monitor|nurture|not_fit|reject>] [--name <text>] [--user <account_user_id|email|me|none>] [--note <text>] [--json] [--account <acct_id>]";
|
|
50
|
+
const COMPANY_RULES_REMOVE_USAGE = "Usage: audienti company-rules remove <rule_id> [--json] [--account <acct_id>]";
|
|
51
|
+
const COMPANY_RULES_APPLY_USAGE = "Usage: audienti company-rules apply (<rule_id>|--all) [--json] [--account <acct_id>]";
|
|
35
52
|
const USERS_ACTIVITY_USAGE = "Usage: audienti users activity [account_user_id|me] [--mode <actor|account_usage>] [--window <24h|7d|30d>] [--platform <linkedin|email|gmail>] [--query <text>] [--limit <n>] [--page <n>] [--json] [--account <acct_id>]";
|
|
53
|
+
const OFFERS_SHOW_USAGE = "Usage: audienti offers show <offr_id> [--json] [--account <acct_id>]";
|
|
54
|
+
const OFFERS_UPDATE_USAGE = "Usage: audienti offers update <offr_id> [--name <text>] [--description <text>] [--url <url>] [--json] [--account <acct_id>]";
|
|
55
|
+
const OFFERS_DELETE_USAGE = "Usage: audienti offers delete <offr_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]";
|
|
36
56
|
const WRITER_TEST_RUN_USAGE = "Usage: audienti writer test-run <prsp_id> [--json] [--mode <report|plan|step>] [--branch <both|no-accept|accepted>] [--step <step_key|row_number>] [--no-cache] [--clear-cache] [--account <acct_id>]";
|
|
37
57
|
const MOTIONS_ANALYTICS_USAGE = "Usage: audienti motions analytics <motn_id> [--window 30d] [--json] [--account <acct_id>]";
|
|
38
|
-
const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> --status <draft|preparing|active|paused|archived> [--json] [--account <acct_id>]";
|
|
58
|
+
const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> [--status <draft|preparing|active|paused|archived>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]";
|
|
59
|
+
const MOTIONS_ADD_TAG_USAGE = "Usage: audienti motions add-tag <motn_id> <tag> [--json] [--account <acct_id>]";
|
|
60
|
+
const MOTIONS_REMOVE_TAG_USAGE = "Usage: audienti motions remove-tag <motn_id> <tag> [--json] [--account <acct_id>]";
|
|
39
61
|
const MOTIONS_DELETE_USAGE = "Usage: audienti motions delete <motn_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]";
|
|
40
62
|
const MOTIONS_CLONE_USAGE = "Usage: audienti motions clone <motn_id> --name <text> [--json] [--account <acct_id>]";
|
|
41
63
|
const MOTIONS_MOVE_PROSPECTS_USAGE = "Usage: audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json] [--account <acct_id>]";
|
|
64
|
+
const MOTIONS_RUN_DISCOVERY_USAGE = "Usage: audienti motions run-discovery <motn_id> [--target-count <n>] [--json] [--account <acct_id>]";
|
|
65
|
+
const ICPS_SHOW_USAGE = "Usage: audienti icps show <icp_id> [--json] [--account <acct_id>]";
|
|
66
|
+
const ICPS_UPDATE_USAGE = "Usage: audienti icps update <icp_id> [--name <text>] [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]";
|
|
67
|
+
const ICPS_ADD_TAG_USAGE = "Usage: audienti icps add-tag <icp_id> <tag> [--json] [--account <acct_id>]";
|
|
68
|
+
const ICPS_REMOVE_TAG_USAGE = "Usage: audienti icps remove-tag <icp_id> <tag> [--json] [--account <acct_id>]";
|
|
69
|
+
const LISTS_ADD_TAG_USAGE = "Usage: audienti lists add-tag <list_id> <tag> [--json] [--account <acct_id>]";
|
|
70
|
+
const LISTS_REMOVE_TAG_USAGE = "Usage: audienti lists remove-tag <list_id> <tag> [--json] [--account <acct_id>]";
|
|
42
71
|
const ANALYTICS_PROSPECTS_USAGE = "Usage: audienti analytics prospects [--window 24h] [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--motion <motn_id>] [--provenance <source>] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
|
|
43
72
|
const ANALYTICS_PROSPECTS_COHORT_ANALYSIS_USAGE = "Usage: audienti analytics prospects cohort-analysis [--weeks <n>] [--window 24h] [--motion <motn_id>] [--provenance <source>] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
|
|
44
73
|
const ANALYTICS_USERS_USAGE = "Usage: audienti analytics users [--user <account_user_id|email|name|me>] [--window 30d | --start YYYY-MM-DD --end YYYY-MM-DD] [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--motion <motn_id>] [--provenance <source>] [--platform <linkedin|email|gmail>] [--json] [--account <acct_id>]";
|
|
74
|
+
const ANALYTICS_DASHBOARD_USAGE = "Usage: audienti analytics dashboard [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--play-tag <tag>] [--motion <motn_id>] [--offer <offr_id>] [--icp <icp_id>] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
|
|
45
75
|
const COHORT_STAGE_ORDER = [
|
|
46
76
|
"identified",
|
|
47
77
|
"pre_connect",
|
|
@@ -120,20 +150,41 @@ async function dispatch(argv, context) {
|
|
|
120
150
|
if (normalizedResource === "auth" && action === "status") return authStatus(rest, context, { accountOverride });
|
|
121
151
|
if (normalizedResource === "auth" && action === "logout") return authLogout(rest, context);
|
|
122
152
|
if (normalizedResource === "config" && action === "list") return configList(rest, context);
|
|
153
|
+
if (normalizedResource === "update" && action === "check") return updateCheck(rest, context);
|
|
123
154
|
if (normalizedResource === "accounts" && action === "list") return accountsList(rest, context, { accountOverride });
|
|
124
155
|
if (normalizedResource === "accounts" && action === "select") return accountsSelect(rest, context);
|
|
125
156
|
if (normalizedResource === "users" && action === "list") return usersList(rest, context, { accountOverride });
|
|
126
157
|
if (normalizedResource === "users" && action === "select") return usersSelect(rest, context, { accountOverride });
|
|
127
158
|
if (normalizedResource === "users" && action === "activity") return usersActivity(rest, context, { accountOverride });
|
|
128
159
|
if (normalizedResource === "offers" && action === "list") return offersList(rest, context, { accountOverride });
|
|
160
|
+
if (normalizedResource === "offers" && action === "show") return offersShow(rest, context, { accountOverride });
|
|
129
161
|
if (normalizedResource === "offers" && action === "create") return offersCreate(rest, context, { accountOverride });
|
|
162
|
+
if (normalizedResource === "offers" && action === "update") return offersUpdate(rest, context, { accountOverride });
|
|
163
|
+
if (normalizedResource === "offers" && action === "delete") return offersDelete(rest, context, { accountOverride });
|
|
130
164
|
if (normalizedResource === "icps" && action === "list") return icpsList(rest, context, { accountOverride });
|
|
165
|
+
if (normalizedResource === "icps" && action === "show") return icpsShow(rest, context, { accountOverride });
|
|
131
166
|
if (normalizedResource === "icps" && action === "create") return icpsCreate(rest, context, { accountOverride });
|
|
167
|
+
if (normalizedResource === "icps" && action === "update") return icpsUpdate(rest, context, { accountOverride });
|
|
168
|
+
if (normalizedResource === "icps" && action === "add-tag") return icpsTagMutation("add", rest, context, { accountOverride });
|
|
169
|
+
if (normalizedResource === "icps" && action === "remove-tag") return icpsTagMutation("remove", rest, context, { accountOverride });
|
|
132
170
|
if (normalizedResource === "companies" && action === "search") return companiesSearch(rest, context, { accountOverride });
|
|
171
|
+
if (normalizedResource === "dnc" && action === "list") return dncList(rest, context, { accountOverride });
|
|
172
|
+
if (normalizedResource === "dnc" && action === "add") return dncAdd(rest, context, { accountOverride });
|
|
173
|
+
if (normalizedResource === "dnc" && action === "import") return dncImport(rest, context, { accountOverride });
|
|
174
|
+
if (normalizedResource === "dnc" && ["remove", "delete"].includes(action)) return dncRemove(rest, context, { accountOverride });
|
|
175
|
+
if (normalizedResource === "company-rules" && action === "list") return companyRulesList(rest, context, { accountOverride });
|
|
176
|
+
if (normalizedResource === "company-rules" && action === "create") return companyRulesCreate(rest, context, { accountOverride });
|
|
177
|
+
if (normalizedResource === "company-rules" && action === "update") return companyRulesUpdate(rest, context, { accountOverride });
|
|
178
|
+
if (normalizedResource === "company-rules" && ["remove", "delete"].includes(action)) return companyRulesRemove(rest, context, { accountOverride });
|
|
179
|
+
if (normalizedResource === "company-rules" && action === "apply") return companyRulesApply(rest, context, { accountOverride });
|
|
180
|
+
if (normalizedResource === "tags" && action === "list") return tagsList(rest, context, { accountOverride });
|
|
181
|
+
if (normalizedResource === "tags" && action === "show") return tagsShow(rest, context, { accountOverride });
|
|
133
182
|
if (normalizedResource === "lists" && action === "list") return listsList(rest, context, { accountOverride });
|
|
134
183
|
if (normalizedResource === "lists" && action === "create") return listsCreate(rest, context, { accountOverride });
|
|
135
184
|
if (normalizedResource === "lists" && action === "show") return listsShow(rest, context, { accountOverride });
|
|
136
185
|
if (normalizedResource === "lists" && action === "update") return listsUpdate(rest, context, { accountOverride });
|
|
186
|
+
if (normalizedResource === "lists" && action === "add-tag") return listsTagMutation("add", rest, context, { accountOverride });
|
|
187
|
+
if (normalizedResource === "lists" && action === "remove-tag") return listsTagMutation("remove", rest, context, { accountOverride });
|
|
137
188
|
if (normalizedResource === "lists" && action === "delete") return listsDelete(rest, context, { accountOverride });
|
|
138
189
|
if (normalizedResource === "lists" && action === "prospects") return listProspects(rest, context, { accountOverride });
|
|
139
190
|
if (normalizedResource === "lists" && action === "add-prospects") return listsAddProspects(rest, context, { accountOverride });
|
|
@@ -146,13 +197,23 @@ async function dispatch(argv, context) {
|
|
|
146
197
|
if (normalizedResource === "motions" && action === "add-prospects") return motionsAddProspects(rest, context, { accountOverride });
|
|
147
198
|
if (normalizedResource === "motions" && action === "create") return motionsCreate(rest, context, { accountOverride });
|
|
148
199
|
if (normalizedResource === "motions" && action === "update") return motionsUpdate(rest, context, { accountOverride });
|
|
200
|
+
if (normalizedResource === "motions" && action === "add-tag") return motionsTagMutation("add", rest, context, { accountOverride });
|
|
201
|
+
if (normalizedResource === "motions" && action === "remove-tag") return motionsTagMutation("remove", rest, context, { accountOverride });
|
|
149
202
|
if (normalizedResource === "motions" && ["activate", "pause", "archive"].includes(action)) return motionsStatusShortcut(action, rest, context, { accountOverride });
|
|
150
203
|
if (normalizedResource === "motions" && action === "delete") return motionsDelete(rest, context, { accountOverride });
|
|
151
204
|
if (normalizedResource === "motions" && action === "clone") return motionsClone(rest, context, { accountOverride });
|
|
152
205
|
if (normalizedResource === "motions" && action === "move-prospects") return motionsMoveProspects(rest, context, { accountOverride });
|
|
206
|
+
if (normalizedResource === "motions" && action === "run-discovery") return motionsRunDiscovery(rest, context, { accountOverride });
|
|
153
207
|
if (normalizedResource === "prospects" && action === "list") return prospectsList(rest, context, { accountOverride });
|
|
208
|
+
if (normalizedResource === "prospects" && action === "check") return prospectsCheck(rest, context, { accountOverride });
|
|
154
209
|
if (normalizedResource === "prospects" && action === "show") return prospectsShow(rest, context, { accountOverride });
|
|
155
210
|
if (normalizedResource === "prospects" && action === "assign") return prospectsAssign(rest, context, { accountOverride });
|
|
211
|
+
if (normalizedResource === "prospects" && action === "set-status") return prospectsSetStatus(rest, context, { accountOverride });
|
|
212
|
+
if (normalizedResource === "prospects" && action === "reject") return prospectsDisposition("reject", rest, context, { accountOverride });
|
|
213
|
+
if (normalizedResource === "prospects" && action === "nurture") return prospectsDisposition("nurture", rest, context, { accountOverride });
|
|
214
|
+
if (normalizedResource === "prospects" && action === "restore") return prospectsDisposition("restore", rest, context, { accountOverride });
|
|
215
|
+
if (normalizedResource === "prospects" && action === "lock") return prospectsLock(rest, context, { accountOverride });
|
|
216
|
+
if (normalizedResource === "prospects" && action === "unlock") return prospectsUnlock(rest, context, { accountOverride });
|
|
156
217
|
if (normalizedResource === "prospects" && action === "timeline") return prospectsTimeline(rest, context, { accountOverride });
|
|
157
218
|
if (normalizedResource === "prospects" && action === "message-types") return prospectsMessageTypes(rest, context, { accountOverride });
|
|
158
219
|
if (normalizedResource === "prospects" && action === "write") return prospectsWrite(rest, context, { accountOverride });
|
|
@@ -174,6 +235,7 @@ async function dispatch(argv, context) {
|
|
|
174
235
|
if (normalizedResource === "analytics" && ["users", "user"].includes(action)) return analyticsUsers(rest, context, { accountOverride });
|
|
175
236
|
if (normalizedResource === "analytics" && ["visibility", "visops"].includes(action)) return analyticsVisibility(rest, context, { accountOverride });
|
|
176
237
|
if (normalizedResource === "analytics" && action === "content") return analyticsContent(rest, context, { accountOverride });
|
|
238
|
+
if (normalizedResource === "analytics" && ["dashboard", "campaign", "campaigns"].includes(action)) return analyticsDashboard(rest, context, { accountOverride });
|
|
177
239
|
|
|
178
240
|
throw new CommandError(usage(), { exitCode: resource ? 1 : 0 });
|
|
179
241
|
}
|
|
@@ -224,6 +286,7 @@ function normalizeTopicParts(parts) {
|
|
|
224
286
|
function normalizeResource(resource) {
|
|
225
287
|
if (resource === "principals") return "users";
|
|
226
288
|
if (resource === "writers") return "writer";
|
|
289
|
+
if (resource === "company_rules" || resource === "company-rules") return "company-rules";
|
|
227
290
|
return resource === "plays" ? "motions" : resource;
|
|
228
291
|
}
|
|
229
292
|
|
|
@@ -332,6 +395,51 @@ async function configList(args, context) {
|
|
|
332
395
|
}
|
|
333
396
|
}
|
|
334
397
|
|
|
398
|
+
async function updateCheck(args, context) {
|
|
399
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
400
|
+
...jsonOptions(),
|
|
401
|
+
registry: { type: "string" }
|
|
402
|
+
});
|
|
403
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti update check [--json] [--registry <url>]");
|
|
404
|
+
|
|
405
|
+
const localPackage = await readLocalPackageMetadata();
|
|
406
|
+
let payload;
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
const latestVersion = await fetchLatestPackageVersion({
|
|
410
|
+
fetchImpl: context.fetchImpl,
|
|
411
|
+
registry: values.registry
|
|
412
|
+
});
|
|
413
|
+
const updateAvailable = compareVersions(localPackage.version, latestVersion) < 0;
|
|
414
|
+
payload = updateCheckPayload({
|
|
415
|
+
currentVersion: localPackage.version,
|
|
416
|
+
latestVersion,
|
|
417
|
+
status: updateAvailable ? "update_available" : "current",
|
|
418
|
+
updateAvailable,
|
|
419
|
+
registry: values.registry || DEFAULT_NPM_REGISTRY,
|
|
420
|
+
now: context.now()
|
|
421
|
+
});
|
|
422
|
+
} catch (error) {
|
|
423
|
+
payload = updateCheckPayload({
|
|
424
|
+
currentVersion: localPackage.version,
|
|
425
|
+
latestVersion: null,
|
|
426
|
+
status: "unknown",
|
|
427
|
+
updateAvailable: null,
|
|
428
|
+
registry: values.registry || DEFAULT_NPM_REGISTRY,
|
|
429
|
+
error: error.message,
|
|
430
|
+
now: context.now()
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (values.json) {
|
|
435
|
+
writeJson(context.stdout, payload);
|
|
436
|
+
return payload.status === "unknown" ? 1 : 0;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
renderUpdateCheck(payload, context);
|
|
440
|
+
return payload.status === "unknown" ? 1 : 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
335
443
|
async function accountsList(args, context, { accountOverride } = {}) {
|
|
336
444
|
const { values, positionals } = parseCommandArgs(args, {
|
|
337
445
|
json: { type: "boolean" }
|
|
@@ -452,11 +560,14 @@ function accountUserLabel(accountUser) {
|
|
|
452
560
|
}
|
|
453
561
|
|
|
454
562
|
async function listsList(args, context, { accountOverride } = {}) {
|
|
455
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
456
|
-
|
|
563
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
564
|
+
...jsonOptions(),
|
|
565
|
+
tag: { type: "string" }
|
|
566
|
+
});
|
|
567
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti lists list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
457
568
|
|
|
458
569
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
459
|
-
const lists = await client.lists(accountId);
|
|
570
|
+
const lists = filterRecordsByTag(await client.lists(accountId), values.tag, "tags");
|
|
460
571
|
if (values.json) return writeJson(context.stdout, lists);
|
|
461
572
|
|
|
462
573
|
renderLists(lists, context);
|
|
@@ -533,6 +644,17 @@ async function offersList(args, context, { accountOverride } = {}) {
|
|
|
533
644
|
renderOffers(offers, context);
|
|
534
645
|
}
|
|
535
646
|
|
|
647
|
+
async function offersShow(args, context, { accountOverride } = {}) {
|
|
648
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
649
|
+
if (positionals.length !== 1) throw new CommandError(OFFERS_SHOW_USAGE);
|
|
650
|
+
|
|
651
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
652
|
+
const offer = await client.offer(accountId, positionals[0]);
|
|
653
|
+
if (values.json) return writeJson(context.stdout, offer);
|
|
654
|
+
|
|
655
|
+
renderOffer(offer, context);
|
|
656
|
+
}
|
|
657
|
+
|
|
536
658
|
async function offersCreate(args, context, { accountOverride } = {}) {
|
|
537
659
|
const { values, positionals } = parseCommandArgs(args, {
|
|
538
660
|
...jsonOptions(),
|
|
@@ -559,27 +681,85 @@ async function offersCreate(args, context, { accountOverride } = {}) {
|
|
|
559
681
|
if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
|
|
560
682
|
}
|
|
561
683
|
|
|
684
|
+
async function offersUpdate(args, context, { accountOverride } = {}) {
|
|
685
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
686
|
+
...jsonOptions(),
|
|
687
|
+
name: { type: "string" },
|
|
688
|
+
description: { type: "string" },
|
|
689
|
+
url: { type: "string" }
|
|
690
|
+
});
|
|
691
|
+
const hasUpdateField = values.name || values.description !== undefined || values.url !== undefined;
|
|
692
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
693
|
+
throw new CommandError(OFFERS_UPDATE_USAGE);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
697
|
+
const offer = await client.updateOffer(accountId, positionals[0], {
|
|
698
|
+
offer: compactObject({
|
|
699
|
+
name: values.name,
|
|
700
|
+
description: values.description,
|
|
701
|
+
url: values.url
|
|
702
|
+
})
|
|
703
|
+
});
|
|
704
|
+
if (values.json) return writeJson(context.stdout, offer);
|
|
705
|
+
|
|
706
|
+
writeLine(context.stdout, `Updated offer ${display(offer?.name)} (${display(offer?.prefix_id)}).`);
|
|
707
|
+
renderOffer(offer, context);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
async function offersDelete(args, context, { accountOverride } = {}) {
|
|
711
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
712
|
+
...jsonOptions(),
|
|
713
|
+
confirm: { type: "string" }
|
|
714
|
+
});
|
|
715
|
+
const normalizedConfirm = String(values.confirm || "").trim().toLowerCase();
|
|
716
|
+
if (positionals.length !== 1 || !DELETE_CONFIRMATION_VALUES.has(normalizedConfirm)) {
|
|
717
|
+
throw new CommandError(OFFERS_DELETE_USAGE);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
721
|
+
const payload = await client.deleteOffer(accountId, positionals[0]);
|
|
722
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
723
|
+
|
|
724
|
+
writeLine(context.stdout, `Deleted offer ${display(payload?.name)} (${display(payload?.prefix_id)}).`);
|
|
725
|
+
}
|
|
726
|
+
|
|
562
727
|
async function icpsList(args, context, { accountOverride } = {}) {
|
|
563
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
564
|
-
|
|
728
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
729
|
+
...jsonOptions(),
|
|
730
|
+
tag: { type: "string" }
|
|
731
|
+
});
|
|
732
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti icps list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
565
733
|
|
|
566
734
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
567
|
-
const icps = await client.icps(accountId);
|
|
735
|
+
const icps = filterRecordsByTag(await client.icps(accountId), values.tag, "tags");
|
|
568
736
|
if (values.json) return writeJson(context.stdout, icps);
|
|
569
737
|
|
|
570
738
|
renderIcps(icps, context);
|
|
571
739
|
}
|
|
572
740
|
|
|
741
|
+
async function icpsShow(args, context, { accountOverride } = {}) {
|
|
742
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
743
|
+
if (positionals.length !== 1) throw new CommandError(ICPS_SHOW_USAGE);
|
|
744
|
+
|
|
745
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
746
|
+
const icp = await client.icp(accountId, positionals[0]);
|
|
747
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
748
|
+
|
|
749
|
+
renderIcp(icp, context);
|
|
750
|
+
}
|
|
751
|
+
|
|
573
752
|
async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
574
753
|
const { values, positionals } = parseCommandArgs(args, {
|
|
575
754
|
...jsonOptions(),
|
|
576
755
|
payload: { type: "string" },
|
|
577
756
|
name: { type: "string" },
|
|
578
757
|
notes: { type: "string" },
|
|
758
|
+
tags: { type: "string" },
|
|
579
759
|
"discovery-keyword": { type: "string" }
|
|
580
760
|
});
|
|
581
761
|
if (positionals.length > 0) {
|
|
582
|
-
throw new CommandError("Usage: audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] | --payload <file.json>) [--json] [--account <acct_id>]");
|
|
762
|
+
throw new CommandError("Usage: audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] | --payload <file.json>) [--json] [--account <acct_id>]");
|
|
583
763
|
}
|
|
584
764
|
|
|
585
765
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -589,9 +769,58 @@ async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
|
589
769
|
|
|
590
770
|
writeLine(context.stdout, `Created ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
591
771
|
if (icp?.notes) writeLine(context.stdout, `Notes: ${icp.notes}`);
|
|
772
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
592
773
|
if (icp?.discovery_keyword) writeLine(context.stdout, `Discovery keyword: ${icp.discovery_keyword}`);
|
|
593
774
|
}
|
|
594
775
|
|
|
776
|
+
async function icpsUpdate(args, context, { accountOverride } = {}) {
|
|
777
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
778
|
+
...jsonOptions(),
|
|
779
|
+
name: { type: "string" },
|
|
780
|
+
notes: { type: "string" },
|
|
781
|
+
tags: { type: "string" },
|
|
782
|
+
"discovery-keyword": { type: "string" }
|
|
783
|
+
});
|
|
784
|
+
const hasUpdateField = values.name || values.notes !== undefined || values.tags !== undefined || values["discovery-keyword"] !== undefined;
|
|
785
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
786
|
+
throw new CommandError(ICPS_UPDATE_USAGE);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
790
|
+
const icp = await client.updateIcp(accountId, positionals[0], {
|
|
791
|
+
icp: compactObject({
|
|
792
|
+
name: values.name,
|
|
793
|
+
notes: values.notes,
|
|
794
|
+
discovery_keyword: values["discovery-keyword"],
|
|
795
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined
|
|
796
|
+
})
|
|
797
|
+
});
|
|
798
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
799
|
+
|
|
800
|
+
writeLine(context.stdout, `Updated ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
801
|
+
renderIcp(icp, context);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
async function icpsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
805
|
+
const usageText = action === "add" ? ICPS_ADD_TAG_USAGE : ICPS_REMOVE_TAG_USAGE;
|
|
806
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
807
|
+
if (positionals.length !== 2) {
|
|
808
|
+
throw new CommandError(usageText);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const [icpId, tag] = positionals;
|
|
812
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
813
|
+
const icp = action === "add" ?
|
|
814
|
+
await client.addIcpTag(accountId, icpId, { tag }) :
|
|
815
|
+
await client.removeIcpTag(accountId, icpId, { tag });
|
|
816
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
817
|
+
|
|
818
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
819
|
+
const preposition = action === "add" ? "to" : "from";
|
|
820
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
821
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
822
|
+
}
|
|
823
|
+
|
|
595
824
|
async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
596
825
|
const { values, positionals } = parseCommandArgs(args, {
|
|
597
826
|
...jsonOptions(),
|
|
@@ -608,16 +837,175 @@ async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
|
608
837
|
renderCompanies(payload, context);
|
|
609
838
|
}
|
|
610
839
|
|
|
840
|
+
async function dncList(args, context, { accountOverride } = {}) {
|
|
841
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
842
|
+
...jsonOptions(),
|
|
843
|
+
limit: { type: "string" },
|
|
844
|
+
offset: { type: "string" }
|
|
845
|
+
});
|
|
846
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti dnc list [--limit <n>] [--offset <n>] [--json] [--account <acct_id>]");
|
|
847
|
+
|
|
848
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
849
|
+
const payload = await client.dncEntries(accountId, compactObject({ limit: values.limit, offset: values.offset }));
|
|
850
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
851
|
+
|
|
852
|
+
renderDncEntries(payload, context);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async function dncAdd(args, context, { accountOverride } = {}) {
|
|
856
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
857
|
+
if (positionals.length !== 1) throw new CommandError(DNC_ADD_USAGE);
|
|
858
|
+
|
|
859
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
860
|
+
const payload = await client.createDncEntry(accountId, { value: positionals[0] });
|
|
861
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
862
|
+
|
|
863
|
+
writeLine(context.stdout, `DNC entry ${display(payload?.status, "created")}: ${display(payload?.dnc_entry?.canonical_value || payload?.dnc_entry?.citation_id)} (${display(payload?.dnc_entry?.prefix_id || payload?.dnc_entry?.id)}).`);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
async function dncImport(args, context, { accountOverride } = {}) {
|
|
867
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
868
|
+
...jsonOptions(),
|
|
869
|
+
file: { type: "string" }
|
|
870
|
+
});
|
|
871
|
+
if (positionals.length > 0 || !values.file) throw new CommandError(DNC_IMPORT_USAGE);
|
|
872
|
+
|
|
873
|
+
const body = await readFile(values.file, "utf8");
|
|
874
|
+
const importValues = parseDncImportValues(body);
|
|
875
|
+
if (importValues.length === 0) throw new CommandError("DNC import file did not contain any values.");
|
|
876
|
+
|
|
877
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
878
|
+
const payload = await client.importDncEntries(accountId, { values: importValues, filename: basename(values.file) });
|
|
879
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
880
|
+
|
|
881
|
+
writeLine(context.stdout, `Imported DNC entries. Accepted ${display(payload?.accepted_count, 0)}, skipped ${display(payload?.skipped_count, 0)}, invalid ${display(payload?.invalid_count, 0)}, matched ${display(payload?.matched_prospect_count, 0)}.`);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
async function dncRemove(args, context, { accountOverride } = {}) {
|
|
885
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
886
|
+
if (positionals.length !== 1) throw new CommandError(DNC_REMOVE_USAGE);
|
|
887
|
+
|
|
888
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
889
|
+
const payload = await client.deleteDncEntry(accountId, positionals[0]);
|
|
890
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
891
|
+
|
|
892
|
+
writeLine(context.stdout, `Removed DNC entry ${display(payload?.prefix_id || payload?.id || positionals[0])}.`);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
async function companyRulesList(args, context, { accountOverride } = {}) {
|
|
896
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
897
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti company-rules list [--json] [--account <acct_id>]");
|
|
898
|
+
|
|
899
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
900
|
+
const payload = await client.companyRules(accountId);
|
|
901
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
902
|
+
|
|
903
|
+
renderCompanyRules(payload, context);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
async function companyRulesCreate(args, context, { accountOverride } = {}) {
|
|
907
|
+
const { values, positionals } = parseCommandArgs(args, companyRuleOptions());
|
|
908
|
+
if (positionals.length > 0 || (!values["linkedin-url"] && !values.domain) || !values.disposition) {
|
|
909
|
+
throw new CommandError(COMPANY_RULES_CREATE_USAGE);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
913
|
+
const payload = await client.createCompanyRule(accountId, { company_rule: companyRulePayload(values) });
|
|
914
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
915
|
+
|
|
916
|
+
const rule = payload?.company_rule;
|
|
917
|
+
writeLine(context.stdout, `Created company rule ${display(rule?.name || rule?.domain || rule?.linkedin_company_identifier)} (${display(rule?.prefix_id || rule?.id)}).`);
|
|
918
|
+
writeLine(context.stdout, `Disposition: ${display(rule?.disposition)} | Scope: ${companyRuleScopeLabel(rule)}`);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
async function companyRulesUpdate(args, context, { accountOverride } = {}) {
|
|
922
|
+
const { values, positionals } = parseCommandArgs(args, companyRuleOptions());
|
|
923
|
+
const hasUpdate = values.disposition || values.name !== undefined || values["linkedin-url"] !== undefined || values.domain !== undefined || values.user !== undefined || values.note !== undefined;
|
|
924
|
+
if (positionals.length !== 1 || !hasUpdate) throw new CommandError(COMPANY_RULES_UPDATE_USAGE);
|
|
925
|
+
|
|
926
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
927
|
+
const payload = await client.updateCompanyRule(accountId, positionals[0], { company_rule: companyRulePayload(values) });
|
|
928
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
929
|
+
|
|
930
|
+
const rule = payload?.company_rule;
|
|
931
|
+
writeLine(context.stdout, `Updated company rule ${display(rule?.name || rule?.domain || rule?.linkedin_company_identifier)} (${display(rule?.prefix_id || rule?.id)}).`);
|
|
932
|
+
writeLine(context.stdout, `Disposition: ${display(rule?.disposition)} | Scope: ${companyRuleScopeLabel(rule)}`);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
async function companyRulesRemove(args, context, { accountOverride } = {}) {
|
|
936
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
937
|
+
if (positionals.length !== 1) throw new CommandError(COMPANY_RULES_REMOVE_USAGE);
|
|
938
|
+
|
|
939
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
940
|
+
const payload = await client.deleteCompanyRule(accountId, positionals[0]);
|
|
941
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
942
|
+
|
|
943
|
+
writeLine(context.stdout, `Removed company rule ${display(payload?.company_rule?.prefix_id || payload?.company_rule?.id || positionals[0])}.`);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
async function companyRulesApply(args, context, { accountOverride } = {}) {
|
|
947
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
948
|
+
...jsonOptions(),
|
|
949
|
+
all: { type: "boolean" }
|
|
950
|
+
});
|
|
951
|
+
if ((values.all && positionals.length > 0) || (!values.all && positionals.length !== 1)) {
|
|
952
|
+
throw new CommandError(COMPANY_RULES_APPLY_USAGE);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
956
|
+
const payload = values.all ?
|
|
957
|
+
await client.applyAllCompanyRules(accountId) :
|
|
958
|
+
await client.applyCompanyRule(accountId, positionals[0]);
|
|
959
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
960
|
+
|
|
961
|
+
if (values.all) {
|
|
962
|
+
writeLine(context.stdout, `Applied company rules. Matched ${display(payload?.matched_count, 0)}, changed ${display(payload?.applied_count, 0)}.`);
|
|
963
|
+
} else {
|
|
964
|
+
writeLine(context.stdout, `Applied company rule. Matched ${display(payload?.matched_count, 0)}, changed ${display(payload?.applied_count, 0)}.`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
async function tagsList(args, context, { accountOverride } = {}) {
|
|
969
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
970
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti tags list [--json] [--account <acct_id>]");
|
|
971
|
+
|
|
972
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
973
|
+
const payload = await client.tags(accountId);
|
|
974
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
975
|
+
|
|
976
|
+
renderTags(payload, context);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
async function tagsShow(args, context, { accountOverride } = {}) {
|
|
980
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
981
|
+
if (positionals.length !== 1) throw new CommandError("Usage: audienti tags show <tag> [--json] [--account <acct_id>]");
|
|
982
|
+
|
|
983
|
+
const tag = tagList(positionals[0])[0];
|
|
984
|
+
if (!tag) throw new CommandError("Usage: audienti tags show <tag> [--json] [--account <acct_id>]");
|
|
985
|
+
|
|
986
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
987
|
+
const payload = {
|
|
988
|
+
tag,
|
|
989
|
+
icps: filterRecordsByTag(await client.icps(accountId), tag, "tags"),
|
|
990
|
+
lists: filterRecordsByTag(await client.lists(accountId), tag, "tags"),
|
|
991
|
+
motions: filterRecordsByTag(await client.motions(accountId), tag, "play_tags")
|
|
992
|
+
};
|
|
993
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
994
|
+
|
|
995
|
+
renderTagDetails(payload, context);
|
|
996
|
+
}
|
|
997
|
+
|
|
611
998
|
async function listsCreate(args, context, { accountOverride } = {}) {
|
|
612
999
|
const { values, positionals } = parseCommandArgs(args, {
|
|
613
1000
|
...jsonOptions(),
|
|
614
1001
|
name: { type: "string" },
|
|
615
1002
|
description: { type: "string" },
|
|
1003
|
+
tags: { type: "string" },
|
|
616
1004
|
"campaign-hook": { type: "string" },
|
|
617
1005
|
"audience-note": { type: "string" }
|
|
618
1006
|
});
|
|
619
1007
|
if (positionals.length > 0 || !values.name) {
|
|
620
|
-
throw new CommandError("Usage: audienti lists create --name <text> [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]");
|
|
1008
|
+
throw new CommandError("Usage: audienti lists create --name <text> [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]");
|
|
621
1009
|
}
|
|
622
1010
|
|
|
623
1011
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -629,6 +1017,7 @@ async function listsCreate(args, context, { accountOverride } = {}) {
|
|
|
629
1017
|
list: compactObject({
|
|
630
1018
|
name: values.name,
|
|
631
1019
|
description: values.description,
|
|
1020
|
+
tags: tagList(values.tags),
|
|
632
1021
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
633
1022
|
})
|
|
634
1023
|
});
|
|
@@ -654,13 +1043,14 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
654
1043
|
...jsonOptions(),
|
|
655
1044
|
name: { type: "string" },
|
|
656
1045
|
description: { type: "string" },
|
|
1046
|
+
tags: { type: "string" },
|
|
657
1047
|
"campaign-hook": { type: "string" },
|
|
658
1048
|
"audience-note": { type: "string" }
|
|
659
1049
|
});
|
|
660
1050
|
const hasCampaignUpdate = values["campaign-hook"] || values["audience-note"];
|
|
661
|
-
const hasUpdateField = values.name || values.description || hasCampaignUpdate;
|
|
1051
|
+
const hasUpdateField = values.name || values.description || values.tags !== undefined || hasCampaignUpdate;
|
|
662
1052
|
if (positionals.length !== 1 || !hasUpdateField) {
|
|
663
|
-
throw new CommandError("Usage: audienti lists update <list_id> [--name <text>] [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]");
|
|
1053
|
+
throw new CommandError("Usage: audienti lists update <list_id> [--name <text>] [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]");
|
|
664
1054
|
}
|
|
665
1055
|
|
|
666
1056
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -672,6 +1062,7 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
672
1062
|
list: compactObject({
|
|
673
1063
|
name: values.name,
|
|
674
1064
|
description: values.description,
|
|
1065
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
675
1066
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
676
1067
|
})
|
|
677
1068
|
});
|
|
@@ -681,6 +1072,26 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
681
1072
|
if (payload?.description) writeLine(context.stdout, `Description: ${payload.description}`);
|
|
682
1073
|
}
|
|
683
1074
|
|
|
1075
|
+
async function listsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
1076
|
+
const usageText = action === "add" ? LISTS_ADD_TAG_USAGE : LISTS_REMOVE_TAG_USAGE;
|
|
1077
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
1078
|
+
if (positionals.length !== 2) {
|
|
1079
|
+
throw new CommandError(usageText);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
const [listId, tag] = positionals;
|
|
1083
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1084
|
+
const payload = action === "add" ?
|
|
1085
|
+
await client.addListTag(accountId, listId, { tag }) :
|
|
1086
|
+
await client.removeListTag(accountId, listId, { tag });
|
|
1087
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1088
|
+
|
|
1089
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
1090
|
+
const preposition = action === "add" ? "to" : "from";
|
|
1091
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} list ${display(payload?.name)} (${display(payload?.prefix_id)}).`);
|
|
1092
|
+
if (Array.isArray(payload?.tags)) writeLine(context.stdout, `Tags: ${display(payload.tags.join(", "), "-")}`);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
684
1095
|
async function listsDelete(args, context, { accountOverride } = {}) {
|
|
685
1096
|
const { values, positionals } = parseCommandArgs(args, {
|
|
686
1097
|
...jsonOptions(),
|
|
@@ -780,11 +1191,14 @@ async function listsRemoveProspects(args, context, { accountOverride } = {}) {
|
|
|
780
1191
|
}
|
|
781
1192
|
|
|
782
1193
|
async function motionsList(args, context, { accountOverride } = {}) {
|
|
783
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
784
|
-
|
|
1194
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1195
|
+
...jsonOptions(),
|
|
1196
|
+
tag: { type: "string" }
|
|
1197
|
+
});
|
|
1198
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti motions list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
785
1199
|
|
|
786
1200
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
787
|
-
const motions = await client.motions(accountId);
|
|
1201
|
+
const motions = filterRecordsByTag(await client.motions(accountId), values.tag, "play_tags");
|
|
788
1202
|
if (values.json) return writeJson(context.stdout, motions);
|
|
789
1203
|
|
|
790
1204
|
renderMotions(motions, context);
|
|
@@ -812,6 +1226,22 @@ async function motionsStatus(args, context, { accountOverride } = {}) {
|
|
|
812
1226
|
renderMotionStatus(status, context);
|
|
813
1227
|
}
|
|
814
1228
|
|
|
1229
|
+
async function motionsRunDiscovery(args, context, { accountOverride } = {}) {
|
|
1230
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1231
|
+
...jsonOptions(),
|
|
1232
|
+
"target-count": { type: "string" }
|
|
1233
|
+
});
|
|
1234
|
+
if (positionals.length !== 1) throw new CommandError(MOTIONS_RUN_DISCOVERY_USAGE);
|
|
1235
|
+
|
|
1236
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1237
|
+
const payload = await client.runMotionDiscovery(accountId, positionals[0], compactObject({
|
|
1238
|
+
target_count: normalizeOptionalPositiveInteger(values["target-count"], "--target-count")
|
|
1239
|
+
}));
|
|
1240
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1241
|
+
|
|
1242
|
+
renderMotionDiscoveryRun(payload, context);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
815
1245
|
async function motionsAnalytics(args, context, { accountOverride } = {}) {
|
|
816
1246
|
const { values, positionals } = parseCommandArgs(args, {
|
|
817
1247
|
...jsonOptions(),
|
|
@@ -929,13 +1359,26 @@ async function motionsDelete(args, context, { accountOverride } = {}) {
|
|
|
929
1359
|
async function motionsUpdate(args, context, { accountOverride } = {}) {
|
|
930
1360
|
const { values, positionals } = parseCommandArgs(args, {
|
|
931
1361
|
...jsonOptions(),
|
|
932
|
-
status: { type: "string" }
|
|
1362
|
+
status: { type: "string" },
|
|
1363
|
+
tags: { type: "string" }
|
|
933
1364
|
});
|
|
934
|
-
|
|
1365
|
+
const hasUpdateField = values.status || values.tags !== undefined;
|
|
1366
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
935
1367
|
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
936
1368
|
}
|
|
937
1369
|
|
|
938
|
-
|
|
1370
|
+
const normalizedStatus = normalizeMotionStatus(values.status);
|
|
1371
|
+
const motionAttributes = compactObject({
|
|
1372
|
+
status: normalizedStatus,
|
|
1373
|
+
play_tags: values.tags !== undefined ? tagList(values.tags) : undefined
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1377
|
+
const motion = await client.updateMotion(accountId, positionals[0], { motion: motionAttributes });
|
|
1378
|
+
if (values.json) return writeJson(context.stdout, motion);
|
|
1379
|
+
|
|
1380
|
+
writeLine(context.stdout, `Updated motion ${display(motion?.name)} (${display(motion?.prefix_id)}).`);
|
|
1381
|
+
renderMotion(motion, context);
|
|
939
1382
|
}
|
|
940
1383
|
|
|
941
1384
|
async function motionsStatusShortcut(action, args, context, { accountOverride } = {}) {
|
|
@@ -954,10 +1397,7 @@ async function motionsStatusShortcut(action, args, context, { accountOverride }
|
|
|
954
1397
|
}
|
|
955
1398
|
|
|
956
1399
|
async function updateMotionStatus(motionId, status, context, { accountOverride, json } = {}) {
|
|
957
|
-
const normalizedStatus =
|
|
958
|
-
if (!MOTION_STATUS_VALUES.has(normalizedStatus)) {
|
|
959
|
-
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
960
|
-
}
|
|
1400
|
+
const normalizedStatus = normalizeMotionStatus(status);
|
|
961
1401
|
|
|
962
1402
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
963
1403
|
const motion = await client.updateMotion(accountId, motionId, {
|
|
@@ -971,6 +1411,37 @@ async function updateMotionStatus(motionId, status, context, { accountOverride,
|
|
|
971
1411
|
renderMotion(motion, context);
|
|
972
1412
|
}
|
|
973
1413
|
|
|
1414
|
+
function normalizeMotionStatus(status) {
|
|
1415
|
+
if (status === undefined) return undefined;
|
|
1416
|
+
|
|
1417
|
+
const normalizedStatus = String(status || "").trim().toLowerCase();
|
|
1418
|
+
if (!MOTION_STATUS_VALUES.has(normalizedStatus)) {
|
|
1419
|
+
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
return normalizedStatus;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
async function motionsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
1426
|
+
const usageText = action === "add" ? MOTIONS_ADD_TAG_USAGE : MOTIONS_REMOVE_TAG_USAGE;
|
|
1427
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
1428
|
+
if (positionals.length !== 2) {
|
|
1429
|
+
throw new CommandError(usageText);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
const [motionId, tag] = positionals;
|
|
1433
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1434
|
+
const motion = action === "add" ?
|
|
1435
|
+
await client.addMotionTag(accountId, motionId, { tag }) :
|
|
1436
|
+
await client.removeMotionTag(accountId, motionId, { tag });
|
|
1437
|
+
if (values.json) return writeJson(context.stdout, motion);
|
|
1438
|
+
|
|
1439
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
1440
|
+
const preposition = action === "add" ? "to" : "from";
|
|
1441
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} motion ${display(motion?.name)} (${display(motion?.prefix_id)}).`);
|
|
1442
|
+
if (Array.isArray(motion?.play_tags)) writeLine(context.stdout, `Tags: ${display(motion.play_tags.join(", "), "-")}`);
|
|
1443
|
+
}
|
|
1444
|
+
|
|
974
1445
|
async function motionsClone(args, context, { accountOverride } = {}) {
|
|
975
1446
|
const { values, positionals } = parseCommandArgs(args, {
|
|
976
1447
|
...jsonOptions(),
|
|
@@ -1018,33 +1489,75 @@ async function motionsMoveProspects(args, context, { accountOverride } = {}) {
|
|
|
1018
1489
|
}
|
|
1019
1490
|
|
|
1020
1491
|
async function prospectsList(args, context, { accountOverride } = {}) {
|
|
1021
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1492
|
+
const { values, positionals } = parseCommandArgs(args, prospectFilterOptions());
|
|
1493
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti prospects list [--json] [filters] [--account <acct_id>]");
|
|
1494
|
+
if (values.csv && values.json) throw new CommandError("Choose one output format: use either --csv or --json.");
|
|
1495
|
+
validateProspectFilterValues(values);
|
|
1496
|
+
|
|
1497
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1498
|
+
const query = prospectQueryFromValues(values, config, { accountOverride });
|
|
1499
|
+
const payload = values.all ?
|
|
1500
|
+
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
1501
|
+
await client.prospects(accountId, query);
|
|
1502
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1503
|
+
if (values.csv) return writeLine(context.stdout, prospectsToCsv(payload?.prospects || []));
|
|
1504
|
+
|
|
1505
|
+
renderProspects(payload, context, { wide: values.wide || values.all, profiles: values.profiles });
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
async function prospectsCheck(args, context, { accountOverride } = {}) {
|
|
1509
|
+
const { values, positionals } = parseCommandArgs(args, prospectFilterOptions());
|
|
1510
|
+
if (positionals.length > 0) throw new CommandError(PROSPECTS_CHECK_USAGE);
|
|
1511
|
+
if (values.csv && values.json) throw new CommandError("Choose one output format: use either --csv or --json.");
|
|
1512
|
+
if (values.company || values["company-profile"]) throw new CommandError("Company filters are not supported for `prospects check`; it already finds prospects missing a certified company.");
|
|
1513
|
+
validateProspectFilterValues(values);
|
|
1514
|
+
|
|
1515
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1516
|
+
const query = {
|
|
1517
|
+
...prospectQueryFromValues(values, config, { accountOverride }),
|
|
1518
|
+
data_quality: "missing_certified_company"
|
|
1519
|
+
};
|
|
1520
|
+
const rawPayload = values.all ?
|
|
1521
|
+
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
1522
|
+
await client.prospects(accountId, query);
|
|
1523
|
+
const payload = withProspectAppUrls(rawPayload, client.host);
|
|
1524
|
+
|
|
1525
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1526
|
+
if (values.csv) return writeLine(context.stdout, prospectCheckToCsv(payload?.prospects || []));
|
|
1527
|
+
|
|
1528
|
+
renderProspectCheck(payload, context);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
function prospectFilterOptions() {
|
|
1532
|
+
return {
|
|
1533
|
+
...jsonOptions(),
|
|
1534
|
+
all: { type: "boolean" },
|
|
1535
|
+
csv: { type: "boolean" },
|
|
1536
|
+
query: { type: "string" },
|
|
1537
|
+
company: { type: "string" },
|
|
1538
|
+
"company-profile": { type: "string" },
|
|
1539
|
+
motion: { type: "string" },
|
|
1540
|
+
play: { type: "string" },
|
|
1541
|
+
list: { type: "string" },
|
|
1542
|
+
stage: { type: "string" },
|
|
1543
|
+
"assigned-user": { type: "string" },
|
|
1544
|
+
limit: { type: "string" },
|
|
1545
|
+
offset: { type: "string" },
|
|
1035
1546
|
page: { type: "string" },
|
|
1036
1547
|
profiles: { type: "boolean" },
|
|
1037
1548
|
wide: { type: "boolean" }
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
function validateProspectFilterValues(values) {
|
|
1041
1553
|
if (values.page && values.offset) throw new CommandError("Choose one pagination mode: use either --page or --offset.");
|
|
1042
1554
|
if (values.all && (values.page || values.offset)) throw new CommandError("--all cannot be combined with --page or --offset.");
|
|
1043
1555
|
if (values.motion && values.play) throw new CommandError("Choose one motion filter: use either --motion or --play.");
|
|
1044
1556
|
if (values.company && values["company-profile"]) throw new CommandError("Choose one company filter: use either --company or --company-profile.");
|
|
1557
|
+
}
|
|
1045
1558
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1559
|
+
function prospectQueryFromValues(values, config, { accountOverride } = {}) {
|
|
1560
|
+
return compactObject({
|
|
1048
1561
|
query: values.query,
|
|
1049
1562
|
company: values.company,
|
|
1050
1563
|
company_profile_id: values["company-profile"],
|
|
@@ -1058,13 +1571,6 @@ async function prospectsList(args, context, { accountOverride } = {}) {
|
|
|
1058
1571
|
page: values.page,
|
|
1059
1572
|
include_profiles: values.profiles
|
|
1060
1573
|
});
|
|
1061
|
-
const payload = values.all ?
|
|
1062
|
-
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
1063
|
-
await client.prospects(accountId, query);
|
|
1064
|
-
if (values.json) return writeJson(context.stdout, payload);
|
|
1065
|
-
if (values.csv) return writeLine(context.stdout, prospectsToCsv(payload?.prospects || []));
|
|
1066
|
-
|
|
1067
|
-
renderProspects(payload, context, { wide: values.wide || values.all, profiles: values.profiles });
|
|
1068
1574
|
}
|
|
1069
1575
|
|
|
1070
1576
|
async function prospectsAssign(args, context, { accountOverride } = {}) {
|
|
@@ -1109,6 +1615,85 @@ async function prospectsShow(args, context, { accountOverride } = {}) {
|
|
|
1109
1615
|
renderProspect(prospect, context);
|
|
1110
1616
|
}
|
|
1111
1617
|
|
|
1618
|
+
async function prospectsDisposition(action, args, context, { accountOverride } = {}) {
|
|
1619
|
+
const usageText = {
|
|
1620
|
+
reject: PROSPECTS_REJECT_USAGE,
|
|
1621
|
+
nurture: PROSPECTS_NURTURE_USAGE,
|
|
1622
|
+
restore: PROSPECTS_RESTORE_USAGE
|
|
1623
|
+
}[action];
|
|
1624
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1625
|
+
...jsonOptions(),
|
|
1626
|
+
reason: { type: "string" }
|
|
1627
|
+
});
|
|
1628
|
+
if (positionals.length !== 1 || (action !== "nurture" && values.reason)) {
|
|
1629
|
+
throw new CommandError(usageText);
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1633
|
+
const prospectId = positionals[0];
|
|
1634
|
+
const payload = action === "reject" ?
|
|
1635
|
+
await client.rejectProspect(accountId, prospectId) :
|
|
1636
|
+
action === "restore" ?
|
|
1637
|
+
await client.restoreProspect(accountId, prospectId) :
|
|
1638
|
+
await client.nurtureProspect(accountId, prospectId, compactObject({ inactive_reason: values.reason }));
|
|
1639
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1640
|
+
|
|
1641
|
+
renderProspectDisposition(payload, context, { action });
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
async function prospectsSetStatus(args, context, { accountOverride } = {}) {
|
|
1645
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1646
|
+
...jsonOptions(),
|
|
1647
|
+
status: { type: "string" }
|
|
1648
|
+
});
|
|
1649
|
+
const status = String(values.status || "").trim();
|
|
1650
|
+
if (positionals.length !== 1 || !PROSPECT_STATUS_VALUES.has(status)) {
|
|
1651
|
+
throw new CommandError(PROSPECTS_SET_STATUS_USAGE);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1655
|
+
const payload = await mutateProspectStatus(client, accountId, positionals[0], status);
|
|
1656
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1657
|
+
|
|
1658
|
+
renderProspectDisposition(payload, context, { action: "set-status" });
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
async function prospectsLock(args, context, { accountOverride } = {}) {
|
|
1662
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1663
|
+
...jsonOptions(),
|
|
1664
|
+
kind: { type: "string" },
|
|
1665
|
+
note: { type: "string" }
|
|
1666
|
+
});
|
|
1667
|
+
if (positionals.length !== 1) throw new CommandError(PROSPECTS_LOCK_USAGE);
|
|
1668
|
+
|
|
1669
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1670
|
+
const payload = await client.lockProspect(accountId, positionals[0], compactObject({
|
|
1671
|
+
lock_kind: values.kind,
|
|
1672
|
+
lock_note: values.note
|
|
1673
|
+
}));
|
|
1674
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1675
|
+
|
|
1676
|
+
renderProspectDisposition(payload, context, { action: "lock" });
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
async function prospectsUnlock(args, context, { accountOverride } = {}) {
|
|
1680
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
1681
|
+
if (positionals.length !== 1) throw new CommandError(PROSPECTS_UNLOCK_USAGE);
|
|
1682
|
+
|
|
1683
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1684
|
+
const payload = await client.unlockProspect(accountId, positionals[0]);
|
|
1685
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1686
|
+
|
|
1687
|
+
renderProspectDisposition(payload, context, { action: "unlock" });
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
async function mutateProspectStatus(client, accountId, prospectId, status) {
|
|
1691
|
+
if (status === "active") return client.restoreProspect(accountId, prospectId);
|
|
1692
|
+
if (status === "rejected") return client.rejectProspect(accountId, prospectId);
|
|
1693
|
+
|
|
1694
|
+
return client.nurtureProspect(accountId, prospectId, { inactive_reason: status });
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1112
1697
|
async function prospectsTimeline(args, context, { accountOverride } = {}) {
|
|
1113
1698
|
const { values, positionals } = parseCommandArgs(args, {
|
|
1114
1699
|
...jsonOptions(),
|
|
@@ -1784,6 +2369,18 @@ async function analyticsContent(args, context, { accountOverride } = {}) {
|
|
|
1784
2369
|
renderAnalyticsContent(payload, context);
|
|
1785
2370
|
}
|
|
1786
2371
|
|
|
2372
|
+
async function analyticsDashboard(args, context, { accountOverride } = {}) {
|
|
2373
|
+
const { values, positionals } = parseCommandArgs(args, analyticsDashboardOptions());
|
|
2374
|
+
if (positionals.length > 0) throw new CommandError(ANALYTICS_DASHBOARD_USAGE);
|
|
2375
|
+
validateDatePair(values["cohort-start"], values["cohort-end"], "--cohort-start", "--cohort-end");
|
|
2376
|
+
|
|
2377
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2378
|
+
const payload = await client.analyticsDashboard(accountId, analyticsDashboardQuery(values, config, { accountOverride }));
|
|
2379
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
2380
|
+
|
|
2381
|
+
renderAnalyticsDashboard(payload, context);
|
|
2382
|
+
}
|
|
2383
|
+
|
|
1787
2384
|
function parseCommandArgs(args, options) {
|
|
1788
2385
|
try {
|
|
1789
2386
|
return parseArgs({
|
|
@@ -1955,6 +2552,20 @@ function analyticsUsersOptions() {
|
|
|
1955
2552
|
};
|
|
1956
2553
|
}
|
|
1957
2554
|
|
|
2555
|
+
function analyticsDashboardOptions() {
|
|
2556
|
+
return {
|
|
2557
|
+
...jsonOptions(),
|
|
2558
|
+
"cohort-start": { type: "string" },
|
|
2559
|
+
"cohort-end": { type: "string" },
|
|
2560
|
+
"play-tag": { type: "string" },
|
|
2561
|
+
tag: { type: "string" },
|
|
2562
|
+
motion: { type: "string" },
|
|
2563
|
+
offer: { type: "string" },
|
|
2564
|
+
icp: { type: "string" },
|
|
2565
|
+
user: { type: "string" }
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2568
|
+
|
|
1958
2569
|
function analyticsQuery(values, config = {}, { accountOverride } = {}) {
|
|
1959
2570
|
return compactObject({
|
|
1960
2571
|
window: values.window,
|
|
@@ -1981,6 +2592,18 @@ function analyticsUsersQuery(values, config = {}, { accountOverride } = {}) {
|
|
|
1981
2592
|
});
|
|
1982
2593
|
}
|
|
1983
2594
|
|
|
2595
|
+
function analyticsDashboardQuery(values, config = {}, { accountOverride } = {}) {
|
|
2596
|
+
return compactObject({
|
|
2597
|
+
cohort_start_date: values["cohort-start"],
|
|
2598
|
+
cohort_end_date: values["cohort-end"],
|
|
2599
|
+
play_tag: values["play-tag"] || values.tag,
|
|
2600
|
+
motion_id: values.motion,
|
|
2601
|
+
offer_id: values.offer,
|
|
2602
|
+
icp_id: values.icp,
|
|
2603
|
+
account_user_id: resolveAccountUserId(values.user, config, { accountOverride })
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
|
|
1984
2607
|
function validateDatePair(start, end, startFlag, endFlag) {
|
|
1985
2608
|
if ((start && !end) || (!start && end)) {
|
|
1986
2609
|
throw new CommandError(`${startFlag} and ${endFlag} must be provided together.`);
|
|
@@ -2086,26 +2709,162 @@ function provenancePayload(provenance) {
|
|
|
2086
2709
|
|
|
2087
2710
|
function compactObject(object) {
|
|
2088
2711
|
return Object.fromEntries(
|
|
2089
|
-
Object.entries(object).filter(([, value]) =>
|
|
2712
|
+
Object.entries(object).filter(([, value]) => {
|
|
2713
|
+
if (value === undefined || value === null) return false;
|
|
2714
|
+
if (Array.isArray(value)) return true;
|
|
2715
|
+
|
|
2716
|
+
return String(value).trim() !== "";
|
|
2717
|
+
})
|
|
2090
2718
|
);
|
|
2091
2719
|
}
|
|
2092
2720
|
|
|
2721
|
+
async function readLocalPackageMetadata() {
|
|
2722
|
+
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
2723
|
+
return {
|
|
2724
|
+
name: packageJson.name || PACKAGE_NAME,
|
|
2725
|
+
version: packageJson.version
|
|
2726
|
+
};
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
async function fetchLatestPackageVersion({ fetchImpl, registry }) {
|
|
2730
|
+
if (!fetchImpl) throw new Error("This Node runtime does not provide fetch.");
|
|
2731
|
+
|
|
2732
|
+
const response = await fetchImpl(registryLatestPackageUrl(registry), {
|
|
2733
|
+
headers: {
|
|
2734
|
+
accept: "application/vnd.npm.install-v1+json, application/json"
|
|
2735
|
+
}
|
|
2736
|
+
});
|
|
2737
|
+
const bodyText = await response.text();
|
|
2738
|
+
const body = bodyText ? JSON.parse(bodyText) : {};
|
|
2739
|
+
|
|
2740
|
+
if (!response.ok) {
|
|
2741
|
+
throw new Error(body?.error || body?.message || `Registry returned HTTP ${response.status}.`);
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2744
|
+
const version = body?.version?.toString().trim();
|
|
2745
|
+
if (!version) throw new Error("Registry response did not include a version.");
|
|
2746
|
+
|
|
2747
|
+
return version;
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
function registryLatestPackageUrl(registry) {
|
|
2751
|
+
const base = new URL(registry || DEFAULT_NPM_REGISTRY);
|
|
2752
|
+
if (!base.pathname.endsWith("/")) base.pathname = `${base.pathname}/`;
|
|
2753
|
+
|
|
2754
|
+
return new URL(`${encodeURIComponent(PACKAGE_NAME)}/latest`, base).toString();
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
function updateCheckPayload({ currentVersion, latestVersion, status, updateAvailable, registry, error, now }) {
|
|
2758
|
+
return {
|
|
2759
|
+
kind: "update_check",
|
|
2760
|
+
package_name: PACKAGE_NAME,
|
|
2761
|
+
current_version: currentVersion,
|
|
2762
|
+
latest_version: latestVersion,
|
|
2763
|
+
update_available: updateAvailable,
|
|
2764
|
+
status,
|
|
2765
|
+
install_command: `npm install --global ${PACKAGE_NAME}`,
|
|
2766
|
+
registry,
|
|
2767
|
+
checked_at: now.toISOString(),
|
|
2768
|
+
error: error || null
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
function compareVersions(currentVersion, latestVersion) {
|
|
2773
|
+
const current = parseVersion(currentVersion);
|
|
2774
|
+
const latest = parseVersion(latestVersion);
|
|
2775
|
+
|
|
2776
|
+
for (let index = 0; index < 3; index += 1) {
|
|
2777
|
+
if (current.parts[index] !== latest.parts[index]) return current.parts[index] - latest.parts[index];
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
if (current.prerelease === latest.prerelease) return 0;
|
|
2781
|
+
if (!current.prerelease) return 1;
|
|
2782
|
+
if (!latest.prerelease) return -1;
|
|
2783
|
+
|
|
2784
|
+
return current.prerelease.localeCompare(latest.prerelease);
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
function parseVersion(version) {
|
|
2788
|
+
const [core, prerelease = ""] = String(version || "").split("-", 2);
|
|
2789
|
+
const parts = core.split(".").map((part) => Number.parseInt(part, 10));
|
|
2790
|
+
|
|
2791
|
+
return {
|
|
2792
|
+
parts: [parts[0] || 0, parts[1] || 0, parts[2] || 0],
|
|
2793
|
+
prerelease
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
function tagList(value) {
|
|
2798
|
+
if (value === undefined) return undefined;
|
|
2799
|
+
|
|
2800
|
+
return String(value)
|
|
2801
|
+
.split(/[\r\n,;]+/)
|
|
2802
|
+
.map((tag) => tag.trim().toLowerCase())
|
|
2803
|
+
.filter(Boolean)
|
|
2804
|
+
.filter((tag, index, tags) => tags.indexOf(tag) === index);
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
function companyRuleOptions() {
|
|
2808
|
+
return {
|
|
2809
|
+
...jsonOptions(),
|
|
2810
|
+
name: { type: "string" },
|
|
2811
|
+
"linkedin-url": { type: "string" },
|
|
2812
|
+
domain: { type: "string" },
|
|
2813
|
+
disposition: { type: "string" },
|
|
2814
|
+
user: { type: "string" },
|
|
2815
|
+
note: { type: "string" }
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
function companyRulePayload(values) {
|
|
2820
|
+
const userValue = values.user === undefined ? undefined : String(values.user || "").trim();
|
|
2821
|
+
const userCleared = userValue && ["none", "account", "all"].includes(userValue.toLowerCase());
|
|
2822
|
+
|
|
2823
|
+
return compactObject({
|
|
2824
|
+
name: values.name,
|
|
2825
|
+
linkedin_company_url: values["linkedin-url"],
|
|
2826
|
+
domain: values.domain,
|
|
2827
|
+
disposition: values.disposition,
|
|
2828
|
+
note: values.note,
|
|
2829
|
+
scope_kind: userValue === undefined ? undefined : (userCleared ? "account" : "account_user"),
|
|
2830
|
+
account_user_id: userValue === undefined ? undefined : (userCleared ? "" : userValue)
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
function parseDncImportValues(body) {
|
|
2835
|
+
return String(body || "")
|
|
2836
|
+
.split(/\r?\n/)
|
|
2837
|
+
.map((line) => line.trim())
|
|
2838
|
+
.filter(Boolean)
|
|
2839
|
+
.map((line) => line.split(",")[0])
|
|
2840
|
+
.map((value) => value.trim().replace(/^"|"$/g, ""))
|
|
2841
|
+
.filter(Boolean);
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
function filterRecordsByTag(records, value, field) {
|
|
2845
|
+
const tag = tagList(value)?.[0];
|
|
2846
|
+
if (!tag) return records;
|
|
2847
|
+
|
|
2848
|
+
return Array.isArray(records) ? records.filter((record) => (tagList(record?.[field]) || []).includes(tag)) : [];
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2093
2851
|
async function icpCreatePayload(values) {
|
|
2094
2852
|
if (values.payload) {
|
|
2095
|
-
if (values.name || values.notes || values["discovery-keyword"]) {
|
|
2096
|
-
throw new CommandError("Choose one ICP input mode: either --payload <file.json> or the simple --name/--notes/--discovery-keyword flags.");
|
|
2853
|
+
if (values.name || values.notes || values.tags !== undefined || values["discovery-keyword"]) {
|
|
2854
|
+
throw new CommandError("Choose one ICP input mode: either --payload <file.json> or the simple --name/--notes/--discovery-keyword/tags flags.");
|
|
2097
2855
|
}
|
|
2098
2856
|
|
|
2099
2857
|
return readJsonPayload(values.payload);
|
|
2100
2858
|
}
|
|
2101
2859
|
|
|
2102
2860
|
if (!values.name) {
|
|
2103
|
-
throw new CommandError("Usage: audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] | --payload <file.json>) [--json] [--account <acct_id>]");
|
|
2861
|
+
throw new CommandError("Usage: audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] | --payload <file.json>) [--json] [--account <acct_id>]");
|
|
2104
2862
|
}
|
|
2105
2863
|
|
|
2106
2864
|
return compactObject({
|
|
2107
2865
|
name: values.name,
|
|
2108
2866
|
notes: values.notes,
|
|
2867
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
2109
2868
|
discovery_keyword: values["discovery-keyword"]
|
|
2110
2869
|
});
|
|
2111
2870
|
}
|
|
@@ -2246,6 +3005,17 @@ function normalizePositiveInteger(value) {
|
|
|
2246
3005
|
return parsed;
|
|
2247
3006
|
}
|
|
2248
3007
|
|
|
3008
|
+
function normalizeOptionalPositiveInteger(value, flagName) {
|
|
3009
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
3010
|
+
|
|
3011
|
+
const parsed = normalizePositiveInteger(value);
|
|
3012
|
+
if (parsed === null || String(parsed) !== String(value).trim()) {
|
|
3013
|
+
throw new CommandError(`${flagName} must be a positive integer.`);
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
return parsed;
|
|
3017
|
+
}
|
|
3018
|
+
|
|
2249
3019
|
function normalizeLookupType(value) {
|
|
2250
3020
|
const normalized = String(value || "").trim().toLowerCase();
|
|
2251
3021
|
if (normalized === "email" || normalized === "phone") return normalized;
|
|
@@ -2394,6 +3164,22 @@ function writeJson(stream, value) {
|
|
|
2394
3164
|
writeLine(stream, JSON.stringify(value, null, 2));
|
|
2395
3165
|
}
|
|
2396
3166
|
|
|
3167
|
+
function renderUpdateCheck(payload, context) {
|
|
3168
|
+
writeLine(context.stdout, `Package: ${payload.package_name}`);
|
|
3169
|
+
writeLine(context.stdout, `Current version: ${display(payload.current_version, "-")}`);
|
|
3170
|
+
writeLine(context.stdout, `Latest version: ${display(payload.latest_version, "unknown")}`);
|
|
3171
|
+
|
|
3172
|
+
if (payload.status === "update_available") {
|
|
3173
|
+
writeLine(context.stdout, "Status: update available");
|
|
3174
|
+
writeLine(context.stdout, `Update: ${payload.install_command}`);
|
|
3175
|
+
} else if (payload.status === "current") {
|
|
3176
|
+
writeLine(context.stdout, "Status: current");
|
|
3177
|
+
} else {
|
|
3178
|
+
writeLine(context.stdout, "Status: unknown");
|
|
3179
|
+
if (payload.error) writeLine(context.stdout, `Error: ${payload.error}`);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
|
|
2397
3183
|
async function sleep(milliseconds) {
|
|
2398
3184
|
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
2399
3185
|
}
|
|
@@ -2410,9 +3196,48 @@ function renderLists(lists, context) {
|
|
|
2410
3196
|
function renderList(list, context) {
|
|
2411
3197
|
writeLine(context.stdout, `List: ${display(list?.name)} (${display(list?.prefix_id)})`);
|
|
2412
3198
|
writeLine(context.stdout, `Prospects: ${display(list?.prospect_count, 0)}`);
|
|
3199
|
+
if (Array.isArray(list?.tags)) writeLine(context.stdout, `Tags: ${display(list.tags.join(", "), "-")}`);
|
|
2413
3200
|
if (list?.description) writeLine(context.stdout, `Description: ${list.description}`);
|
|
2414
3201
|
}
|
|
2415
3202
|
|
|
3203
|
+
function renderTags(tags, context) {
|
|
3204
|
+
if (!Array.isArray(tags) || tags.length === 0) return writeLine(context.stdout, "No tags found.");
|
|
3205
|
+
|
|
3206
|
+
writeLine(context.stdout, "TAG\tICPS\tLISTS\tMOTIONS\tTOTAL");
|
|
3207
|
+
for (const tag of tags) {
|
|
3208
|
+
writeLine(
|
|
3209
|
+
context.stdout,
|
|
3210
|
+
[
|
|
3211
|
+
display(tag.name),
|
|
3212
|
+
display(tag.icp_count, 0),
|
|
3213
|
+
display(tag.list_count, 0),
|
|
3214
|
+
display(tag.motion_count, 0),
|
|
3215
|
+
display(tag.total_count, 0)
|
|
3216
|
+
].join("\t")
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
function renderTagDetails(payload, context) {
|
|
3222
|
+
const icps = Array.isArray(payload?.icps) ? payload.icps : [];
|
|
3223
|
+
const lists = Array.isArray(payload?.lists) ? payload.lists : [];
|
|
3224
|
+
const motions = Array.isArray(payload?.motions) ? payload.motions : [];
|
|
3225
|
+
|
|
3226
|
+
writeLine(context.stdout, `Tag: ${display(payload?.tag)}`);
|
|
3227
|
+
writeLine(context.stdout, `ICPs: ${icps.length}`);
|
|
3228
|
+
writeLine(context.stdout, `Lists: ${lists.length}`);
|
|
3229
|
+
writeLine(context.stdout, `Motions: ${motions.length}`);
|
|
3230
|
+
writeLine(context.stdout);
|
|
3231
|
+
writeLine(context.stdout, "ICPs");
|
|
3232
|
+
renderIcps(icps, context);
|
|
3233
|
+
writeLine(context.stdout);
|
|
3234
|
+
writeLine(context.stdout, "Lists");
|
|
3235
|
+
renderLists(lists, context);
|
|
3236
|
+
writeLine(context.stdout);
|
|
3237
|
+
writeLine(context.stdout, "Motions");
|
|
3238
|
+
renderMotions(motions, context);
|
|
3239
|
+
}
|
|
3240
|
+
|
|
2416
3241
|
function renderUsers(users, context) {
|
|
2417
3242
|
if (!Array.isArray(users) || users.length === 0) return writeLine(context.stdout, "No account users found.");
|
|
2418
3243
|
|
|
@@ -2482,16 +3307,23 @@ function renderOffers(offers, context) {
|
|
|
2482
3307
|
}
|
|
2483
3308
|
}
|
|
2484
3309
|
|
|
3310
|
+
function renderOffer(offer, context) {
|
|
3311
|
+
writeLine(context.stdout, `Offer: ${display(offer?.name)} (${display(offer?.prefix_id)})`);
|
|
3312
|
+
if (offer?.description) writeLine(context.stdout, `Description: ${offer.description}`);
|
|
3313
|
+
if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
|
|
3314
|
+
}
|
|
3315
|
+
|
|
2485
3316
|
function renderIcps(icps, context) {
|
|
2486
3317
|
if (!Array.isArray(icps) || icps.length === 0) return writeLine(context.stdout, "No ICPs found.");
|
|
2487
3318
|
|
|
2488
|
-
writeLine(context.stdout, "ICP ID\tNAME\tDISCOVERY KEYWORD\tAGENT");
|
|
3319
|
+
writeLine(context.stdout, "ICP ID\tNAME\tTAGS\tDISCOVERY KEYWORD\tAGENT");
|
|
2489
3320
|
for (const icp of icps) {
|
|
2490
3321
|
writeLine(
|
|
2491
3322
|
context.stdout,
|
|
2492
3323
|
[
|
|
2493
3324
|
display(icp.prefix_id),
|
|
2494
3325
|
display(icp.name),
|
|
3326
|
+
display(Array.isArray(icp.tags) && icp.tags.length > 0 ? icp.tags.join(",") : "-"),
|
|
2495
3327
|
display(icp.discovery_keyword),
|
|
2496
3328
|
display(icp.agent?.name)
|
|
2497
3329
|
].join("\t")
|
|
@@ -2499,6 +3331,14 @@ function renderIcps(icps, context) {
|
|
|
2499
3331
|
}
|
|
2500
3332
|
}
|
|
2501
3333
|
|
|
3334
|
+
function renderIcp(icp, context) {
|
|
3335
|
+
writeLine(context.stdout, `ICP: ${display(icp?.name)} (${display(icp?.prefix_id)})`);
|
|
3336
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
3337
|
+
if (icp?.notes) writeLine(context.stdout, `Notes: ${icp.notes}`);
|
|
3338
|
+
if (icp?.discovery_keyword) writeLine(context.stdout, `Discovery keyword: ${icp.discovery_keyword}`);
|
|
3339
|
+
if (icp?.agent?.name) writeLine(context.stdout, `Agent: ${icp.agent.name}`);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
2502
3342
|
function renderCompanies(payload, context) {
|
|
2503
3343
|
const companies = Array.isArray(payload?.companies) ? payload.companies : [];
|
|
2504
3344
|
if (companies.length === 0) return writeLine(context.stdout, "No companies found.");
|
|
@@ -2519,6 +3359,54 @@ function renderCompanies(payload, context) {
|
|
|
2519
3359
|
}
|
|
2520
3360
|
}
|
|
2521
3361
|
|
|
3362
|
+
function renderDncEntries(payload, context) {
|
|
3363
|
+
const entries = Array.isArray(payload?.dnc_entries) ? payload.dnc_entries : [];
|
|
3364
|
+
if (entries.length === 0) return writeLine(context.stdout, "No DNC entries found.");
|
|
3365
|
+
|
|
3366
|
+
writeLine(context.stdout, "DNC ID\tKIND\tVALUE\tIDENTIFIER\tSOURCE\tPROSPECT");
|
|
3367
|
+
for (const entry of entries) {
|
|
3368
|
+
writeLine(
|
|
3369
|
+
context.stdout,
|
|
3370
|
+
[
|
|
3371
|
+
display(entry.prefix_id || entry.id),
|
|
3372
|
+
display(entry.key_kind),
|
|
3373
|
+
display(entry.canonical_value || entry.citation_id),
|
|
3374
|
+
display(entry.identifier),
|
|
3375
|
+
display(entry.source_kind),
|
|
3376
|
+
display(entry.prospect_id)
|
|
3377
|
+
].join("\t")
|
|
3378
|
+
);
|
|
3379
|
+
}
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
function renderCompanyRules(payload, context) {
|
|
3383
|
+
const rules = Array.isArray(payload?.company_rules) ? payload.company_rules : [];
|
|
3384
|
+
if (rules.length === 0) return writeLine(context.stdout, "No company rules found.");
|
|
3385
|
+
|
|
3386
|
+
writeLine(context.stdout, "RULE ID\tCOMPANY\tDOMAIN\tDISPOSITION\tSCOPE\tACTIVE");
|
|
3387
|
+
for (const rule of rules) {
|
|
3388
|
+
writeLine(
|
|
3389
|
+
context.stdout,
|
|
3390
|
+
[
|
|
3391
|
+
display(rule.prefix_id || rule.id),
|
|
3392
|
+
display(rule.name || rule.linkedin_company_identifier || rule.linkedin_company_url),
|
|
3393
|
+
display(rule.domain),
|
|
3394
|
+
display(rule.disposition),
|
|
3395
|
+
companyRuleScopeLabel(rule),
|
|
3396
|
+
rule.active ? "yes" : "no"
|
|
3397
|
+
].join("\t")
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
function companyRuleScopeLabel(rule) {
|
|
3403
|
+
if (rule?.scope_kind === "account_user") {
|
|
3404
|
+
return `user:${display(rule.account_user_email || rule.account_user_id)}`;
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
return "account";
|
|
3408
|
+
}
|
|
3409
|
+
|
|
2522
3410
|
async function performBulkMutation(perform) {
|
|
2523
3411
|
try {
|
|
2524
3412
|
return { payload: await perform(), rejected: false };
|
|
@@ -2563,6 +3451,7 @@ function renderMotion(motion, context) {
|
|
|
2563
3451
|
if (motion?.offer?.name) writeLine(context.stdout, `Offer: ${motion.offer.name} (${display(motion.offer.prefix_id)})`);
|
|
2564
3452
|
if (motion?.icp?.name) writeLine(context.stdout, `ICP: ${motion.icp.name} (${display(motion.icp.prefix_id)})`);
|
|
2565
3453
|
if (motion?.list?.name) writeLine(context.stdout, `List: ${motion.list.name} (${display(motion.list.prefix_id)})`);
|
|
3454
|
+
if (Array.isArray(motion?.play_tags)) writeLine(context.stdout, `Tags: ${display(motion.play_tags.join(", "), "-")}`);
|
|
2566
3455
|
if (motion?.principal_account_user?.id) {
|
|
2567
3456
|
writeLine(
|
|
2568
3457
|
context.stdout,
|
|
@@ -2630,6 +3519,27 @@ function renderProspects(payload, context, { wide = false, profiles = false } =
|
|
|
2630
3519
|
}
|
|
2631
3520
|
}
|
|
2632
3521
|
|
|
3522
|
+
function renderProspectCheck(payload, context) {
|
|
3523
|
+
const prospects = Array.isArray(payload?.prospects) ? payload.prospects : [];
|
|
3524
|
+
const totalCount = display(payload?.meta?.total_count, prospects.length);
|
|
3525
|
+
if (prospects.length === 0) return writeLine(context.stdout, "No suspect prospects found.");
|
|
3526
|
+
|
|
3527
|
+
writeLine(context.stdout, `Suspect prospects: ${totalCount}`);
|
|
3528
|
+
writeLine(context.stdout, "PROSPECT ID\tSTAGE\tNAME\tREPORTED COMPANY\tCERTIFIED\tREASON\tURL");
|
|
3529
|
+
for (const prospect of prospects) {
|
|
3530
|
+
const certification = prospect.company_certification || {};
|
|
3531
|
+
writeLine(context.stdout, [
|
|
3532
|
+
display(prospect.prefix_id),
|
|
3533
|
+
display(prospect.account_prospect?.pipeline_stage),
|
|
3534
|
+
display(prospect.display_name || prospect.name),
|
|
3535
|
+
display(certification.reported_company || prospect.company),
|
|
3536
|
+
certification.status === "certified" ? "yes" : "no",
|
|
3537
|
+
display(certification.reason, "missing_employment_citation"),
|
|
3538
|
+
display(prospect.app_url)
|
|
3539
|
+
].join("\t"));
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
|
|
2633
3543
|
function renderProspect(prospect, context) {
|
|
2634
3544
|
writeLine(context.stdout, `Prospect: ${display(prospect?.display_name || prospect?.name)} (${display(prospect?.prefix_id)})`);
|
|
2635
3545
|
if (prospect?.company) writeLine(context.stdout, `Company: ${prospect.company}`);
|
|
@@ -2639,6 +3549,27 @@ function renderProspect(prospect, context) {
|
|
|
2639
3549
|
if (nextActionLabel(prospect?.queue)) writeLine(context.stdout, `Next action: ${nextActionLabel(prospect.queue)}`);
|
|
2640
3550
|
}
|
|
2641
3551
|
|
|
3552
|
+
function renderProspectDisposition(payload, context, { action }) {
|
|
3553
|
+
const prospect = payload?.prospect || {};
|
|
3554
|
+
const accountProspect = payload?.account_prospect || {};
|
|
3555
|
+
const actionLabel = {
|
|
3556
|
+
reject: "Rejected",
|
|
3557
|
+
nurture: "Moved to nurture",
|
|
3558
|
+
restore: "Restored",
|
|
3559
|
+
"set-status": "Set status for",
|
|
3560
|
+
lock: "Locked",
|
|
3561
|
+
unlock: "Unlocked"
|
|
3562
|
+
}[action] || display(payload?.status, "Updated");
|
|
3563
|
+
|
|
3564
|
+
writeLine(context.stdout, `${actionLabel} prospect ${display(prospect.display_name || prospect.name)} (${display(prospect.prefix_id)}).`);
|
|
3565
|
+
if (accountProspect.status) writeLine(context.stdout, `Status: ${accountProspect.status}`);
|
|
3566
|
+
if (accountProspect.inactive_reason) writeLine(context.stdout, `Inactive reason: ${accountProspect.inactive_reason}`);
|
|
3567
|
+
if (accountProspect.locked_at) writeLine(context.stdout, `Locked at: ${accountProspect.locked_at}`);
|
|
3568
|
+
if (accountProspect.lock_kind) writeLine(context.stdout, `Lock kind: ${accountProspect.lock_kind}`);
|
|
3569
|
+
if (accountProspect.lock_note) writeLine(context.stdout, `Lock note: ${accountProspect.lock_note}`);
|
|
3570
|
+
if (payload?.system_list?.name) writeLine(context.stdout, `List: ${payload.system_list.name} (${display(payload.system_list.prefix_id)})`);
|
|
3571
|
+
}
|
|
3572
|
+
|
|
2642
3573
|
function renderProspectTimeline(payload, context) {
|
|
2643
3574
|
const prospect = payload?.prospect || {};
|
|
2644
3575
|
const timeline = Array.isArray(payload?.timeline) ? payload.timeline : [];
|
|
@@ -3161,6 +4092,32 @@ function renderMotionAnalytics(payload, context) {
|
|
|
3161
4092
|
writeCountTable(context, "Prospect cohorts by produced day", payload?.prospects_by_day, ["DATE", "PRODUCED", "ACTIVE", "ACTIVE %", "INACTIVE", "STAGES"], dailyProspectRow);
|
|
3162
4093
|
}
|
|
3163
4094
|
|
|
4095
|
+
function renderMotionDiscoveryRun(payload, context) {
|
|
4096
|
+
const motion = payload?.motion || {};
|
|
4097
|
+
const label = entityLabel(motion) || payload?.motion_id;
|
|
4098
|
+
const prefix = payload?.enqueued ? "Discovery queued" : "Discovery not queued";
|
|
4099
|
+
writeLine(context.stdout, `${prefix} for ${display(label)}.`);
|
|
4100
|
+
writeLine(context.stdout, `Reason: ${display(payload?.reason)}`);
|
|
4101
|
+
writeLine(context.stdout, `Target count: ${display(payload?.target_count)}`);
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
function renderAnalyticsDashboard(payload, context) {
|
|
4105
|
+
writeLine(context.stdout, `Dashboard analytics (${display(payload?.cohort?.label, "selected cohort")})`);
|
|
4106
|
+
if (payload?.cohort) {
|
|
4107
|
+
writeLine(context.stdout, `Cohort: ${payload.cohort.start_date} to ${payload.cohort.end_date} (${display(payload.cohort.field, "account_prospects.created_at")})`);
|
|
4108
|
+
}
|
|
4109
|
+
if (payload?.activity) {
|
|
4110
|
+
writeLine(context.stdout, `Activity: ${payload.activity.start_date} to ${payload.activity.end_date} (${display(payload.activity.field, "events.created_at")})`);
|
|
4111
|
+
}
|
|
4112
|
+
writeDashboardFilters(payload, context);
|
|
4113
|
+
writeLine(context.stdout, `Prospects: ${display(payload?.cohort_size, 0)}`);
|
|
4114
|
+
writeLine(context.stdout, `Companies: ${display(payload?.cohort_company_target_count, 0)}`);
|
|
4115
|
+
writeLine(context.stdout, `People/company: ${display(payload?.cohort_people_per_company_average, "0.0")}`);
|
|
4116
|
+
writeLine(context.stdout, `Active: ${display(payload?.active_cohort_count, 0)} (${display(payload?.active_cohort_company_target_count, 0)} companies, ${percentageLabel(payload?.active_cohort_percentage)})`);
|
|
4117
|
+
writeLine(context.stdout, `Inactive: ${display(payload?.inactive_cohort_count, 0)}`);
|
|
4118
|
+
writeCountTable(context, "Current pipeline stages", payload?.pipeline_stage_counts, ["STAGE", "COUNT"], countRow);
|
|
4119
|
+
}
|
|
4120
|
+
|
|
3164
4121
|
function renderAnalyticsProspectCohortAnalysis(payload, context) {
|
|
3165
4122
|
const cohorts = Array.isArray(payload?.cohorts) ? payload.cohorts : [];
|
|
3166
4123
|
writeLine(context.stdout, `Prospect cohort analysis (${display(payload?.weeks, cohorts.length)} weeks)`);
|
|
@@ -3235,7 +4192,20 @@ function writeAnalyticsScope(payload, context) {
|
|
|
3235
4192
|
}
|
|
3236
4193
|
}
|
|
3237
4194
|
|
|
3238
|
-
function
|
|
4195
|
+
function writeDashboardFilters(payload, context) {
|
|
4196
|
+
const filters = payload?.filters || {};
|
|
4197
|
+
if (filters.motion) writeLine(context.stdout, `Motion: ${entityLabel(filters.motion)}`);
|
|
4198
|
+
if (filters.play_tag) writeLine(context.stdout, `Tag: ${filters.play_tag}`);
|
|
4199
|
+
if (filters.offer) writeLine(context.stdout, `Offer: ${entityLabel(filters.offer)}`);
|
|
4200
|
+
if (filters.icp) writeLine(context.stdout, `ICP: ${entityLabel(filters.icp)}`);
|
|
4201
|
+
if (filters.account_user) {
|
|
4202
|
+
writeLine(context.stdout, `User: ${entityLabel(filters.account_user)}`);
|
|
4203
|
+
} else {
|
|
4204
|
+
writeLine(context.stdout, "User: all account users");
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
function writeAnalyticsPlatform(payload, context) {
|
|
3239
4209
|
if (!payload?.platform) return;
|
|
3240
4210
|
|
|
3241
4211
|
const label = display(payload.platform.label, payload.platform.key);
|
|
@@ -3674,6 +4644,77 @@ function prospectsToCsv(prospects) {
|
|
|
3674
4644
|
].join("\n");
|
|
3675
4645
|
}
|
|
3676
4646
|
|
|
4647
|
+
function prospectCheckToCsv(prospects) {
|
|
4648
|
+
const headers = [
|
|
4649
|
+
"prefix_id",
|
|
4650
|
+
"display_name",
|
|
4651
|
+
"name",
|
|
4652
|
+
"title",
|
|
4653
|
+
"reported_company",
|
|
4654
|
+
"company_certification_status",
|
|
4655
|
+
"company_certification_reason",
|
|
4656
|
+
"email",
|
|
4657
|
+
"linkedin_url",
|
|
4658
|
+
"app_url",
|
|
4659
|
+
"account_prospect_status",
|
|
4660
|
+
"pipeline_stage",
|
|
4661
|
+
"assigned_to_account_user_id",
|
|
4662
|
+
"motion_prefix_id",
|
|
4663
|
+
"motion_name",
|
|
4664
|
+
"updated_at"
|
|
4665
|
+
];
|
|
4666
|
+
|
|
4667
|
+
const rows = prospects.map((prospect) => {
|
|
4668
|
+
const certification = prospect.company_certification || {};
|
|
4669
|
+
return {
|
|
4670
|
+
prefix_id: prospect.prefix_id,
|
|
4671
|
+
display_name: prospect.display_name,
|
|
4672
|
+
name: prospect.name,
|
|
4673
|
+
title: prospect.title,
|
|
4674
|
+
reported_company: certification.reported_company || prospect.company,
|
|
4675
|
+
company_certification_status: certification.status,
|
|
4676
|
+
company_certification_reason: certification.reason,
|
|
4677
|
+
email: prospect.email,
|
|
4678
|
+
linkedin_url: prospect.linkedin_url,
|
|
4679
|
+
app_url: prospect.app_url,
|
|
4680
|
+
account_prospect_status: prospect.account_prospect?.status,
|
|
4681
|
+
pipeline_stage: prospect.account_prospect?.pipeline_stage,
|
|
4682
|
+
assigned_to_account_user_id: prospect.account_prospect?.assigned_to_account_user_id,
|
|
4683
|
+
motion_prefix_id: prospect.account_prospect?.motion?.prefix_id,
|
|
4684
|
+
motion_name: prospect.account_prospect?.motion?.name,
|
|
4685
|
+
updated_at: prospect.updated_at
|
|
4686
|
+
};
|
|
4687
|
+
});
|
|
4688
|
+
|
|
4689
|
+
return [
|
|
4690
|
+
headers.join(","),
|
|
4691
|
+
...rows.map((row) => headers.map((header) => csvField(row[header])).join(","))
|
|
4692
|
+
].join("\n");
|
|
4693
|
+
}
|
|
4694
|
+
|
|
4695
|
+
function withProspectAppUrls(payload, host) {
|
|
4696
|
+
if (!payload || !Array.isArray(payload.prospects)) return payload;
|
|
4697
|
+
|
|
4698
|
+
return {
|
|
4699
|
+
...payload,
|
|
4700
|
+
prospects: payload.prospects.map((prospect) => ({
|
|
4701
|
+
...prospect,
|
|
4702
|
+
app_url: prospectAppUrl(prospect, host)
|
|
4703
|
+
}))
|
|
4704
|
+
};
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4707
|
+
function prospectAppUrl(prospect, host) {
|
|
4708
|
+
const prospectId = String(prospect?.prefix_id || "").trim();
|
|
4709
|
+
if (!prospectId) return undefined;
|
|
4710
|
+
|
|
4711
|
+
try {
|
|
4712
|
+
return new URL(`/prospects/${encodeURIComponent(prospectId)}`, normalizeHost(host)).toString();
|
|
4713
|
+
} catch {
|
|
4714
|
+
return undefined;
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
|
|
3677
4718
|
function sequenceExportRowsToCsv(rows) {
|
|
3678
4719
|
return [
|
|
3679
4720
|
SEQUENCE_EXPORT_CSV_COLUMNS.join(","),
|
|
@@ -3774,6 +4815,7 @@ const HELP_TOPICS = new Map([
|
|
|
3774
4815
|
" Setup & identity",
|
|
3775
4816
|
" audienti auth status",
|
|
3776
4817
|
" audienti config list",
|
|
4818
|
+
" audienti update check",
|
|
3777
4819
|
" audienti users list",
|
|
3778
4820
|
" audienti users select <account_user_id|email|name|me>",
|
|
3779
4821
|
" audienti users activity [account_user_id|me]",
|
|
@@ -3782,9 +4824,12 @@ const HELP_TOPICS = new Map([
|
|
|
3782
4824
|
" audienti motions list",
|
|
3783
4825
|
" audienti motions show <motn_id>",
|
|
3784
4826
|
" audienti motions analytics <motn_id>",
|
|
4827
|
+
" audienti motions run-discovery <motn_id>",
|
|
3785
4828
|
" audienti motions prospects <motn_id>",
|
|
3786
4829
|
" audienti motions create --payload <file.json>",
|
|
3787
|
-
" audienti motions update <motn_id> --status <state>",
|
|
4830
|
+
" audienti motions update <motn_id> [--status <state>] [--tags <tag[,tag...]>]",
|
|
4831
|
+
" audienti motions add-tag <motn_id> <tag>",
|
|
4832
|
+
" audienti motions remove-tag <motn_id> <tag>",
|
|
3788
4833
|
" audienti motions activate <motn_id>",
|
|
3789
4834
|
" audienti motions pause <motn_id>",
|
|
3790
4835
|
" audienti motions delete <motn_id> --confirm <yes|true|Y|y>",
|
|
@@ -3794,8 +4839,15 @@ const HELP_TOPICS = new Map([
|
|
|
3794
4839
|
"",
|
|
3795
4840
|
" Prospects",
|
|
3796
4841
|
" audienti prospects list [filters]",
|
|
4842
|
+
" audienti prospects check [filters]",
|
|
3797
4843
|
" audienti prospects show <prsp_id>",
|
|
3798
4844
|
" audienti prospects assign <prsp_id> --assigned-user <id|me|unassign>",
|
|
4845
|
+
" audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|rejected>",
|
|
4846
|
+
" audienti prospects lock <prsp_id> [--note <text>]",
|
|
4847
|
+
" audienti prospects reject <prsp_id>",
|
|
4848
|
+
" audienti prospects nurture <prsp_id> [--reason <reason>]",
|
|
4849
|
+
" audienti prospects restore <prsp_id>",
|
|
4850
|
+
" audienti prospects unlock <prsp_id>",
|
|
3799
4851
|
" audienti prospects timeline <prsp_id>",
|
|
3800
4852
|
" audienti prospects import <linkedin_url> [--motion <motn_id>]",
|
|
3801
4853
|
" audienti prospects import-batch --file <csv|jsonl|json>",
|
|
@@ -3803,11 +4855,26 @@ const HELP_TOPICS = new Map([
|
|
|
3803
4855
|
" audienti prospects add-profile <prsp_id> --url <profile_url|email|phone>",
|
|
3804
4856
|
"",
|
|
3805
4857
|
" Lists & targeting inputs",
|
|
3806
|
-
" audienti lists list",
|
|
4858
|
+
" audienti lists list [--tag <tag>]",
|
|
3807
4859
|
" audienti lists prospects <list_id>",
|
|
4860
|
+
" audienti lists add-tag <list_id> <tag>",
|
|
4861
|
+
" audienti lists remove-tag <list_id> <tag>",
|
|
4862
|
+
" audienti tags list",
|
|
4863
|
+
" audienti tags show <tag>",
|
|
3808
4864
|
" audienti offers list",
|
|
3809
|
-
" audienti
|
|
4865
|
+
" audienti offers show <offr_id>",
|
|
4866
|
+
" audienti offers update <offr_id> [--name <text>]",
|
|
4867
|
+
" audienti offers delete <offr_id> --confirm <yes|true|Y|y>",
|
|
4868
|
+
" audienti icps list [--tag <tag>]",
|
|
4869
|
+
" audienti icps show <icp_id>",
|
|
4870
|
+
" audienti icps update <icp_id> [--tags <tag[,tag...]>]",
|
|
4871
|
+
" audienti icps add-tag <icp_id> <tag>",
|
|
4872
|
+
" audienti icps remove-tag <icp_id> <tag>",
|
|
3810
4873
|
" audienti companies search --query <text>",
|
|
4874
|
+
" audienti dnc list",
|
|
4875
|
+
" audienti dnc add <email|citation_id|profile_url>",
|
|
4876
|
+
" audienti company-rules list",
|
|
4877
|
+
" audienti company-rules create (--linkedin-url <url> | --domain <domain>) --disposition <state>",
|
|
3811
4878
|
"",
|
|
3812
4879
|
" Writer",
|
|
3813
4880
|
" audienti writer test-run <prsp_id>",
|
|
@@ -3821,6 +4888,7 @@ const HELP_TOPICS = new Map([
|
|
|
3821
4888
|
"",
|
|
3822
4889
|
" Analytics",
|
|
3823
4890
|
" audienti analytics prospects --window 24h",
|
|
4891
|
+
" audienti analytics dashboard --play-tag <tag>",
|
|
3824
4892
|
" audienti analytics prospects cohort-analysis --weeks 4 --motion <motn_id>",
|
|
3825
4893
|
" audienti analytics users --user me --window 30d",
|
|
3826
4894
|
" audienti analytics visibility --window 24h --user me",
|
|
@@ -3835,6 +4903,7 @@ const HELP_TOPICS = new Map([
|
|
|
3835
4903
|
" Inspect a prospect: audienti prospects show <prsp_id> --json",
|
|
3836
4904
|
" Preview a campaign: audienti writer test-run <prsp_id>",
|
|
3837
4905
|
" Analyze one motion: audienti motions analytics <motn_id>",
|
|
4906
|
+
" Count one campaign: audienti analytics dashboard --play-tag <tag>",
|
|
3838
4907
|
" Audit your work: audienti analytics users --user me --window 30d",
|
|
3839
4908
|
"",
|
|
3840
4909
|
"Global options:",
|
|
@@ -3935,6 +5004,46 @@ const HELP_TOPICS = new Map([
|
|
|
3935
5004
|
" Default account user: account user name and id, or none selected"
|
|
3936
5005
|
].join("\n")],
|
|
3937
5006
|
|
|
5007
|
+
["update", [
|
|
5008
|
+
"Usage:",
|
|
5009
|
+
" audienti update check [--json] [--registry <url>]",
|
|
5010
|
+
"",
|
|
5011
|
+
"Status: implemented",
|
|
5012
|
+
"",
|
|
5013
|
+
"Purpose:",
|
|
5014
|
+
" Check whether this local Audienti CLI install is behind the latest published package.",
|
|
5015
|
+
"",
|
|
5016
|
+
"Commands:",
|
|
5017
|
+
" audienti update check Compare the local package version to the npm registry"
|
|
5018
|
+
].join("\n")],
|
|
5019
|
+
|
|
5020
|
+
["update check", [
|
|
5021
|
+
"Usage:",
|
|
5022
|
+
" audienti update check [--json] [--registry <url>]",
|
|
5023
|
+
"",
|
|
5024
|
+
"Status: implemented",
|
|
5025
|
+
"",
|
|
5026
|
+
"Purpose:",
|
|
5027
|
+
" Report whether this local CLI should be updated.",
|
|
5028
|
+
"",
|
|
5029
|
+
"Output shape:",
|
|
5030
|
+
" package_name: @audienti/cli",
|
|
5031
|
+
" current_version: local package version",
|
|
5032
|
+
" latest_version: latest registry version, or null when unknown",
|
|
5033
|
+
" update_available: true | false | null",
|
|
5034
|
+
" status: current | update_available | unknown",
|
|
5035
|
+
" install_command: npm install --global @audienti/cli",
|
|
5036
|
+
" registry: registry URL used for the check",
|
|
5037
|
+
" checked_at: ISO timestamp",
|
|
5038
|
+
" error: string | null",
|
|
5039
|
+
"",
|
|
5040
|
+
"Options:",
|
|
5041
|
+
" --registry <url> Alternate npm-compatible registry. Default: https://registry.npmjs.org",
|
|
5042
|
+
"",
|
|
5043
|
+
"Example:",
|
|
5044
|
+
" audienti update check --json"
|
|
5045
|
+
].join("\n")],
|
|
5046
|
+
|
|
3938
5047
|
["accounts", [
|
|
3939
5048
|
"Usage:",
|
|
3940
5049
|
" audienti accounts list [--json]",
|
|
@@ -4047,12 +5156,15 @@ const HELP_TOPICS = new Map([
|
|
|
4047
5156
|
["offers", [
|
|
4048
5157
|
"Usage:",
|
|
4049
5158
|
" audienti offers list [--json]",
|
|
5159
|
+
" audienti offers show <offr_id> [--json]",
|
|
4050
5160
|
" audienti offers create --name <text> [--json]",
|
|
5161
|
+
" audienti offers update <offr_id> [--name <text>] [--json]",
|
|
5162
|
+
" audienti offers delete <offr_id> --confirm <yes|true|Y|y> [--json]",
|
|
4051
5163
|
"",
|
|
4052
5164
|
"Status: implemented",
|
|
4053
5165
|
"",
|
|
4054
5166
|
"Purpose:",
|
|
4055
|
-
"
|
|
5167
|
+
" Manage the offers available to the current account so an agent can choose offer_id for motion creation."
|
|
4056
5168
|
].join("\n")],
|
|
4057
5169
|
|
|
4058
5170
|
["offers list", [
|
|
@@ -4102,10 +5214,60 @@ const HELP_TOPICS = new Map([
|
|
|
4102
5214
|
" }"
|
|
4103
5215
|
].join("\n")],
|
|
4104
5216
|
|
|
5217
|
+
["offers show", [
|
|
5218
|
+
"Usage:",
|
|
5219
|
+
` ${OFFERS_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
5220
|
+
"",
|
|
5221
|
+
"Status: implemented",
|
|
5222
|
+
"",
|
|
5223
|
+
"Input shape:",
|
|
5224
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
5225
|
+
"",
|
|
5226
|
+
"API:",
|
|
5227
|
+
" GET /api/v1/accounts/:account_id/offers/:id.json"
|
|
5228
|
+
].join("\n")],
|
|
5229
|
+
|
|
5230
|
+
["offers update", [
|
|
5231
|
+
"Usage:",
|
|
5232
|
+
` ${OFFERS_UPDATE_USAGE.slice("Usage: ".length)}`,
|
|
5233
|
+
"",
|
|
5234
|
+
"Status: implemented",
|
|
5235
|
+
"",
|
|
5236
|
+
"Purpose:",
|
|
5237
|
+
" Update simple offer fields without changing linked motions.",
|
|
5238
|
+
"",
|
|
5239
|
+
"Input shape:",
|
|
5240
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
5241
|
+
" name: string | optional",
|
|
5242
|
+
" description: string | optional",
|
|
5243
|
+
" url: string | optional",
|
|
5244
|
+
"",
|
|
5245
|
+
"API:",
|
|
5246
|
+
" PATCH /api/v1/accounts/:account_id/offers/:id.json"
|
|
5247
|
+
].join("\n")],
|
|
5248
|
+
|
|
5249
|
+
["offers delete", [
|
|
5250
|
+
"Usage:",
|
|
5251
|
+
` ${OFFERS_DELETE_USAGE.slice("Usage: ".length)}`,
|
|
5252
|
+
"",
|
|
5253
|
+
"Status: implemented",
|
|
5254
|
+
"",
|
|
5255
|
+
"Input shape:",
|
|
5256
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
5257
|
+
" confirm: one of yes, true, Y, y",
|
|
5258
|
+
"",
|
|
5259
|
+
"API:",
|
|
5260
|
+
" DELETE /api/v1/accounts/:account_id/offers/:id.json"
|
|
5261
|
+
].join("\n")],
|
|
5262
|
+
|
|
4105
5263
|
["icps", [
|
|
4106
5264
|
"Usage:",
|
|
4107
|
-
" audienti icps list [--json]",
|
|
5265
|
+
" audienti icps list [--tag <tag>] [--json]",
|
|
5266
|
+
" audienti icps show <icp_id> [--json]",
|
|
4108
5267
|
" audienti icps create (--name <text> | --payload <file.json>) [--json]",
|
|
5268
|
+
" audienti icps update <icp_id> [--tags <tag[,tag...]>] [--json]",
|
|
5269
|
+
" audienti icps add-tag <icp_id> <tag> [--json]",
|
|
5270
|
+
" audienti icps remove-tag <icp_id> <tag> [--json]",
|
|
4109
5271
|
"",
|
|
4110
5272
|
"Status: implemented",
|
|
4111
5273
|
"",
|
|
@@ -4115,10 +5277,13 @@ const HELP_TOPICS = new Map([
|
|
|
4115
5277
|
|
|
4116
5278
|
["icps list", [
|
|
4117
5279
|
"Usage:",
|
|
4118
|
-
" audienti icps list [--json] [--account <acct_id>]",
|
|
5280
|
+
" audienti icps list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4119
5281
|
"",
|
|
4120
5282
|
"Status: implemented",
|
|
4121
5283
|
"",
|
|
5284
|
+
"Options:",
|
|
5285
|
+
" --tag <tag> Filter locally to ICPs whose tags include the normalized tag",
|
|
5286
|
+
"",
|
|
4122
5287
|
"API:",
|
|
4123
5288
|
" GET /api/v1/accounts/:account_id/icps.json",
|
|
4124
5289
|
"",
|
|
@@ -4127,91 +5292,376 @@ const HELP_TOPICS = new Map([
|
|
|
4127
5292
|
" prefix_id: icpp_",
|
|
4128
5293
|
" name: string",
|
|
4129
5294
|
" notes: string | null",
|
|
5295
|
+
" tags: [string]",
|
|
4130
5296
|
" discovery_keyword: string | null",
|
|
4131
5297
|
" agent: { id, name } | null"
|
|
4132
5298
|
].join("\n")],
|
|
4133
5299
|
|
|
4134
|
-
["icps create", [
|
|
5300
|
+
["icps create", [
|
|
5301
|
+
"Usage:",
|
|
5302
|
+
" audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] | --payload <file.json>) [--json] [--account <acct_id>]",
|
|
5303
|
+
"",
|
|
5304
|
+
"Status: implemented",
|
|
5305
|
+
"",
|
|
5306
|
+
"Purpose:",
|
|
5307
|
+
" Create a new account ICP that can be attached to a motion or reused for targeting work.",
|
|
5308
|
+
"",
|
|
5309
|
+
"Input shape:",
|
|
5310
|
+
" name: string Required ICP name",
|
|
5311
|
+
" notes: string | optional",
|
|
5312
|
+
" tags: comma-separated tag list | optional",
|
|
5313
|
+
" discovery_keyword: string | optional",
|
|
5314
|
+
" payload: file.json | optional full ICP object using the account API create shape",
|
|
5315
|
+
"",
|
|
5316
|
+
"API:",
|
|
5317
|
+
" POST /api/v1/accounts/:account_id/icps.json",
|
|
5318
|
+
"",
|
|
5319
|
+
"Simple JSON body:",
|
|
5320
|
+
" {",
|
|
5321
|
+
" \"icp\": {",
|
|
5322
|
+
" \"name\": \"Renewal-stage IT leaders\",",
|
|
5323
|
+
" \"notes\": \"IT leaders reviewing vendors before renewal or QBR.\",",
|
|
5324
|
+
" \"discovery_keyword\": \"renewal\",",
|
|
5325
|
+
" \"tags\": [\"enterprise\", \"renewal\"]",
|
|
5326
|
+
" }",
|
|
5327
|
+
" }",
|
|
5328
|
+
"",
|
|
5329
|
+
"Payload file example:",
|
|
5330
|
+
" {",
|
|
5331
|
+
" \"name\": \"Vendor Management Office\",",
|
|
5332
|
+
" \"text_criteria\": \"Owns vendor governance, renewals, and escalations.\",",
|
|
5333
|
+
" \"discovery_keyword\": \"vendor governance\",",
|
|
5334
|
+
" \"negative_title_exceptions\": [\"sales\", \"recruiting\"],",
|
|
5335
|
+
" \"company_keywords\": {",
|
|
5336
|
+
" \"include\": [\"vendor governance\", \"supplier performance\"],",
|
|
5337
|
+
" \"exclude\": [\"staffing\"]",
|
|
5338
|
+
" },",
|
|
5339
|
+
" \"job_titles_attributes\": [",
|
|
5340
|
+
" {\"name\": \"Vendor Management Office\"},",
|
|
5341
|
+
" {\"name\": \"Strategic Vendor Management\"}",
|
|
5342
|
+
" ]",
|
|
5343
|
+
" }"
|
|
5344
|
+
].join("\n")],
|
|
5345
|
+
|
|
5346
|
+
["icps show", [
|
|
5347
|
+
"Usage:",
|
|
5348
|
+
` ${ICPS_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
5349
|
+
"",
|
|
5350
|
+
"Status: implemented",
|
|
5351
|
+
"",
|
|
5352
|
+
"Input shape:",
|
|
5353
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5354
|
+
"",
|
|
5355
|
+
"API:",
|
|
5356
|
+
" GET /api/v1/accounts/:account_id/icps/:id.json"
|
|
5357
|
+
].join("\n")],
|
|
5358
|
+
|
|
5359
|
+
["icps update", [
|
|
5360
|
+
"Usage:",
|
|
5361
|
+
" audienti icps update <icp_id> [--name <text>] [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]",
|
|
5362
|
+
"",
|
|
5363
|
+
"Status: implemented",
|
|
5364
|
+
"",
|
|
5365
|
+
"Purpose:",
|
|
5366
|
+
" Update simple ICP fields or replace the ICP's full tag set.",
|
|
5367
|
+
"",
|
|
5368
|
+
"Input shape:",
|
|
5369
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5370
|
+
" name: string | optional",
|
|
5371
|
+
" notes: string | optional",
|
|
5372
|
+
" discovery_keyword: string | optional",
|
|
5373
|
+
" tags: comma-separated tag list | optional",
|
|
5374
|
+
"",
|
|
5375
|
+
"API:",
|
|
5376
|
+
" PATCH /api/v1/accounts/:account_id/icps/:id.json",
|
|
5377
|
+
"",
|
|
5378
|
+
"JSON body:",
|
|
5379
|
+
" {",
|
|
5380
|
+
" \"icp\": {",
|
|
5381
|
+
" \"tags\": [\"enterprise\", \"renewal\"]",
|
|
5382
|
+
" }",
|
|
5383
|
+
" }"
|
|
5384
|
+
].join("\n")],
|
|
5385
|
+
|
|
5386
|
+
["icps add-tag", [
|
|
5387
|
+
"Usage:",
|
|
5388
|
+
" audienti icps add-tag <icp_id> <tag> [--json] [--account <acct_id>]",
|
|
5389
|
+
"",
|
|
5390
|
+
"Status: implemented",
|
|
5391
|
+
"",
|
|
5392
|
+
"Purpose:",
|
|
5393
|
+
" Add one normalized tag to an ICP.",
|
|
5394
|
+
"",
|
|
5395
|
+
"Input shape:",
|
|
5396
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5397
|
+
" tag: string",
|
|
5398
|
+
"",
|
|
5399
|
+
"API:",
|
|
5400
|
+
" POST /api/v1/accounts/:account_id/icps/:id/add_tag.json",
|
|
5401
|
+
"",
|
|
5402
|
+
"JSON body:",
|
|
5403
|
+
" {",
|
|
5404
|
+
" \"tag\": \"enterprise\"",
|
|
5405
|
+
" }"
|
|
5406
|
+
].join("\n")],
|
|
5407
|
+
|
|
5408
|
+
["icps remove-tag", [
|
|
5409
|
+
"Usage:",
|
|
5410
|
+
" audienti icps remove-tag <icp_id> <tag> [--json] [--account <acct_id>]",
|
|
5411
|
+
"",
|
|
5412
|
+
"Status: implemented",
|
|
5413
|
+
"",
|
|
5414
|
+
"Purpose:",
|
|
5415
|
+
" Remove one normalized tag from an ICP.",
|
|
5416
|
+
"",
|
|
5417
|
+
"Input shape:",
|
|
5418
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5419
|
+
" tag: string",
|
|
5420
|
+
"",
|
|
5421
|
+
"API:",
|
|
5422
|
+
" DELETE /api/v1/accounts/:account_id/icps/:id/remove_tag.json",
|
|
5423
|
+
"",
|
|
5424
|
+
"JSON body:",
|
|
5425
|
+
" {",
|
|
5426
|
+
" \"tag\": \"enterprise\"",
|
|
5427
|
+
" }"
|
|
5428
|
+
].join("\n")],
|
|
5429
|
+
|
|
5430
|
+
["companies", [
|
|
5431
|
+
"Usage:",
|
|
5432
|
+
" audienti companies search --query <text> [--json]",
|
|
5433
|
+
"",
|
|
5434
|
+
"Status: implemented",
|
|
5435
|
+
"",
|
|
5436
|
+
"Purpose:",
|
|
5437
|
+
" Returns persisted LinkedIn company profiles that match a company search query."
|
|
5438
|
+
].join("\n")],
|
|
5439
|
+
|
|
5440
|
+
["companies search", [
|
|
5441
|
+
"Usage:",
|
|
5442
|
+
" audienti companies search --query <text> [--json] [--account <acct_id>]",
|
|
5443
|
+
"",
|
|
5444
|
+
"Status: implemented",
|
|
5445
|
+
"",
|
|
5446
|
+
"API:",
|
|
5447
|
+
" GET /api/v1/accounts/:account_id/companies.json",
|
|
5448
|
+
"",
|
|
5449
|
+
"Input shape:",
|
|
5450
|
+
" query: string",
|
|
5451
|
+
"",
|
|
5452
|
+
"Output shape:",
|
|
5453
|
+
" companies[].prefix_id: prof_ profile id used by --company-profile",
|
|
5454
|
+
" companies[].citation_id: linkedin/company:...",
|
|
5455
|
+
" companies[].display_name: string",
|
|
5456
|
+
" companies[].url: string",
|
|
5457
|
+
" companies[].industry: string | null",
|
|
5458
|
+
" companies[].location: string | null"
|
|
5459
|
+
].join("\n")],
|
|
5460
|
+
|
|
5461
|
+
["dnc", [
|
|
5462
|
+
"Usage:",
|
|
5463
|
+
" audienti dnc list [--json]",
|
|
5464
|
+
` ${DNC_ADD_USAGE.slice("Usage: ".length)}`,
|
|
5465
|
+
` ${DNC_IMPORT_USAGE.slice("Usage: ".length)}`,
|
|
5466
|
+
` ${DNC_REMOVE_USAGE.slice("Usage: ".length)}`,
|
|
5467
|
+
"",
|
|
5468
|
+
"Status: implemented",
|
|
5469
|
+
"",
|
|
5470
|
+
"Purpose:",
|
|
5471
|
+
" Manage account-level do-not-contact entries through the same settings/API path as the app."
|
|
5472
|
+
].join("\n")],
|
|
5473
|
+
|
|
5474
|
+
["dnc list", [
|
|
5475
|
+
"Usage:",
|
|
5476
|
+
" audienti dnc list [--limit <n>] [--offset <n>] [--json] [--account <acct_id>]",
|
|
5477
|
+
"",
|
|
5478
|
+
"Status: implemented",
|
|
5479
|
+
"",
|
|
5480
|
+
"API:",
|
|
5481
|
+
" GET /api/v1/accounts/:account_id/dnc.json"
|
|
5482
|
+
].join("\n")],
|
|
5483
|
+
|
|
5484
|
+
["dnc add", [
|
|
5485
|
+
"Usage:",
|
|
5486
|
+
` ${DNC_ADD_USAGE.slice("Usage: ".length)}`,
|
|
5487
|
+
"",
|
|
5488
|
+
"Status: implemented",
|
|
5489
|
+
"",
|
|
5490
|
+
"Input shape:",
|
|
5491
|
+
" value: email, citation ID, or supported person profile URL",
|
|
5492
|
+
"",
|
|
5493
|
+
"Behavior:",
|
|
5494
|
+
" Creates or reactivates an account DNC entry and retroactively rejects matching account prospects.",
|
|
5495
|
+
"",
|
|
5496
|
+
"API:",
|
|
5497
|
+
" POST /api/v1/accounts/:account_id/dnc.json"
|
|
5498
|
+
].join("\n")],
|
|
5499
|
+
|
|
5500
|
+
["dnc import", [
|
|
5501
|
+
"Usage:",
|
|
5502
|
+
` ${DNC_IMPORT_USAGE.slice("Usage: ".length)}`,
|
|
5503
|
+
"",
|
|
5504
|
+
"Status: implemented",
|
|
5505
|
+
"",
|
|
5506
|
+
"Input shape:",
|
|
5507
|
+
" file: text or CSV file. The CLI sends one value per line using column one for CSV-like rows.",
|
|
5508
|
+
"",
|
|
5509
|
+
"API:",
|
|
5510
|
+
" POST /api/v1/accounts/:account_id/dnc/import.json"
|
|
5511
|
+
].join("\n")],
|
|
5512
|
+
|
|
5513
|
+
["dnc remove", [
|
|
5514
|
+
"Usage:",
|
|
5515
|
+
` ${DNC_REMOVE_USAGE.slice("Usage: ".length)}`,
|
|
5516
|
+
"",
|
|
5517
|
+
"Status: implemented",
|
|
5518
|
+
"",
|
|
5519
|
+
"API:",
|
|
5520
|
+
" DELETE /api/v1/accounts/:account_id/dnc/:id.json"
|
|
5521
|
+
].join("\n")],
|
|
5522
|
+
|
|
5523
|
+
["company-rules", [
|
|
5524
|
+
"Usage:",
|
|
5525
|
+
" audienti company-rules list [--json]",
|
|
5526
|
+
` ${COMPANY_RULES_CREATE_USAGE.slice("Usage: ".length)}`,
|
|
5527
|
+
` ${COMPANY_RULES_UPDATE_USAGE.slice("Usage: ".length)}`,
|
|
5528
|
+
` ${COMPANY_RULES_REMOVE_USAGE.slice("Usage: ".length)}`,
|
|
5529
|
+
` ${COMPANY_RULES_APPLY_USAGE.slice("Usage: ".length)}`,
|
|
5530
|
+
"",
|
|
5531
|
+
"Status: implemented",
|
|
5532
|
+
"",
|
|
5533
|
+
"Purpose:",
|
|
5534
|
+
" Manage account-wide and user-scoped company disposition rules keyed by LinkedIn company URL or domain."
|
|
5535
|
+
].join("\n")],
|
|
5536
|
+
|
|
5537
|
+
["company-rules list", [
|
|
5538
|
+
"Usage:",
|
|
5539
|
+
" audienti company-rules list [--json] [--account <acct_id>]",
|
|
5540
|
+
"",
|
|
5541
|
+
"Status: implemented",
|
|
5542
|
+
"",
|
|
5543
|
+
"API:",
|
|
5544
|
+
" GET /api/v1/accounts/:account_id/company_rules.json"
|
|
5545
|
+
].join("\n")],
|
|
5546
|
+
|
|
5547
|
+
["company-rules create", [
|
|
5548
|
+
"Usage:",
|
|
5549
|
+
` ${COMPANY_RULES_CREATE_USAGE.slice("Usage: ".length)}`,
|
|
5550
|
+
"",
|
|
5551
|
+
"Status: implemented",
|
|
5552
|
+
"",
|
|
5553
|
+
"Input shape:",
|
|
5554
|
+
" linkedin-url: LinkedIn company URL | optional when domain is present",
|
|
5555
|
+
" domain: company domain | optional when linkedin-url is present",
|
|
5556
|
+
" disposition: monitor | nurture | not_fit | reject",
|
|
5557
|
+
" user: account user id, email, or me | optional. Omit for account-wide.",
|
|
5558
|
+
"",
|
|
5559
|
+
"Behavior:",
|
|
5560
|
+
" Matching prospects are always created first. Rule application then applies the disposition; monitor locks activity with lock_kind=company_policy until dedicated monitor mode exists.",
|
|
5561
|
+
"",
|
|
5562
|
+
"API:",
|
|
5563
|
+
" POST /api/v1/accounts/:account_id/company_rules.json"
|
|
5564
|
+
].join("\n")],
|
|
5565
|
+
|
|
5566
|
+
["company-rules update", [
|
|
5567
|
+
"Usage:",
|
|
5568
|
+
` ${COMPANY_RULES_UPDATE_USAGE.slice("Usage: ".length)}`,
|
|
5569
|
+
"",
|
|
5570
|
+
"Status: implemented",
|
|
5571
|
+
"",
|
|
5572
|
+
"Input shape:",
|
|
5573
|
+
" user: account user id, email, me, or none. none makes the rule account-wide.",
|
|
5574
|
+
"",
|
|
5575
|
+
"API:",
|
|
5576
|
+
" PATCH /api/v1/accounts/:account_id/company_rules/:id.json"
|
|
5577
|
+
].join("\n")],
|
|
5578
|
+
|
|
5579
|
+
["company-rules remove", [
|
|
5580
|
+
"Usage:",
|
|
5581
|
+
` ${COMPANY_RULES_REMOVE_USAGE.slice("Usage: ".length)}`,
|
|
5582
|
+
"",
|
|
5583
|
+
"Status: implemented",
|
|
5584
|
+
"",
|
|
5585
|
+
"API:",
|
|
5586
|
+
" DELETE /api/v1/accounts/:account_id/company_rules/:id.json"
|
|
5587
|
+
].join("\n")],
|
|
5588
|
+
|
|
5589
|
+
["company-rules apply", [
|
|
4135
5590
|
"Usage:",
|
|
4136
|
-
|
|
5591
|
+
` ${COMPANY_RULES_APPLY_USAGE.slice("Usage: ".length)}`,
|
|
4137
5592
|
"",
|
|
4138
5593
|
"Status: implemented",
|
|
4139
5594
|
"",
|
|
4140
|
-
"
|
|
4141
|
-
"
|
|
4142
|
-
"",
|
|
4143
|
-
"Input shape:",
|
|
4144
|
-
" name: string Required ICP name",
|
|
4145
|
-
" notes: string | optional",
|
|
4146
|
-
" discovery_keyword: string | optional",
|
|
4147
|
-
" payload: file.json | optional full ICP object using the account API create shape",
|
|
5595
|
+
"Behavior:",
|
|
5596
|
+
" Backfills active visible account prospects through the same company-rule applicator used after profile writes.",
|
|
4148
5597
|
"",
|
|
4149
5598
|
"API:",
|
|
4150
|
-
" POST /api/v1/accounts/:account_id/
|
|
5599
|
+
" POST /api/v1/accounts/:account_id/company_rules/:id/apply.json",
|
|
5600
|
+
" POST /api/v1/accounts/:account_id/company_rules/apply_all.json"
|
|
5601
|
+
].join("\n")],
|
|
5602
|
+
|
|
5603
|
+
["tags", [
|
|
5604
|
+
"Usage:",
|
|
5605
|
+
" audienti tags list [--json]",
|
|
5606
|
+
" audienti tags show <tag> [--json]",
|
|
4151
5607
|
"",
|
|
4152
|
-
"
|
|
4153
|
-
" {",
|
|
4154
|
-
" \"icp\": {",
|
|
4155
|
-
" \"name\": \"Renewal-stage IT leaders\",",
|
|
4156
|
-
" \"notes\": \"IT leaders reviewing vendors before renewal or QBR.\",",
|
|
4157
|
-
" \"discovery_keyword\": \"renewal\"",
|
|
4158
|
-
" }",
|
|
4159
|
-
" }",
|
|
5608
|
+
"Status: implemented",
|
|
4160
5609
|
"",
|
|
4161
|
-
"
|
|
4162
|
-
"
|
|
4163
|
-
"
|
|
4164
|
-
"
|
|
4165
|
-
" \"discovery_keyword\": \"vendor governance\",",
|
|
4166
|
-
" \"negative_title_exceptions\": [\"sales\", \"recruiting\"],",
|
|
4167
|
-
" \"company_keywords\": {",
|
|
4168
|
-
" \"include\": [\"vendor governance\", \"supplier performance\"],",
|
|
4169
|
-
" \"exclude\": [\"staffing\"]",
|
|
4170
|
-
" },",
|
|
4171
|
-
" \"job_titles_attributes\": [",
|
|
4172
|
-
" {\"name\": \"Vendor Management Office\"},",
|
|
4173
|
-
" {\"name\": \"Strategic Vendor Management\"}",
|
|
4174
|
-
" ]",
|
|
4175
|
-
" }"
|
|
5610
|
+
"Purpose:",
|
|
5611
|
+
" Show the shared vocabulary from ICP tags, list tags, and motion play_tags currently in use.",
|
|
5612
|
+
"",
|
|
5613
|
+
"Run `audienti tags list help` or `audienti tags show help` for output shape."
|
|
4176
5614
|
].join("\n")],
|
|
4177
5615
|
|
|
4178
|
-
["
|
|
5616
|
+
["tags list", [
|
|
4179
5617
|
"Usage:",
|
|
4180
|
-
" audienti
|
|
5618
|
+
" audienti tags list [--json] [--account <acct_id>]",
|
|
4181
5619
|
"",
|
|
4182
5620
|
"Status: implemented",
|
|
4183
5621
|
"",
|
|
4184
5622
|
"Purpose:",
|
|
4185
|
-
"
|
|
5623
|
+
" List normalized tags currently used by account ICPs, lists, and motions so new records can match existing labels.",
|
|
5624
|
+
"",
|
|
5625
|
+
"API:",
|
|
5626
|
+
" GET /api/v1/accounts/:account_id/tags.json",
|
|
5627
|
+
"",
|
|
5628
|
+
"Output shape:",
|
|
5629
|
+
" tags[].name: normalized tag string",
|
|
5630
|
+
" tags[].icp_count: number of ICPs using the tag",
|
|
5631
|
+
" tags[].list_count: number of lists using the tag",
|
|
5632
|
+
" tags[].motion_count: number of motions using the tag",
|
|
5633
|
+
" tags[].total_count: icp_count + list_count + motion_count"
|
|
4186
5634
|
].join("\n")],
|
|
4187
5635
|
|
|
4188
|
-
["
|
|
5636
|
+
["tags show", [
|
|
4189
5637
|
"Usage:",
|
|
4190
|
-
" audienti
|
|
5638
|
+
" audienti tags show <tag> [--json] [--account <acct_id>]",
|
|
4191
5639
|
"",
|
|
4192
5640
|
"Status: implemented",
|
|
4193
5641
|
"",
|
|
4194
|
-
"
|
|
4195
|
-
"
|
|
5642
|
+
"Purpose:",
|
|
5643
|
+
" Show the ICPs, lists, and motions currently using one normalized tag.",
|
|
4196
5644
|
"",
|
|
4197
|
-
"
|
|
4198
|
-
"
|
|
5645
|
+
"API:",
|
|
5646
|
+
" GET /api/v1/accounts/:account_id/icps.json",
|
|
5647
|
+
" GET /api/v1/accounts/:account_id/lists.json",
|
|
5648
|
+
" GET /api/v1/accounts/:account_id/motions.json",
|
|
4199
5649
|
"",
|
|
4200
5650
|
"Output shape:",
|
|
4201
|
-
"
|
|
4202
|
-
"
|
|
4203
|
-
"
|
|
4204
|
-
"
|
|
4205
|
-
" companies[].industry: string | null",
|
|
4206
|
-
" companies[].location: string | null"
|
|
5651
|
+
" tag: normalized tag string",
|
|
5652
|
+
" icps[]: ICP rows whose tags include tag",
|
|
5653
|
+
" lists[]: list rows whose tags include tag",
|
|
5654
|
+
" motions[]: motion rows whose play_tags include tag"
|
|
4207
5655
|
].join("\n")],
|
|
4208
5656
|
|
|
4209
5657
|
["lists", [
|
|
4210
5658
|
"Usage:",
|
|
4211
|
-
" audienti lists list [--json]",
|
|
4212
|
-
" audienti lists create --name <text> [--json]",
|
|
5659
|
+
" audienti lists list [--tag <tag>] [--json]",
|
|
5660
|
+
" audienti lists create --name <text> [--tags <tag[,tag...]>] [--json]",
|
|
4213
5661
|
" audienti lists show <list_id> [--json]",
|
|
4214
|
-
" audienti lists update <list_id> [--json]",
|
|
5662
|
+
" audienti lists update <list_id> [--tags <tag[,tag...]>] [--json]",
|
|
5663
|
+
" audienti lists add-tag <list_id> <tag> [--json]",
|
|
5664
|
+
" audienti lists remove-tag <list_id> <tag> [--json]",
|
|
4215
5665
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json]",
|
|
4216
5666
|
" audienti lists prospects <list_id> [--json]",
|
|
4217
5667
|
" audienti lists add-prospects <list_id> <prsp_id> [prsp_id...] [--json]",
|
|
@@ -4225,10 +5675,13 @@ const HELP_TOPICS = new Map([
|
|
|
4225
5675
|
|
|
4226
5676
|
["lists list", [
|
|
4227
5677
|
"Usage:",
|
|
4228
|
-
" audienti lists list [--json] [--account <acct_id>]",
|
|
5678
|
+
" audienti lists list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4229
5679
|
"",
|
|
4230
5680
|
"Status: implemented",
|
|
4231
5681
|
"",
|
|
5682
|
+
"Options:",
|
|
5683
|
+
" --tag <tag> Filter locally to lists whose tags include the normalized tag",
|
|
5684
|
+
"",
|
|
4232
5685
|
"API:",
|
|
4233
5686
|
" GET /api/v1/accounts/:account_id/lists.json",
|
|
4234
5687
|
"",
|
|
@@ -4239,12 +5692,13 @@ const HELP_TOPICS = new Map([
|
|
|
4239
5692
|
" description: string | null",
|
|
4240
5693
|
" prospect_count: integer",
|
|
4241
5694
|
" protected_system_list: boolean",
|
|
4242
|
-
" hubspot_synced: boolean"
|
|
5695
|
+
" hubspot_synced: boolean",
|
|
5696
|
+
" tags: [string]"
|
|
4243
5697
|
].join("\n")],
|
|
4244
5698
|
|
|
4245
5699
|
["lists create", [
|
|
4246
5700
|
"Usage:",
|
|
4247
|
-
" audienti lists create --name <text> [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
5701
|
+
" audienti lists create --name <text> [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
4248
5702
|
"",
|
|
4249
5703
|
"Status: implemented",
|
|
4250
5704
|
"",
|
|
@@ -4254,6 +5708,7 @@ const HELP_TOPICS = new Map([
|
|
|
4254
5708
|
"Input shape:",
|
|
4255
5709
|
" name: string Required list name",
|
|
4256
5710
|
" description: string | optional",
|
|
5711
|
+
" tags: comma-separated tag list | optional",
|
|
4257
5712
|
" campaign_hook: string | optional",
|
|
4258
5713
|
" audience_note: string | optional",
|
|
4259
5714
|
"",
|
|
@@ -4262,10 +5717,11 @@ const HELP_TOPICS = new Map([
|
|
|
4262
5717
|
"",
|
|
4263
5718
|
"JSON body:",
|
|
4264
5719
|
" {",
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
5720
|
+
" \"list\": {",
|
|
5721
|
+
" \"name\": \"CIO renewal targets\",",
|
|
5722
|
+
" \"description\": \"Accounts to review before QBR outreach.\",",
|
|
5723
|
+
" \"tags\": [\"sarit\", \"pj\"],",
|
|
5724
|
+
" \"campaign_brief\": {",
|
|
4269
5725
|
" \"hook\": \"Vendor accountability before renewal\",",
|
|
4270
5726
|
" \"audience_note\": \"IT leaders running QBRs and renewals\"",
|
|
4271
5727
|
" }",
|
|
@@ -4288,7 +5744,7 @@ const HELP_TOPICS = new Map([
|
|
|
4288
5744
|
|
|
4289
5745
|
["lists update", [
|
|
4290
5746
|
"Usage:",
|
|
4291
|
-
" audienti lists update <list_id> [--name <text>] [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
5747
|
+
" audienti lists update <list_id> [--name <text>] [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
4292
5748
|
"",
|
|
4293
5749
|
"Status: implemented",
|
|
4294
5750
|
"",
|
|
@@ -4299,6 +5755,7 @@ const HELP_TOPICS = new Map([
|
|
|
4299
5755
|
" list_id: list_ prefix id",
|
|
4300
5756
|
" list.name: string | optional",
|
|
4301
5757
|
" list.description: string | optional",
|
|
5758
|
+
" list.tags: comma-separated tag list | optional",
|
|
4302
5759
|
" list.campaign_brief.hook: string | optional",
|
|
4303
5760
|
" list.campaign_brief.audience_note: string | optional",
|
|
4304
5761
|
"",
|
|
@@ -4306,6 +5763,50 @@ const HELP_TOPICS = new Map([
|
|
|
4306
5763
|
" PATCH /api/v1/accounts/:account_id/lists/:id.json"
|
|
4307
5764
|
].join("\n")],
|
|
4308
5765
|
|
|
5766
|
+
["lists add-tag", [
|
|
5767
|
+
"Usage:",
|
|
5768
|
+
` ${LISTS_ADD_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5769
|
+
"",
|
|
5770
|
+
"Status: implemented",
|
|
5771
|
+
"",
|
|
5772
|
+
"Purpose:",
|
|
5773
|
+
" Add one normalized tag to a list without changing prospect membership.",
|
|
5774
|
+
"",
|
|
5775
|
+
"Input shape:",
|
|
5776
|
+
" list_id: list_ prefix id",
|
|
5777
|
+
" tag: string",
|
|
5778
|
+
"",
|
|
5779
|
+
"API:",
|
|
5780
|
+
" POST /api/v1/accounts/:account_id/lists/:id/add_tag.json",
|
|
5781
|
+
"",
|
|
5782
|
+
"JSON body:",
|
|
5783
|
+
" {",
|
|
5784
|
+
" \"tag\": \"sarit\"",
|
|
5785
|
+
" }"
|
|
5786
|
+
].join("\n")],
|
|
5787
|
+
|
|
5788
|
+
["lists remove-tag", [
|
|
5789
|
+
"Usage:",
|
|
5790
|
+
` ${LISTS_REMOVE_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5791
|
+
"",
|
|
5792
|
+
"Status: implemented",
|
|
5793
|
+
"",
|
|
5794
|
+
"Purpose:",
|
|
5795
|
+
" Remove one normalized tag from a list.",
|
|
5796
|
+
"",
|
|
5797
|
+
"Input shape:",
|
|
5798
|
+
" list_id: list_ prefix id",
|
|
5799
|
+
" tag: string",
|
|
5800
|
+
"",
|
|
5801
|
+
"API:",
|
|
5802
|
+
" DELETE /api/v1/accounts/:account_id/lists/:id/remove_tag.json",
|
|
5803
|
+
"",
|
|
5804
|
+
"JSON body:",
|
|
5805
|
+
" {",
|
|
5806
|
+
" \"tag\": \"sarit\"",
|
|
5807
|
+
" }"
|
|
5808
|
+
].join("\n")],
|
|
5809
|
+
|
|
4309
5810
|
["lists delete", [
|
|
4310
5811
|
"Usage:",
|
|
4311
5812
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]",
|
|
@@ -4398,14 +5899,17 @@ const HELP_TOPICS = new Map([
|
|
|
4398
5899
|
|
|
4399
5900
|
["motions", [
|
|
4400
5901
|
"Usage:",
|
|
4401
|
-
" audienti motions list [--json]",
|
|
5902
|
+
" audienti motions list [--tag <tag>] [--json]",
|
|
4402
5903
|
" audienti motions show <motn_id> [--json]",
|
|
4403
5904
|
" audienti motions status <motn_id> [--json]",
|
|
5905
|
+
" audienti motions run-discovery <motn_id> [--target-count <n>] [--json]",
|
|
4404
5906
|
" audienti motions analytics <motn_id> [--window 30d] [--json]",
|
|
4405
5907
|
" audienti motions prospects <motn_id> [--json]",
|
|
4406
5908
|
" audienti motions add-prospects <motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4407
5909
|
" audienti motions create --payload <file.json> [--json]",
|
|
4408
|
-
" audienti motions update <motn_id> --status <draft|preparing|active|paused|archived> [--json]",
|
|
5910
|
+
" audienti motions update <motn_id> [--status <draft|preparing|active|paused|archived>] [--tags <tag[,tag...]>] [--json]",
|
|
5911
|
+
" audienti motions add-tag <motn_id> <tag> [--json]",
|
|
5912
|
+
" audienti motions remove-tag <motn_id> <tag> [--json]",
|
|
4409
5913
|
" audienti motions activate <motn_id> [--json]",
|
|
4410
5914
|
" audienti motions pause <motn_id> [--json]",
|
|
4411
5915
|
" audienti motions archive <motn_id> [--json]",
|
|
@@ -4413,7 +5917,7 @@ const HELP_TOPICS = new Map([
|
|
|
4413
5917
|
" audienti motions clone <motn_id> --name <text> [--json]",
|
|
4414
5918
|
" audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4415
5919
|
"",
|
|
4416
|
-
"Status: read, create, status update, delete, clone, status, and prospect attachment commands implemented",
|
|
5920
|
+
"Status: read, create, status update, delete, clone, status, discovery launch, and prospect attachment commands implemented",
|
|
4417
5921
|
"",
|
|
4418
5922
|
"CLI synonym:",
|
|
4419
5923
|
" `plays` is accepted anywhere `motions` is accepted",
|
|
@@ -4424,10 +5928,13 @@ const HELP_TOPICS = new Map([
|
|
|
4424
5928
|
|
|
4425
5929
|
["motions list", [
|
|
4426
5930
|
"Usage:",
|
|
4427
|
-
" audienti motions list [--json] [--account <acct_id>]",
|
|
5931
|
+
" audienti motions list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4428
5932
|
"",
|
|
4429
5933
|
"Status: implemented",
|
|
4430
5934
|
"",
|
|
5935
|
+
"Options:",
|
|
5936
|
+
" --tag <tag> Filter locally to motions whose play_tags include the normalized tag",
|
|
5937
|
+
"",
|
|
4431
5938
|
"API:",
|
|
4432
5939
|
" GET /api/v1/accounts/:account_id/motions.json",
|
|
4433
5940
|
"",
|
|
@@ -4440,7 +5947,8 @@ const HELP_TOPICS = new Map([
|
|
|
4440
5947
|
" offer.prefix_id: offr_",
|
|
4441
5948
|
" icp.prefix_id: icpp_",
|
|
4442
5949
|
" list.prefix_id: list_ | null",
|
|
4443
|
-
" principal_account_user.id: integer"
|
|
5950
|
+
" principal_account_user.id: integer",
|
|
5951
|
+
" play_tags: [string]"
|
|
4444
5952
|
].join("\n")],
|
|
4445
5953
|
|
|
4446
5954
|
["motions show", [
|
|
@@ -4498,6 +6006,27 @@ const HELP_TOPICS = new Map([
|
|
|
4498
6006
|
" GET /api/v1/accounts/:account_id/analytics/prospects.json?motion_id=:motion_id"
|
|
4499
6007
|
].join("\n")],
|
|
4500
6008
|
|
|
6009
|
+
["motions run-discovery", [
|
|
6010
|
+
"Usage:",
|
|
6011
|
+
` ${MOTIONS_RUN_DISCOVERY_USAGE.slice("Usage: ".length)}`,
|
|
6012
|
+
"",
|
|
6013
|
+
"Status: implemented",
|
|
6014
|
+
"",
|
|
6015
|
+
"Purpose:",
|
|
6016
|
+
" Queue an immediate discovery run for one discovery-capable motion or play.",
|
|
6017
|
+
"",
|
|
6018
|
+
"Options:",
|
|
6019
|
+
" --target-count <n> Override the manual replenishment target count for this launch.",
|
|
6020
|
+
"",
|
|
6021
|
+
"Output shape:",
|
|
6022
|
+
" enqueued: true when Motions::DiscoverJob was queued",
|
|
6023
|
+
" reason: launched | run_in_progress | lock_contention | target_met | enqueue_failed",
|
|
6024
|
+
" target_count: requested target count",
|
|
6025
|
+
"",
|
|
6026
|
+
"API:",
|
|
6027
|
+
" POST /api/v1/accounts/:account_id/motions/:id/run_discovery.json"
|
|
6028
|
+
].join("\n")],
|
|
6029
|
+
|
|
4501
6030
|
["motions prospects", [
|
|
4502
6031
|
"Usage:",
|
|
4503
6032
|
" audienti motions prospects <motn_id> [--json] [--account <acct_id>]",
|
|
@@ -4568,7 +6097,8 @@ const HELP_TOPICS = new Map([
|
|
|
4568
6097
|
" principal_account_user_id: integer | me | optional",
|
|
4569
6098
|
" icp_id: icpp_ prefix id | optional",
|
|
4570
6099
|
" list_id: list_ prefix id | optional",
|
|
4571
|
-
"
|
|
6100
|
+
" play_tags: [string] | optional",
|
|
6101
|
+
" inbound_channels: [linkedin | reddit] | optional",
|
|
4572
6102
|
" lopa_profiles: [{ url: string, source_type: creator | competitor | partner | customer | other }] | optional",
|
|
4573
6103
|
"",
|
|
4574
6104
|
"JSON example:",
|
|
@@ -4579,7 +6109,8 @@ const HELP_TOPICS = new Map([
|
|
|
4579
6109
|
" \"status\": \"draft\",",
|
|
4580
6110
|
" \"offer_id\": \"offr_abc123\",",
|
|
4581
6111
|
" \"principal_account_user_id\": 42,",
|
|
4582
|
-
" \"list_id\": \"list_abc123\"",
|
|
6112
|
+
" \"list_id\": \"list_abc123\",",
|
|
6113
|
+
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
4583
6114
|
" }",
|
|
4584
6115
|
"",
|
|
4585
6116
|
"Behavior:",
|
|
@@ -4622,23 +6153,69 @@ const HELP_TOPICS = new Map([
|
|
|
4622
6153
|
"Status: implemented",
|
|
4623
6154
|
"",
|
|
4624
6155
|
"Purpose:",
|
|
4625
|
-
" Change one motion or play's lifecycle status.",
|
|
6156
|
+
" Change one motion or play's lifecycle status or replace its tag set.",
|
|
4626
6157
|
"",
|
|
4627
6158
|
"Input shape:",
|
|
4628
6159
|
" motn_id: motn_ prefix id",
|
|
4629
|
-
" status: draft | preparing | active | paused | archived",
|
|
6160
|
+
" status: draft | preparing | active | paused | archived | optional",
|
|
6161
|
+
" tags: comma-separated tag list | optional",
|
|
4630
6162
|
"",
|
|
4631
6163
|
"Behavior:",
|
|
4632
|
-
" Updates only the
|
|
6164
|
+
" Updates only the provided fields. Sending --tags replaces the motion's full tag set.",
|
|
4633
6165
|
"",
|
|
4634
6166
|
"API:",
|
|
4635
6167
|
" PATCH /api/v1/accounts/:account_id/motions/:id.json",
|
|
4636
6168
|
"",
|
|
4637
6169
|
"JSON body:",
|
|
4638
6170
|
" {",
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
6171
|
+
" \"motion\": {",
|
|
6172
|
+
" \"status\": \"paused\",",
|
|
6173
|
+
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
6174
|
+
" }",
|
|
6175
|
+
" }"
|
|
6176
|
+
].join("\n")],
|
|
6177
|
+
|
|
6178
|
+
["motions add-tag", [
|
|
6179
|
+
"Usage:",
|
|
6180
|
+
` ${MOTIONS_ADD_TAG_USAGE.slice("Usage: ".length)}`,
|
|
6181
|
+
"",
|
|
6182
|
+
"Status: implemented",
|
|
6183
|
+
"",
|
|
6184
|
+
"Purpose:",
|
|
6185
|
+
" Add one normalized tag to a motion or play.",
|
|
6186
|
+
"",
|
|
6187
|
+
"Input shape:",
|
|
6188
|
+
" motn_id: motn_ prefix id",
|
|
6189
|
+
" tag: string",
|
|
6190
|
+
"",
|
|
6191
|
+
"API:",
|
|
6192
|
+
" POST /api/v1/accounts/:account_id/motions/:id/add_tag.json",
|
|
6193
|
+
"",
|
|
6194
|
+
"JSON body:",
|
|
6195
|
+
" {",
|
|
6196
|
+
" \"tag\": \"sarit\"",
|
|
6197
|
+
" }"
|
|
6198
|
+
].join("\n")],
|
|
6199
|
+
|
|
6200
|
+
["motions remove-tag", [
|
|
6201
|
+
"Usage:",
|
|
6202
|
+
` ${MOTIONS_REMOVE_TAG_USAGE.slice("Usage: ".length)}`,
|
|
6203
|
+
"",
|
|
6204
|
+
"Status: implemented",
|
|
6205
|
+
"",
|
|
6206
|
+
"Purpose:",
|
|
6207
|
+
" Remove one normalized tag from a motion or play.",
|
|
6208
|
+
"",
|
|
6209
|
+
"Input shape:",
|
|
6210
|
+
" motn_id: motn_ prefix id",
|
|
6211
|
+
" tag: string",
|
|
6212
|
+
"",
|
|
6213
|
+
"API:",
|
|
6214
|
+
" DELETE /api/v1/accounts/:account_id/motions/:id/remove_tag.json",
|
|
6215
|
+
"",
|
|
6216
|
+
"JSON body:",
|
|
6217
|
+
" {",
|
|
6218
|
+
" \"tag\": \"sarit\"",
|
|
4642
6219
|
" }"
|
|
4643
6220
|
].join("\n")],
|
|
4644
6221
|
|
|
@@ -4732,8 +6309,15 @@ const HELP_TOPICS = new Map([
|
|
|
4732
6309
|
["prospects", [
|
|
4733
6310
|
"Usage:",
|
|
4734
6311
|
" audienti prospects list [--json] [filters]",
|
|
6312
|
+
" audienti prospects check [--json|--csv] [filters]",
|
|
4735
6313
|
" audienti prospects show <prsp_id> [--json]",
|
|
4736
6314
|
" audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json]",
|
|
6315
|
+
" audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|rejected> [--json]",
|
|
6316
|
+
" audienti prospects reject <prsp_id> [--json]",
|
|
6317
|
+
" audienti prospects nurture <prsp_id> [--reason <reason>] [--json]",
|
|
6318
|
+
" audienti prospects restore <prsp_id> [--json]",
|
|
6319
|
+
" audienti prospects lock <prsp_id> [--note <text>] [--json]",
|
|
6320
|
+
" audienti prospects unlock <prsp_id> [--json]",
|
|
4737
6321
|
" audienti prospects timeline <prsp_id> [--json]",
|
|
4738
6322
|
" audienti prospects message-types <prsp_id> [--json]",
|
|
4739
6323
|
" audienti prospects write <prsp_id> --type <surface_key> [--json]",
|
|
@@ -4747,7 +6331,7 @@ const HELP_TOPICS = new Map([
|
|
|
4747
6331
|
" audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--json]",
|
|
4748
6332
|
" audienti prospects import-status <primp_id> [--json]",
|
|
4749
6333
|
"",
|
|
4750
|
-
"Status: read commands, assignment, per-prospect draft preview, sequence preview, and import implemented
|
|
6334
|
+
"Status: read commands, assignment, disposition, lock/unlock, per-prospect draft preview, sequence preview, and import implemented",
|
|
4751
6335
|
"",
|
|
4752
6336
|
"Filters:",
|
|
4753
6337
|
" --query <text>",
|
|
@@ -4816,6 +6400,43 @@ const HELP_TOPICS = new Map([
|
|
|
4816
6400
|
" audienti prospects list --all --csv"
|
|
4817
6401
|
].join("\n")],
|
|
4818
6402
|
|
|
6403
|
+
["prospects check", [
|
|
6404
|
+
"Usage:",
|
|
6405
|
+
" audienti prospects check [--json|--csv] [filters] [--account <acct_id>]",
|
|
6406
|
+
"",
|
|
6407
|
+
"Status: implemented",
|
|
6408
|
+
"",
|
|
6409
|
+
"Description:",
|
|
6410
|
+
" Lists suspect people prospects that do not have a certified company employment citation.",
|
|
6411
|
+
" Imported or reported company text is shown for investigation but does not count as certification.",
|
|
6412
|
+
"",
|
|
6413
|
+
"Filters:",
|
|
6414
|
+
" --query <text> Search name, title, company, email, profile URL",
|
|
6415
|
+
" --motion <motn_id> Filter to a motion",
|
|
6416
|
+
" --play <motn_id> Filter to a play using the same motion relationship",
|
|
6417
|
+
" --list <list_id> Filter to a prospect list",
|
|
6418
|
+
" --stage <stage> Filter to a pipeline stage",
|
|
6419
|
+
" --assigned-user <id|me|unassigned> Filter by assigned account user",
|
|
6420
|
+
" --limit <n> Max rows for one page; with --all it caps total rows up to 1000",
|
|
6421
|
+
" --page <n> 1-based page number",
|
|
6422
|
+
" --offset <n> Row offset for manual pagination",
|
|
6423
|
+
" --all Fetch every matching suspect prospect up to 1000 rows",
|
|
6424
|
+
" --csv Export CSV with app_url for operator review",
|
|
6425
|
+
"",
|
|
6426
|
+
"Output shape:",
|
|
6427
|
+
" prospects[].company_certification.status: missing",
|
|
6428
|
+
" prospects[].company_certification.reason: missing_employment_citation",
|
|
6429
|
+
" prospects[].app_url: product URL for operator inspection",
|
|
6430
|
+
" meta.total_count: total matching suspect prospects",
|
|
6431
|
+
"",
|
|
6432
|
+
"API:",
|
|
6433
|
+
" GET /api/v1/accounts/:account_id/prospects.json?data_quality=missing_certified_company",
|
|
6434
|
+
"",
|
|
6435
|
+
"Examples:",
|
|
6436
|
+
" audienti prospects check --motion <motn_id> --all --csv",
|
|
6437
|
+
" audienti prospects check --assigned-user me --json"
|
|
6438
|
+
].join("\n")],
|
|
6439
|
+
|
|
4819
6440
|
["prospects assign", [
|
|
4820
6441
|
"Usage:",
|
|
4821
6442
|
` ${PROSPECTS_ASSIGN_USAGE.slice("Usage: ".length)}`,
|
|
@@ -4839,6 +6460,27 @@ const HELP_TOPICS = new Map([
|
|
|
4839
6460
|
" }"
|
|
4840
6461
|
].join("\n")],
|
|
4841
6462
|
|
|
6463
|
+
["prospects set-status", [
|
|
6464
|
+
"Usage:",
|
|
6465
|
+
` ${PROSPECTS_SET_STATUS_USAGE.slice("Usage: ".length)}`,
|
|
6466
|
+
"",
|
|
6467
|
+
"Status: implemented",
|
|
6468
|
+
"",
|
|
6469
|
+
"Purpose:",
|
|
6470
|
+
" Set the account-scoped prospect disposition directly, without routing through a motion.",
|
|
6471
|
+
"",
|
|
6472
|
+
"Input shape:",
|
|
6473
|
+
" status: active | nurture | non_responsive | not_fit | rejected",
|
|
6474
|
+
"",
|
|
6475
|
+
"Behavior:",
|
|
6476
|
+
" active restores the prospect, rejected uses the rejection/DNC path, and nurture/non_responsive/not_fit use the shared inactive disposition path.",
|
|
6477
|
+
"",
|
|
6478
|
+
"API:",
|
|
6479
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/restore.json",
|
|
6480
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/reject.json",
|
|
6481
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/nurture.json"
|
|
6482
|
+
].join("\n")],
|
|
6483
|
+
|
|
4842
6484
|
["prospects show", [
|
|
4843
6485
|
"Usage:",
|
|
4844
6486
|
" audienti prospects show <prsp_id> [--json] [--account <acct_id>]",
|
|
@@ -4852,6 +6494,78 @@ const HELP_TOPICS = new Map([
|
|
|
4852
6494
|
" GET /api/v1/accounts/:account_id/prospects/:id.json"
|
|
4853
6495
|
].join("\n")],
|
|
4854
6496
|
|
|
6497
|
+
["prospects reject", [
|
|
6498
|
+
"Usage:",
|
|
6499
|
+
` ${PROSPECTS_REJECT_USAGE.slice("Usage: ".length)}`,
|
|
6500
|
+
"",
|
|
6501
|
+
"Status: implemented",
|
|
6502
|
+
"",
|
|
6503
|
+
"Purpose:",
|
|
6504
|
+
" Reject one prospect through the shared disposition and account DNC path.",
|
|
6505
|
+
"",
|
|
6506
|
+
"API:",
|
|
6507
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/reject.json"
|
|
6508
|
+
].join("\n")],
|
|
6509
|
+
|
|
6510
|
+
["prospects nurture", [
|
|
6511
|
+
"Usage:",
|
|
6512
|
+
` ${PROSPECTS_NURTURE_USAGE.slice("Usage: ".length)}`,
|
|
6513
|
+
"",
|
|
6514
|
+
"Status: implemented",
|
|
6515
|
+
"",
|
|
6516
|
+
"Purpose:",
|
|
6517
|
+
" Move one prospect to an inactive nurture disposition through the shared disposition path.",
|
|
6518
|
+
"",
|
|
6519
|
+
"Input shape:",
|
|
6520
|
+
" reason: nurture | non_responsive | not_fit. Defaults to nurture.",
|
|
6521
|
+
"",
|
|
6522
|
+
"API:",
|
|
6523
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/nurture.json"
|
|
6524
|
+
].join("\n")],
|
|
6525
|
+
|
|
6526
|
+
["prospects restore", [
|
|
6527
|
+
"Usage:",
|
|
6528
|
+
` ${PROSPECTS_RESTORE_USAGE.slice("Usage: ".length)}`,
|
|
6529
|
+
"",
|
|
6530
|
+
"Status: implemented",
|
|
6531
|
+
"",
|
|
6532
|
+
"Purpose:",
|
|
6533
|
+
" Restore one rejected or inactive prospect through the shared disposition path.",
|
|
6534
|
+
"",
|
|
6535
|
+
"API:",
|
|
6536
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/restore.json"
|
|
6537
|
+
].join("\n")],
|
|
6538
|
+
|
|
6539
|
+
["prospects lock", [
|
|
6540
|
+
"Usage:",
|
|
6541
|
+
` ${PROSPECTS_LOCK_USAGE.slice("Usage: ".length)}`,
|
|
6542
|
+
"",
|
|
6543
|
+
"Status: implemented",
|
|
6544
|
+
"",
|
|
6545
|
+
"Purpose:",
|
|
6546
|
+
" Lock one prospect immediately through the same protected-relationship path used by the prospect page.",
|
|
6547
|
+
"",
|
|
6548
|
+
"Input shape:",
|
|
6549
|
+
" kind: protected_relationship | company_policy. Defaults to protected_relationship.",
|
|
6550
|
+
" note: optional operator note explaining the lock.",
|
|
6551
|
+
"",
|
|
6552
|
+
"API:",
|
|
6553
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/lock.json"
|
|
6554
|
+
].join("\n")],
|
|
6555
|
+
|
|
6556
|
+
["prospects unlock", [
|
|
6557
|
+
"Usage:",
|
|
6558
|
+
` ${PROSPECTS_UNLOCK_USAGE.slice("Usage: ".length)}`,
|
|
6559
|
+
"",
|
|
6560
|
+
"Status: implemented",
|
|
6561
|
+
"",
|
|
6562
|
+
"Purpose:",
|
|
6563
|
+
" Clear one prospect lock through the same unlock path used by the prospect page.",
|
|
6564
|
+
"",
|
|
6565
|
+
"API:",
|
|
6566
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/unlock.json"
|
|
6567
|
+
].join("\n")],
|
|
6568
|
+
|
|
4855
6569
|
["prospects timeline", [
|
|
4856
6570
|
"Usage:",
|
|
4857
6571
|
" audienti prospects timeline <prsp_id> [--json] [--types <post,comment,reaction>] [--limit <n>] [--account <acct_id>]",
|
|
@@ -5209,26 +6923,6 @@ const HELP_TOPICS = new Map([
|
|
|
5209
6923
|
" GET /api/v1/accounts/:account_id/prospect_imports/:id.json"
|
|
5210
6924
|
].join("\n")],
|
|
5211
6925
|
|
|
5212
|
-
["prospects disposition", [
|
|
5213
|
-
"Usage:",
|
|
5214
|
-
" audienti prospects disposition <prsp_id> --payload <file.json> [--account <acct_id>]",
|
|
5215
|
-
"",
|
|
5216
|
-
"Status: planned",
|
|
5217
|
-
"",
|
|
5218
|
-
"Input shape:",
|
|
5219
|
-
" action: defer | nurture | reject | restore",
|
|
5220
|
-
" reason: string | optional",
|
|
5221
|
-
" delay_until: ISO8601 datetime | optional",
|
|
5222
|
-
" note: string | optional",
|
|
5223
|
-
"",
|
|
5224
|
-
"JSON example:",
|
|
5225
|
-
" {",
|
|
5226
|
-
" \"action\": \"nurture\",",
|
|
5227
|
-
" \"reason\": \"not_a_fit\",",
|
|
5228
|
-
" \"note\": \"Not a fit for this motion right now.\"",
|
|
5229
|
-
" }"
|
|
5230
|
-
].join("\n")],
|
|
5231
|
-
|
|
5232
6926
|
["tools", [
|
|
5233
6927
|
"Usage:",
|
|
5234
6928
|
" audienti tools get <email|phone> --url <linkedin_url> [--json]",
|
|
@@ -5358,6 +7052,7 @@ const HELP_TOPICS = new Map([
|
|
|
5358
7052
|
["analytics", [
|
|
5359
7053
|
"Usage:",
|
|
5360
7054
|
" audienti analytics prospects [--window 24h] [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--motion <motn_id>] [--user <account_user_id|email|name|me>] [--json]",
|
|
7055
|
+
" audienti analytics dashboard [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--play-tag <tag>] [--motion <motn_id>] [--json]",
|
|
5361
7056
|
" audienti analytics prospects cohort-analysis [--weeks <n>] [--window 24h] [--motion <motn_id>] [--user <account_user_id|email|name|me>] [--json]",
|
|
5362
7057
|
" audienti analytics users [--user <account_user_id|email|name|me>] [--window 30d | --start YYYY-MM-DD --end YYYY-MM-DD] [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--motion <motn_id>] [--platform <linkedin|email|gmail>] [--json]",
|
|
5363
7058
|
" audienti analytics visibility [--window 24h] [--user <account_user_id|email|name|me>] [--json]",
|
|
@@ -5371,13 +7066,42 @@ const HELP_TOPICS = new Map([
|
|
|
5371
7066
|
" --start <YYYY-MM-DD> --end <YYYY-MM-DD> For user analytics, select the events.created_at activity range instead of --window.",
|
|
5372
7067
|
" --cohort-start <YYYY-MM-DD> --cohort-end <YYYY-MM-DD> Select the AccountProspect.created_at cohort while --window or --start/--end selects the activity period.",
|
|
5373
7068
|
" --motion <motn_id> For prospect and user analytics, filter AccountProspect.motion_id to one motion/play.",
|
|
7069
|
+
" --play-tag <tag> For dashboard analytics, filter to motions/lists tagged with a campaign tag.",
|
|
5374
7070
|
" --provenance <source> Optional lower-level AccountProspect.intake_source filter.",
|
|
5375
7071
|
" --platform <linkedin|email|gmail> For user analytics, filter events.platform. --channel is accepted as an alias.",
|
|
5376
7072
|
" cohort-analysis loops over recent weekly AccountProspect.created_at cohorts and compares their current stages.",
|
|
5377
7073
|
" --user <account_user_id|email|name|me> Narrow analytics to one account user. For prospect analytics, this means prospects assigned to that account user. Email/name partials are accepted when they match exactly one account user.",
|
|
5378
7074
|
"",
|
|
5379
7075
|
"Output:",
|
|
5380
|
-
" Account-scoped analytics for prospects, users, visibility engagement, and ContentOps publishing."
|
|
7076
|
+
" Account-scoped analytics for prospects, campaign dashboard counts, users, visibility engagement, and ContentOps publishing."
|
|
7077
|
+
].join("\n")],
|
|
7078
|
+
|
|
7079
|
+
["analytics dashboard", [
|
|
7080
|
+
"Usage:",
|
|
7081
|
+
` ${ANALYTICS_DASHBOARD_USAGE.slice("Usage: ".length)}`,
|
|
7082
|
+
"",
|
|
7083
|
+
"Status: implemented",
|
|
7084
|
+
"",
|
|
7085
|
+
"Purpose:",
|
|
7086
|
+
" Return the dashboard outreach read model through the CLI, including distinct company target counts for a motion, tag, offer, ICP, or user-filtered cohort.",
|
|
7087
|
+
"",
|
|
7088
|
+
"Options:",
|
|
7089
|
+
" --cohort-start <YYYY-MM-DD> --cohort-end <YYYY-MM-DD> Select the AccountProspect.created_at cohort.",
|
|
7090
|
+
" --play-tag <tag> Filter to motions/lists tagged with a campaign tag. --tag is accepted as an alias.",
|
|
7091
|
+
" --motion <motn_id> Filter to one motion/play.",
|
|
7092
|
+
" --offer <offr_id> Filter to one offer.",
|
|
7093
|
+
" --icp <icp_id> Filter to one ICP.",
|
|
7094
|
+
" --user <account_user_id|email|name|me> Filter to prospects assigned to one account user.",
|
|
7095
|
+
"",
|
|
7096
|
+
"Output shape:",
|
|
7097
|
+
" cohort_size: people in the selected cohort",
|
|
7098
|
+
" cohort_company_target_count: distinct company targets in that cohort",
|
|
7099
|
+
" cohort_people_per_company_average: people per company target",
|
|
7100
|
+
" active_cohort_count and active_cohort_company_target_count: still-active campaign cohort counts",
|
|
7101
|
+
" pipeline_stage_counts[]: current stage distribution",
|
|
7102
|
+
"",
|
|
7103
|
+
"API:",
|
|
7104
|
+
" GET /api/v1/accounts/:account_id/analytics/dashboard.json"
|
|
5381
7105
|
].join("\n")],
|
|
5382
7106
|
|
|
5383
7107
|
["analytics prospects", [
|
|
@@ -5529,6 +7253,7 @@ const HELP_TOPICS = new Map([
|
|
|
5529
7253
|
" audienti motions pause <motn_id>",
|
|
5530
7254
|
" audienti motions delete <motn_id> --confirm yes",
|
|
5531
7255
|
" audienti motions status <motn_id>",
|
|
7256
|
+
" audienti motions run-discovery <motn_id>",
|
|
5532
7257
|
"",
|
|
5533
7258
|
"3. Add a new prospect from LinkedIn and poll enrichment",
|
|
5534
7259
|
" audienti lists create --name \"Target list\"",
|
|
@@ -5550,6 +7275,12 @@ const HELP_TOPICS = new Map([
|
|
|
5550
7275
|
" audienti prospects add-profile <prsp_id> --url prospect@example.com",
|
|
5551
7276
|
" audienti prospects report-bad-profile <prsp_id> <prof_id>",
|
|
5552
7277
|
" audienti prospects add-note <prsp_id> --type steer --message \"Meeting will not happen\" --engagement-type action.meeting.canceled",
|
|
7278
|
+
" audienti prospects set-status <prsp_id> --status not_fit",
|
|
7279
|
+
" audienti prospects lock <prsp_id> --note \"Emergency hold\"",
|
|
7280
|
+
" audienti prospects reject <prsp_id>",
|
|
7281
|
+
" audienti prospects nurture <prsp_id>",
|
|
7282
|
+
" audienti prospects restore <prsp_id>",
|
|
7283
|
+
" audienti prospects unlock <prsp_id>",
|
|
5553
7284
|
" audienti prospects sequence-preview <prsp_id>",
|
|
5554
7285
|
" audienti writer test-run <prsp_id>",
|
|
5555
7286
|
" audienti prospects sequence-export <prsp_id> --csv",
|
|
@@ -5567,6 +7298,7 @@ const HELP_TOPICS = new Map([
|
|
|
5567
7298
|
"7. Inspect account analytics",
|
|
5568
7299
|
" audienti users activity me --window 7d",
|
|
5569
7300
|
" audienti analytics prospects --window 24h",
|
|
7301
|
+
" audienti analytics dashboard --play-tag wine_campaign",
|
|
5570
7302
|
" audienti analytics users --user me --window 30d",
|
|
5571
7303
|
" audienti analytics visibility --window 24h --user me",
|
|
5572
7304
|
" audienti analytics content --window week",
|
|
@@ -5578,7 +7310,6 @@ const HELP_TOPICS = new Map([
|
|
|
5578
7310
|
" Prefer prospects import for new LinkedIn people and add-prospects commands for records that already exist.",
|
|
5579
7311
|
"",
|
|
5580
7312
|
"Current gaps to plan around:",
|
|
5581
|
-
" Prospect disposition still lacks a dedicated CLI mutation.",
|
|
5582
7313
|
" Operator outcome writeback is implemented for prospect rows, not visibility rows."
|
|
5583
7314
|
].join("\n")]
|
|
5584
7315
|
]);
|