@audienti/cli 0.1.11 → 0.1.15
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 +37 -0
- package/README.md +25 -0
- package/package.json +1 -1
- package/src/api-client.js +104 -0
- package/src/cli.js +1327 -98
package/src/cli.js
CHANGED
|
@@ -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",
|
|
@@ -31,17 +33,34 @@ const PROSPECTS_ADD_STEER_USAGE = "Usage: audienti prospects add-steer <prsp_id>
|
|
|
31
33
|
const PROSPECTS_ADD_PROFILE_USAGE = "Usage: audienti prospects add-profile <prsp_id> --url <profile_url|email|phone> [--json] [--account <acct_id>]";
|
|
32
34
|
const PROSPECTS_REPORT_BAD_PROFILE_USAGE = "Usage: audienti prospects report-bad-profile <prsp_id> <prof_id|citation_id> [--json] [--account <acct_id>]";
|
|
33
35
|
const PROSPECTS_ASSIGN_USAGE = "Usage: audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json] [--account <acct_id>]";
|
|
36
|
+
const PROSPECTS_REJECT_USAGE = "Usage: audienti prospects reject <prsp_id> [--json] [--account <acct_id>]";
|
|
37
|
+
const PROSPECTS_NURTURE_USAGE = "Usage: audienti prospects nurture <prsp_id> [--reason <nurture|non_responsive|not_fit>] [--json] [--account <acct_id>]";
|
|
38
|
+
const PROSPECTS_RESTORE_USAGE = "Usage: audienti prospects restore <prsp_id> [--json] [--account <acct_id>]";
|
|
39
|
+
const PROSPECTS_CHECK_USAGE = "Usage: audienti prospects check [--json|--csv] [filters] [--account <acct_id>]";
|
|
34
40
|
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>]";
|
|
35
41
|
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>]";
|
|
42
|
+
const OFFERS_SHOW_USAGE = "Usage: audienti offers show <offr_id> [--json] [--account <acct_id>]";
|
|
43
|
+
const OFFERS_UPDATE_USAGE = "Usage: audienti offers update <offr_id> [--name <text>] [--description <text>] [--url <url>] [--json] [--account <acct_id>]";
|
|
44
|
+
const OFFERS_DELETE_USAGE = "Usage: audienti offers delete <offr_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]";
|
|
36
45
|
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
46
|
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>]";
|
|
47
|
+
const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> [--status <draft|preparing|active|paused|archived>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]";
|
|
48
|
+
const MOTIONS_ADD_TAG_USAGE = "Usage: audienti motions add-tag <motn_id> <tag> [--json] [--account <acct_id>]";
|
|
49
|
+
const MOTIONS_REMOVE_TAG_USAGE = "Usage: audienti motions remove-tag <motn_id> <tag> [--json] [--account <acct_id>]";
|
|
39
50
|
const MOTIONS_DELETE_USAGE = "Usage: audienti motions delete <motn_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]";
|
|
40
51
|
const MOTIONS_CLONE_USAGE = "Usage: audienti motions clone <motn_id> --name <text> [--json] [--account <acct_id>]";
|
|
41
52
|
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>]";
|
|
53
|
+
const MOTIONS_RUN_DISCOVERY_USAGE = "Usage: audienti motions run-discovery <motn_id> [--target-count <n>] [--json] [--account <acct_id>]";
|
|
54
|
+
const ICPS_SHOW_USAGE = "Usage: audienti icps show <icp_id> [--json] [--account <acct_id>]";
|
|
55
|
+
const ICPS_UPDATE_USAGE = "Usage: audienti icps update <icp_id> [--name <text>] [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]";
|
|
56
|
+
const ICPS_ADD_TAG_USAGE = "Usage: audienti icps add-tag <icp_id> <tag> [--json] [--account <acct_id>]";
|
|
57
|
+
const ICPS_REMOVE_TAG_USAGE = "Usage: audienti icps remove-tag <icp_id> <tag> [--json] [--account <acct_id>]";
|
|
58
|
+
const LISTS_ADD_TAG_USAGE = "Usage: audienti lists add-tag <list_id> <tag> [--json] [--account <acct_id>]";
|
|
59
|
+
const LISTS_REMOVE_TAG_USAGE = "Usage: audienti lists remove-tag <list_id> <tag> [--json] [--account <acct_id>]";
|
|
42
60
|
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
61
|
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
62
|
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>]";
|
|
63
|
+
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
64
|
const COHORT_STAGE_ORDER = [
|
|
46
65
|
"identified",
|
|
47
66
|
"pre_connect",
|
|
@@ -120,20 +139,32 @@ async function dispatch(argv, context) {
|
|
|
120
139
|
if (normalizedResource === "auth" && action === "status") return authStatus(rest, context, { accountOverride });
|
|
121
140
|
if (normalizedResource === "auth" && action === "logout") return authLogout(rest, context);
|
|
122
141
|
if (normalizedResource === "config" && action === "list") return configList(rest, context);
|
|
142
|
+
if (normalizedResource === "update" && action === "check") return updateCheck(rest, context);
|
|
123
143
|
if (normalizedResource === "accounts" && action === "list") return accountsList(rest, context, { accountOverride });
|
|
124
144
|
if (normalizedResource === "accounts" && action === "select") return accountsSelect(rest, context);
|
|
125
145
|
if (normalizedResource === "users" && action === "list") return usersList(rest, context, { accountOverride });
|
|
126
146
|
if (normalizedResource === "users" && action === "select") return usersSelect(rest, context, { accountOverride });
|
|
127
147
|
if (normalizedResource === "users" && action === "activity") return usersActivity(rest, context, { accountOverride });
|
|
128
148
|
if (normalizedResource === "offers" && action === "list") return offersList(rest, context, { accountOverride });
|
|
149
|
+
if (normalizedResource === "offers" && action === "show") return offersShow(rest, context, { accountOverride });
|
|
129
150
|
if (normalizedResource === "offers" && action === "create") return offersCreate(rest, context, { accountOverride });
|
|
151
|
+
if (normalizedResource === "offers" && action === "update") return offersUpdate(rest, context, { accountOverride });
|
|
152
|
+
if (normalizedResource === "offers" && action === "delete") return offersDelete(rest, context, { accountOverride });
|
|
130
153
|
if (normalizedResource === "icps" && action === "list") return icpsList(rest, context, { accountOverride });
|
|
154
|
+
if (normalizedResource === "icps" && action === "show") return icpsShow(rest, context, { accountOverride });
|
|
131
155
|
if (normalizedResource === "icps" && action === "create") return icpsCreate(rest, context, { accountOverride });
|
|
156
|
+
if (normalizedResource === "icps" && action === "update") return icpsUpdate(rest, context, { accountOverride });
|
|
157
|
+
if (normalizedResource === "icps" && action === "add-tag") return icpsTagMutation("add", rest, context, { accountOverride });
|
|
158
|
+
if (normalizedResource === "icps" && action === "remove-tag") return icpsTagMutation("remove", rest, context, { accountOverride });
|
|
132
159
|
if (normalizedResource === "companies" && action === "search") return companiesSearch(rest, context, { accountOverride });
|
|
160
|
+
if (normalizedResource === "tags" && action === "list") return tagsList(rest, context, { accountOverride });
|
|
161
|
+
if (normalizedResource === "tags" && action === "show") return tagsShow(rest, context, { accountOverride });
|
|
133
162
|
if (normalizedResource === "lists" && action === "list") return listsList(rest, context, { accountOverride });
|
|
134
163
|
if (normalizedResource === "lists" && action === "create") return listsCreate(rest, context, { accountOverride });
|
|
135
164
|
if (normalizedResource === "lists" && action === "show") return listsShow(rest, context, { accountOverride });
|
|
136
165
|
if (normalizedResource === "lists" && action === "update") return listsUpdate(rest, context, { accountOverride });
|
|
166
|
+
if (normalizedResource === "lists" && action === "add-tag") return listsTagMutation("add", rest, context, { accountOverride });
|
|
167
|
+
if (normalizedResource === "lists" && action === "remove-tag") return listsTagMutation("remove", rest, context, { accountOverride });
|
|
137
168
|
if (normalizedResource === "lists" && action === "delete") return listsDelete(rest, context, { accountOverride });
|
|
138
169
|
if (normalizedResource === "lists" && action === "prospects") return listProspects(rest, context, { accountOverride });
|
|
139
170
|
if (normalizedResource === "lists" && action === "add-prospects") return listsAddProspects(rest, context, { accountOverride });
|
|
@@ -146,13 +177,20 @@ async function dispatch(argv, context) {
|
|
|
146
177
|
if (normalizedResource === "motions" && action === "add-prospects") return motionsAddProspects(rest, context, { accountOverride });
|
|
147
178
|
if (normalizedResource === "motions" && action === "create") return motionsCreate(rest, context, { accountOverride });
|
|
148
179
|
if (normalizedResource === "motions" && action === "update") return motionsUpdate(rest, context, { accountOverride });
|
|
180
|
+
if (normalizedResource === "motions" && action === "add-tag") return motionsTagMutation("add", rest, context, { accountOverride });
|
|
181
|
+
if (normalizedResource === "motions" && action === "remove-tag") return motionsTagMutation("remove", rest, context, { accountOverride });
|
|
149
182
|
if (normalizedResource === "motions" && ["activate", "pause", "archive"].includes(action)) return motionsStatusShortcut(action, rest, context, { accountOverride });
|
|
150
183
|
if (normalizedResource === "motions" && action === "delete") return motionsDelete(rest, context, { accountOverride });
|
|
151
184
|
if (normalizedResource === "motions" && action === "clone") return motionsClone(rest, context, { accountOverride });
|
|
152
185
|
if (normalizedResource === "motions" && action === "move-prospects") return motionsMoveProspects(rest, context, { accountOverride });
|
|
186
|
+
if (normalizedResource === "motions" && action === "run-discovery") return motionsRunDiscovery(rest, context, { accountOverride });
|
|
153
187
|
if (normalizedResource === "prospects" && action === "list") return prospectsList(rest, context, { accountOverride });
|
|
188
|
+
if (normalizedResource === "prospects" && action === "check") return prospectsCheck(rest, context, { accountOverride });
|
|
154
189
|
if (normalizedResource === "prospects" && action === "show") return prospectsShow(rest, context, { accountOverride });
|
|
155
190
|
if (normalizedResource === "prospects" && action === "assign") return prospectsAssign(rest, context, { accountOverride });
|
|
191
|
+
if (normalizedResource === "prospects" && action === "reject") return prospectsDisposition("reject", rest, context, { accountOverride });
|
|
192
|
+
if (normalizedResource === "prospects" && action === "nurture") return prospectsDisposition("nurture", rest, context, { accountOverride });
|
|
193
|
+
if (normalizedResource === "prospects" && action === "restore") return prospectsDisposition("restore", rest, context, { accountOverride });
|
|
156
194
|
if (normalizedResource === "prospects" && action === "timeline") return prospectsTimeline(rest, context, { accountOverride });
|
|
157
195
|
if (normalizedResource === "prospects" && action === "message-types") return prospectsMessageTypes(rest, context, { accountOverride });
|
|
158
196
|
if (normalizedResource === "prospects" && action === "write") return prospectsWrite(rest, context, { accountOverride });
|
|
@@ -174,6 +212,7 @@ async function dispatch(argv, context) {
|
|
|
174
212
|
if (normalizedResource === "analytics" && ["users", "user"].includes(action)) return analyticsUsers(rest, context, { accountOverride });
|
|
175
213
|
if (normalizedResource === "analytics" && ["visibility", "visops"].includes(action)) return analyticsVisibility(rest, context, { accountOverride });
|
|
176
214
|
if (normalizedResource === "analytics" && action === "content") return analyticsContent(rest, context, { accountOverride });
|
|
215
|
+
if (normalizedResource === "analytics" && ["dashboard", "campaign", "campaigns"].includes(action)) return analyticsDashboard(rest, context, { accountOverride });
|
|
177
216
|
|
|
178
217
|
throw new CommandError(usage(), { exitCode: resource ? 1 : 0 });
|
|
179
218
|
}
|
|
@@ -332,6 +371,51 @@ async function configList(args, context) {
|
|
|
332
371
|
}
|
|
333
372
|
}
|
|
334
373
|
|
|
374
|
+
async function updateCheck(args, context) {
|
|
375
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
376
|
+
...jsonOptions(),
|
|
377
|
+
registry: { type: "string" }
|
|
378
|
+
});
|
|
379
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti update check [--json] [--registry <url>]");
|
|
380
|
+
|
|
381
|
+
const localPackage = await readLocalPackageMetadata();
|
|
382
|
+
let payload;
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const latestVersion = await fetchLatestPackageVersion({
|
|
386
|
+
fetchImpl: context.fetchImpl,
|
|
387
|
+
registry: values.registry
|
|
388
|
+
});
|
|
389
|
+
const updateAvailable = compareVersions(localPackage.version, latestVersion) < 0;
|
|
390
|
+
payload = updateCheckPayload({
|
|
391
|
+
currentVersion: localPackage.version,
|
|
392
|
+
latestVersion,
|
|
393
|
+
status: updateAvailable ? "update_available" : "current",
|
|
394
|
+
updateAvailable,
|
|
395
|
+
registry: values.registry || DEFAULT_NPM_REGISTRY,
|
|
396
|
+
now: context.now()
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
payload = updateCheckPayload({
|
|
400
|
+
currentVersion: localPackage.version,
|
|
401
|
+
latestVersion: null,
|
|
402
|
+
status: "unknown",
|
|
403
|
+
updateAvailable: null,
|
|
404
|
+
registry: values.registry || DEFAULT_NPM_REGISTRY,
|
|
405
|
+
error: error.message,
|
|
406
|
+
now: context.now()
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (values.json) {
|
|
411
|
+
writeJson(context.stdout, payload);
|
|
412
|
+
return payload.status === "unknown" ? 1 : 0;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
renderUpdateCheck(payload, context);
|
|
416
|
+
return payload.status === "unknown" ? 1 : 0;
|
|
417
|
+
}
|
|
418
|
+
|
|
335
419
|
async function accountsList(args, context, { accountOverride } = {}) {
|
|
336
420
|
const { values, positionals } = parseCommandArgs(args, {
|
|
337
421
|
json: { type: "boolean" }
|
|
@@ -452,11 +536,14 @@ function accountUserLabel(accountUser) {
|
|
|
452
536
|
}
|
|
453
537
|
|
|
454
538
|
async function listsList(args, context, { accountOverride } = {}) {
|
|
455
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
456
|
-
|
|
539
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
540
|
+
...jsonOptions(),
|
|
541
|
+
tag: { type: "string" }
|
|
542
|
+
});
|
|
543
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti lists list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
457
544
|
|
|
458
545
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
459
|
-
const lists = await client.lists(accountId);
|
|
546
|
+
const lists = filterRecordsByTag(await client.lists(accountId), values.tag, "tags");
|
|
460
547
|
if (values.json) return writeJson(context.stdout, lists);
|
|
461
548
|
|
|
462
549
|
renderLists(lists, context);
|
|
@@ -533,6 +620,17 @@ async function offersList(args, context, { accountOverride } = {}) {
|
|
|
533
620
|
renderOffers(offers, context);
|
|
534
621
|
}
|
|
535
622
|
|
|
623
|
+
async function offersShow(args, context, { accountOverride } = {}) {
|
|
624
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
625
|
+
if (positionals.length !== 1) throw new CommandError(OFFERS_SHOW_USAGE);
|
|
626
|
+
|
|
627
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
628
|
+
const offer = await client.offer(accountId, positionals[0]);
|
|
629
|
+
if (values.json) return writeJson(context.stdout, offer);
|
|
630
|
+
|
|
631
|
+
renderOffer(offer, context);
|
|
632
|
+
}
|
|
633
|
+
|
|
536
634
|
async function offersCreate(args, context, { accountOverride } = {}) {
|
|
537
635
|
const { values, positionals } = parseCommandArgs(args, {
|
|
538
636
|
...jsonOptions(),
|
|
@@ -559,27 +657,85 @@ async function offersCreate(args, context, { accountOverride } = {}) {
|
|
|
559
657
|
if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
|
|
560
658
|
}
|
|
561
659
|
|
|
660
|
+
async function offersUpdate(args, context, { accountOverride } = {}) {
|
|
661
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
662
|
+
...jsonOptions(),
|
|
663
|
+
name: { type: "string" },
|
|
664
|
+
description: { type: "string" },
|
|
665
|
+
url: { type: "string" }
|
|
666
|
+
});
|
|
667
|
+
const hasUpdateField = values.name || values.description !== undefined || values.url !== undefined;
|
|
668
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
669
|
+
throw new CommandError(OFFERS_UPDATE_USAGE);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
673
|
+
const offer = await client.updateOffer(accountId, positionals[0], {
|
|
674
|
+
offer: compactObject({
|
|
675
|
+
name: values.name,
|
|
676
|
+
description: values.description,
|
|
677
|
+
url: values.url
|
|
678
|
+
})
|
|
679
|
+
});
|
|
680
|
+
if (values.json) return writeJson(context.stdout, offer);
|
|
681
|
+
|
|
682
|
+
writeLine(context.stdout, `Updated offer ${display(offer?.name)} (${display(offer?.prefix_id)}).`);
|
|
683
|
+
renderOffer(offer, context);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
async function offersDelete(args, context, { accountOverride } = {}) {
|
|
687
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
688
|
+
...jsonOptions(),
|
|
689
|
+
confirm: { type: "string" }
|
|
690
|
+
});
|
|
691
|
+
const normalizedConfirm = String(values.confirm || "").trim().toLowerCase();
|
|
692
|
+
if (positionals.length !== 1 || !DELETE_CONFIRMATION_VALUES.has(normalizedConfirm)) {
|
|
693
|
+
throw new CommandError(OFFERS_DELETE_USAGE);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
697
|
+
const payload = await client.deleteOffer(accountId, positionals[0]);
|
|
698
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
699
|
+
|
|
700
|
+
writeLine(context.stdout, `Deleted offer ${display(payload?.name)} (${display(payload?.prefix_id)}).`);
|
|
701
|
+
}
|
|
702
|
+
|
|
562
703
|
async function icpsList(args, context, { accountOverride } = {}) {
|
|
563
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
564
|
-
|
|
704
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
705
|
+
...jsonOptions(),
|
|
706
|
+
tag: { type: "string" }
|
|
707
|
+
});
|
|
708
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti icps list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
565
709
|
|
|
566
710
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
567
|
-
const icps = await client.icps(accountId);
|
|
711
|
+
const icps = filterRecordsByTag(await client.icps(accountId), values.tag, "tags");
|
|
568
712
|
if (values.json) return writeJson(context.stdout, icps);
|
|
569
713
|
|
|
570
714
|
renderIcps(icps, context);
|
|
571
715
|
}
|
|
572
716
|
|
|
717
|
+
async function icpsShow(args, context, { accountOverride } = {}) {
|
|
718
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
719
|
+
if (positionals.length !== 1) throw new CommandError(ICPS_SHOW_USAGE);
|
|
720
|
+
|
|
721
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
722
|
+
const icp = await client.icp(accountId, positionals[0]);
|
|
723
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
724
|
+
|
|
725
|
+
renderIcp(icp, context);
|
|
726
|
+
}
|
|
727
|
+
|
|
573
728
|
async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
574
729
|
const { values, positionals } = parseCommandArgs(args, {
|
|
575
730
|
...jsonOptions(),
|
|
576
731
|
payload: { type: "string" },
|
|
577
732
|
name: { type: "string" },
|
|
578
733
|
notes: { type: "string" },
|
|
734
|
+
tags: { type: "string" },
|
|
579
735
|
"discovery-keyword": { type: "string" }
|
|
580
736
|
});
|
|
581
737
|
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>]");
|
|
738
|
+
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
739
|
}
|
|
584
740
|
|
|
585
741
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -589,9 +745,58 @@ async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
|
589
745
|
|
|
590
746
|
writeLine(context.stdout, `Created ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
591
747
|
if (icp?.notes) writeLine(context.stdout, `Notes: ${icp.notes}`);
|
|
748
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
592
749
|
if (icp?.discovery_keyword) writeLine(context.stdout, `Discovery keyword: ${icp.discovery_keyword}`);
|
|
593
750
|
}
|
|
594
751
|
|
|
752
|
+
async function icpsUpdate(args, context, { accountOverride } = {}) {
|
|
753
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
754
|
+
...jsonOptions(),
|
|
755
|
+
name: { type: "string" },
|
|
756
|
+
notes: { type: "string" },
|
|
757
|
+
tags: { type: "string" },
|
|
758
|
+
"discovery-keyword": { type: "string" }
|
|
759
|
+
});
|
|
760
|
+
const hasUpdateField = values.name || values.notes !== undefined || values.tags !== undefined || values["discovery-keyword"] !== undefined;
|
|
761
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
762
|
+
throw new CommandError(ICPS_UPDATE_USAGE);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
766
|
+
const icp = await client.updateIcp(accountId, positionals[0], {
|
|
767
|
+
icp: compactObject({
|
|
768
|
+
name: values.name,
|
|
769
|
+
notes: values.notes,
|
|
770
|
+
discovery_keyword: values["discovery-keyword"],
|
|
771
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined
|
|
772
|
+
})
|
|
773
|
+
});
|
|
774
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
775
|
+
|
|
776
|
+
writeLine(context.stdout, `Updated ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
777
|
+
renderIcp(icp, context);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
async function icpsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
781
|
+
const usageText = action === "add" ? ICPS_ADD_TAG_USAGE : ICPS_REMOVE_TAG_USAGE;
|
|
782
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
783
|
+
if (positionals.length !== 2) {
|
|
784
|
+
throw new CommandError(usageText);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
const [icpId, tag] = positionals;
|
|
788
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
789
|
+
const icp = action === "add" ?
|
|
790
|
+
await client.addIcpTag(accountId, icpId, { tag }) :
|
|
791
|
+
await client.removeIcpTag(accountId, icpId, { tag });
|
|
792
|
+
if (values.json) return writeJson(context.stdout, icp);
|
|
793
|
+
|
|
794
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
795
|
+
const preposition = action === "add" ? "to" : "from";
|
|
796
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
797
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
798
|
+
}
|
|
799
|
+
|
|
595
800
|
async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
596
801
|
const { values, positionals } = parseCommandArgs(args, {
|
|
597
802
|
...jsonOptions(),
|
|
@@ -608,16 +813,47 @@ async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
|
608
813
|
renderCompanies(payload, context);
|
|
609
814
|
}
|
|
610
815
|
|
|
816
|
+
async function tagsList(args, context, { accountOverride } = {}) {
|
|
817
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
818
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti tags list [--json] [--account <acct_id>]");
|
|
819
|
+
|
|
820
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
821
|
+
const payload = await client.tags(accountId);
|
|
822
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
823
|
+
|
|
824
|
+
renderTags(payload, context);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
async function tagsShow(args, context, { accountOverride } = {}) {
|
|
828
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
829
|
+
if (positionals.length !== 1) throw new CommandError("Usage: audienti tags show <tag> [--json] [--account <acct_id>]");
|
|
830
|
+
|
|
831
|
+
const tag = tagList(positionals[0])[0];
|
|
832
|
+
if (!tag) throw new CommandError("Usage: audienti tags show <tag> [--json] [--account <acct_id>]");
|
|
833
|
+
|
|
834
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
835
|
+
const payload = {
|
|
836
|
+
tag,
|
|
837
|
+
icps: filterRecordsByTag(await client.icps(accountId), tag, "tags"),
|
|
838
|
+
lists: filterRecordsByTag(await client.lists(accountId), tag, "tags"),
|
|
839
|
+
motions: filterRecordsByTag(await client.motions(accountId), tag, "play_tags")
|
|
840
|
+
};
|
|
841
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
842
|
+
|
|
843
|
+
renderTagDetails(payload, context);
|
|
844
|
+
}
|
|
845
|
+
|
|
611
846
|
async function listsCreate(args, context, { accountOverride } = {}) {
|
|
612
847
|
const { values, positionals } = parseCommandArgs(args, {
|
|
613
848
|
...jsonOptions(),
|
|
614
849
|
name: { type: "string" },
|
|
615
850
|
description: { type: "string" },
|
|
851
|
+
tags: { type: "string" },
|
|
616
852
|
"campaign-hook": { type: "string" },
|
|
617
853
|
"audience-note": { type: "string" }
|
|
618
854
|
});
|
|
619
855
|
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>]");
|
|
856
|
+
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
857
|
}
|
|
622
858
|
|
|
623
859
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -629,6 +865,7 @@ async function listsCreate(args, context, { accountOverride } = {}) {
|
|
|
629
865
|
list: compactObject({
|
|
630
866
|
name: values.name,
|
|
631
867
|
description: values.description,
|
|
868
|
+
tags: tagList(values.tags),
|
|
632
869
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
633
870
|
})
|
|
634
871
|
});
|
|
@@ -654,13 +891,14 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
654
891
|
...jsonOptions(),
|
|
655
892
|
name: { type: "string" },
|
|
656
893
|
description: { type: "string" },
|
|
894
|
+
tags: { type: "string" },
|
|
657
895
|
"campaign-hook": { type: "string" },
|
|
658
896
|
"audience-note": { type: "string" }
|
|
659
897
|
});
|
|
660
898
|
const hasCampaignUpdate = values["campaign-hook"] || values["audience-note"];
|
|
661
|
-
const hasUpdateField = values.name || values.description || hasCampaignUpdate;
|
|
899
|
+
const hasUpdateField = values.name || values.description || values.tags !== undefined || hasCampaignUpdate;
|
|
662
900
|
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>]");
|
|
901
|
+
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
902
|
}
|
|
665
903
|
|
|
666
904
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -672,6 +910,7 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
672
910
|
list: compactObject({
|
|
673
911
|
name: values.name,
|
|
674
912
|
description: values.description,
|
|
913
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
675
914
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
676
915
|
})
|
|
677
916
|
});
|
|
@@ -681,6 +920,26 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
681
920
|
if (payload?.description) writeLine(context.stdout, `Description: ${payload.description}`);
|
|
682
921
|
}
|
|
683
922
|
|
|
923
|
+
async function listsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
924
|
+
const usageText = action === "add" ? LISTS_ADD_TAG_USAGE : LISTS_REMOVE_TAG_USAGE;
|
|
925
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
926
|
+
if (positionals.length !== 2) {
|
|
927
|
+
throw new CommandError(usageText);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const [listId, tag] = positionals;
|
|
931
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
932
|
+
const payload = action === "add" ?
|
|
933
|
+
await client.addListTag(accountId, listId, { tag }) :
|
|
934
|
+
await client.removeListTag(accountId, listId, { tag });
|
|
935
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
936
|
+
|
|
937
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
938
|
+
const preposition = action === "add" ? "to" : "from";
|
|
939
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} list ${display(payload?.name)} (${display(payload?.prefix_id)}).`);
|
|
940
|
+
if (Array.isArray(payload?.tags)) writeLine(context.stdout, `Tags: ${display(payload.tags.join(", "), "-")}`);
|
|
941
|
+
}
|
|
942
|
+
|
|
684
943
|
async function listsDelete(args, context, { accountOverride } = {}) {
|
|
685
944
|
const { values, positionals } = parseCommandArgs(args, {
|
|
686
945
|
...jsonOptions(),
|
|
@@ -780,11 +1039,14 @@ async function listsRemoveProspects(args, context, { accountOverride } = {}) {
|
|
|
780
1039
|
}
|
|
781
1040
|
|
|
782
1041
|
async function motionsList(args, context, { accountOverride } = {}) {
|
|
783
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
784
|
-
|
|
1042
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1043
|
+
...jsonOptions(),
|
|
1044
|
+
tag: { type: "string" }
|
|
1045
|
+
});
|
|
1046
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti motions list [--tag <tag>] [--json] [--account <acct_id>]");
|
|
785
1047
|
|
|
786
1048
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
787
|
-
const motions = await client.motions(accountId);
|
|
1049
|
+
const motions = filterRecordsByTag(await client.motions(accountId), values.tag, "play_tags");
|
|
788
1050
|
if (values.json) return writeJson(context.stdout, motions);
|
|
789
1051
|
|
|
790
1052
|
renderMotions(motions, context);
|
|
@@ -812,6 +1074,22 @@ async function motionsStatus(args, context, { accountOverride } = {}) {
|
|
|
812
1074
|
renderMotionStatus(status, context);
|
|
813
1075
|
}
|
|
814
1076
|
|
|
1077
|
+
async function motionsRunDiscovery(args, context, { accountOverride } = {}) {
|
|
1078
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1079
|
+
...jsonOptions(),
|
|
1080
|
+
"target-count": { type: "string" }
|
|
1081
|
+
});
|
|
1082
|
+
if (positionals.length !== 1) throw new CommandError(MOTIONS_RUN_DISCOVERY_USAGE);
|
|
1083
|
+
|
|
1084
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1085
|
+
const payload = await client.runMotionDiscovery(accountId, positionals[0], compactObject({
|
|
1086
|
+
target_count: normalizeOptionalPositiveInteger(values["target-count"], "--target-count")
|
|
1087
|
+
}));
|
|
1088
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1089
|
+
|
|
1090
|
+
renderMotionDiscoveryRun(payload, context);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
815
1093
|
async function motionsAnalytics(args, context, { accountOverride } = {}) {
|
|
816
1094
|
const { values, positionals } = parseCommandArgs(args, {
|
|
817
1095
|
...jsonOptions(),
|
|
@@ -929,13 +1207,26 @@ async function motionsDelete(args, context, { accountOverride } = {}) {
|
|
|
929
1207
|
async function motionsUpdate(args, context, { accountOverride } = {}) {
|
|
930
1208
|
const { values, positionals } = parseCommandArgs(args, {
|
|
931
1209
|
...jsonOptions(),
|
|
932
|
-
status: { type: "string" }
|
|
1210
|
+
status: { type: "string" },
|
|
1211
|
+
tags: { type: "string" }
|
|
933
1212
|
});
|
|
934
|
-
|
|
1213
|
+
const hasUpdateField = values.status || values.tags !== undefined;
|
|
1214
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
935
1215
|
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
936
1216
|
}
|
|
937
1217
|
|
|
938
|
-
|
|
1218
|
+
const normalizedStatus = normalizeMotionStatus(values.status);
|
|
1219
|
+
const motionAttributes = compactObject({
|
|
1220
|
+
status: normalizedStatus,
|
|
1221
|
+
play_tags: values.tags !== undefined ? tagList(values.tags) : undefined
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1225
|
+
const motion = await client.updateMotion(accountId, positionals[0], { motion: motionAttributes });
|
|
1226
|
+
if (values.json) return writeJson(context.stdout, motion);
|
|
1227
|
+
|
|
1228
|
+
writeLine(context.stdout, `Updated motion ${display(motion?.name)} (${display(motion?.prefix_id)}).`);
|
|
1229
|
+
renderMotion(motion, context);
|
|
939
1230
|
}
|
|
940
1231
|
|
|
941
1232
|
async function motionsStatusShortcut(action, args, context, { accountOverride } = {}) {
|
|
@@ -954,10 +1245,7 @@ async function motionsStatusShortcut(action, args, context, { accountOverride }
|
|
|
954
1245
|
}
|
|
955
1246
|
|
|
956
1247
|
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
|
-
}
|
|
1248
|
+
const normalizedStatus = normalizeMotionStatus(status);
|
|
961
1249
|
|
|
962
1250
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
963
1251
|
const motion = await client.updateMotion(accountId, motionId, {
|
|
@@ -971,6 +1259,37 @@ async function updateMotionStatus(motionId, status, context, { accountOverride,
|
|
|
971
1259
|
renderMotion(motion, context);
|
|
972
1260
|
}
|
|
973
1261
|
|
|
1262
|
+
function normalizeMotionStatus(status) {
|
|
1263
|
+
if (status === undefined) return undefined;
|
|
1264
|
+
|
|
1265
|
+
const normalizedStatus = String(status || "").trim().toLowerCase();
|
|
1266
|
+
if (!MOTION_STATUS_VALUES.has(normalizedStatus)) {
|
|
1267
|
+
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return normalizedStatus;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
async function motionsTagMutation(action, args, context, { accountOverride } = {}) {
|
|
1274
|
+
const usageText = action === "add" ? MOTIONS_ADD_TAG_USAGE : MOTIONS_REMOVE_TAG_USAGE;
|
|
1275
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
1276
|
+
if (positionals.length !== 2) {
|
|
1277
|
+
throw new CommandError(usageText);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
const [motionId, tag] = positionals;
|
|
1281
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1282
|
+
const motion = action === "add" ?
|
|
1283
|
+
await client.addMotionTag(accountId, motionId, { tag }) :
|
|
1284
|
+
await client.removeMotionTag(accountId, motionId, { tag });
|
|
1285
|
+
if (values.json) return writeJson(context.stdout, motion);
|
|
1286
|
+
|
|
1287
|
+
const verb = action === "add" ? "Added" : "Removed";
|
|
1288
|
+
const preposition = action === "add" ? "to" : "from";
|
|
1289
|
+
writeLine(context.stdout, `${verb} tag ${display(tag)} ${preposition} motion ${display(motion?.name)} (${display(motion?.prefix_id)}).`);
|
|
1290
|
+
if (Array.isArray(motion?.play_tags)) writeLine(context.stdout, `Tags: ${display(motion.play_tags.join(", "), "-")}`);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
974
1293
|
async function motionsClone(args, context, { accountOverride } = {}) {
|
|
975
1294
|
const { values, positionals } = parseCommandArgs(args, {
|
|
976
1295
|
...jsonOptions(),
|
|
@@ -1018,7 +1337,47 @@ async function motionsMoveProspects(args, context, { accountOverride } = {}) {
|
|
|
1018
1337
|
}
|
|
1019
1338
|
|
|
1020
1339
|
async function prospectsList(args, context, { accountOverride } = {}) {
|
|
1021
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
1340
|
+
const { values, positionals } = parseCommandArgs(args, prospectFilterOptions());
|
|
1341
|
+
if (positionals.length > 0) throw new CommandError("Usage: audienti prospects list [--json] [filters] [--account <acct_id>]");
|
|
1342
|
+
if (values.csv && values.json) throw new CommandError("Choose one output format: use either --csv or --json.");
|
|
1343
|
+
validateProspectFilterValues(values);
|
|
1344
|
+
|
|
1345
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1346
|
+
const query = prospectQueryFromValues(values, config, { accountOverride });
|
|
1347
|
+
const payload = values.all ?
|
|
1348
|
+
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
1349
|
+
await client.prospects(accountId, query);
|
|
1350
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1351
|
+
if (values.csv) return writeLine(context.stdout, prospectsToCsv(payload?.prospects || []));
|
|
1352
|
+
|
|
1353
|
+
renderProspects(payload, context, { wide: values.wide || values.all, profiles: values.profiles });
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
async function prospectsCheck(args, context, { accountOverride } = {}) {
|
|
1357
|
+
const { values, positionals } = parseCommandArgs(args, prospectFilterOptions());
|
|
1358
|
+
if (positionals.length > 0) throw new CommandError(PROSPECTS_CHECK_USAGE);
|
|
1359
|
+
if (values.csv && values.json) throw new CommandError("Choose one output format: use either --csv or --json.");
|
|
1360
|
+
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.");
|
|
1361
|
+
validateProspectFilterValues(values);
|
|
1362
|
+
|
|
1363
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1364
|
+
const query = {
|
|
1365
|
+
...prospectQueryFromValues(values, config, { accountOverride }),
|
|
1366
|
+
data_quality: "missing_certified_company"
|
|
1367
|
+
};
|
|
1368
|
+
const rawPayload = values.all ?
|
|
1369
|
+
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
1370
|
+
await client.prospects(accountId, query);
|
|
1371
|
+
const payload = withProspectAppUrls(rawPayload, client.host);
|
|
1372
|
+
|
|
1373
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1374
|
+
if (values.csv) return writeLine(context.stdout, prospectCheckToCsv(payload?.prospects || []));
|
|
1375
|
+
|
|
1376
|
+
renderProspectCheck(payload, context);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
function prospectFilterOptions() {
|
|
1380
|
+
return {
|
|
1022
1381
|
...jsonOptions(),
|
|
1023
1382
|
all: { type: "boolean" },
|
|
1024
1383
|
csv: { type: "boolean" },
|
|
@@ -1035,16 +1394,18 @@ async function prospectsList(args, context, { accountOverride } = {}) {
|
|
|
1035
1394
|
page: { type: "string" },
|
|
1036
1395
|
profiles: { type: "boolean" },
|
|
1037
1396
|
wide: { type: "boolean" }
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
function validateProspectFilterValues(values) {
|
|
1041
1401
|
if (values.page && values.offset) throw new CommandError("Choose one pagination mode: use either --page or --offset.");
|
|
1042
1402
|
if (values.all && (values.page || values.offset)) throw new CommandError("--all cannot be combined with --page or --offset.");
|
|
1043
1403
|
if (values.motion && values.play) throw new CommandError("Choose one motion filter: use either --motion or --play.");
|
|
1044
1404
|
if (values.company && values["company-profile"]) throw new CommandError("Choose one company filter: use either --company or --company-profile.");
|
|
1405
|
+
}
|
|
1045
1406
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1407
|
+
function prospectQueryFromValues(values, config, { accountOverride } = {}) {
|
|
1408
|
+
return compactObject({
|
|
1048
1409
|
query: values.query,
|
|
1049
1410
|
company: values.company,
|
|
1050
1411
|
company_profile_id: values["company-profile"],
|
|
@@ -1058,13 +1419,6 @@ async function prospectsList(args, context, { accountOverride } = {}) {
|
|
|
1058
1419
|
page: values.page,
|
|
1059
1420
|
include_profiles: values.profiles
|
|
1060
1421
|
});
|
|
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
1422
|
}
|
|
1069
1423
|
|
|
1070
1424
|
async function prospectsAssign(args, context, { accountOverride } = {}) {
|
|
@@ -1109,6 +1463,32 @@ async function prospectsShow(args, context, { accountOverride } = {}) {
|
|
|
1109
1463
|
renderProspect(prospect, context);
|
|
1110
1464
|
}
|
|
1111
1465
|
|
|
1466
|
+
async function prospectsDisposition(action, args, context, { accountOverride } = {}) {
|
|
1467
|
+
const usageText = {
|
|
1468
|
+
reject: PROSPECTS_REJECT_USAGE,
|
|
1469
|
+
nurture: PROSPECTS_NURTURE_USAGE,
|
|
1470
|
+
restore: PROSPECTS_RESTORE_USAGE
|
|
1471
|
+
}[action];
|
|
1472
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
1473
|
+
...jsonOptions(),
|
|
1474
|
+
reason: { type: "string" }
|
|
1475
|
+
});
|
|
1476
|
+
if (positionals.length !== 1 || (action !== "nurture" && values.reason)) {
|
|
1477
|
+
throw new CommandError(usageText);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1481
|
+
const prospectId = positionals[0];
|
|
1482
|
+
const payload = action === "reject" ?
|
|
1483
|
+
await client.rejectProspect(accountId, prospectId) :
|
|
1484
|
+
action === "restore" ?
|
|
1485
|
+
await client.restoreProspect(accountId, prospectId) :
|
|
1486
|
+
await client.nurtureProspect(accountId, prospectId, compactObject({ inactive_reason: values.reason }));
|
|
1487
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1488
|
+
|
|
1489
|
+
renderProspectDisposition(payload, context, { action });
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1112
1492
|
async function prospectsTimeline(args, context, { accountOverride } = {}) {
|
|
1113
1493
|
const { values, positionals } = parseCommandArgs(args, {
|
|
1114
1494
|
...jsonOptions(),
|
|
@@ -1784,6 +2164,18 @@ async function analyticsContent(args, context, { accountOverride } = {}) {
|
|
|
1784
2164
|
renderAnalyticsContent(payload, context);
|
|
1785
2165
|
}
|
|
1786
2166
|
|
|
2167
|
+
async function analyticsDashboard(args, context, { accountOverride } = {}) {
|
|
2168
|
+
const { values, positionals } = parseCommandArgs(args, analyticsDashboardOptions());
|
|
2169
|
+
if (positionals.length > 0) throw new CommandError(ANALYTICS_DASHBOARD_USAGE);
|
|
2170
|
+
validateDatePair(values["cohort-start"], values["cohort-end"], "--cohort-start", "--cohort-end");
|
|
2171
|
+
|
|
2172
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2173
|
+
const payload = await client.analyticsDashboard(accountId, analyticsDashboardQuery(values, config, { accountOverride }));
|
|
2174
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
2175
|
+
|
|
2176
|
+
renderAnalyticsDashboard(payload, context);
|
|
2177
|
+
}
|
|
2178
|
+
|
|
1787
2179
|
function parseCommandArgs(args, options) {
|
|
1788
2180
|
try {
|
|
1789
2181
|
return parseArgs({
|
|
@@ -1955,6 +2347,20 @@ function analyticsUsersOptions() {
|
|
|
1955
2347
|
};
|
|
1956
2348
|
}
|
|
1957
2349
|
|
|
2350
|
+
function analyticsDashboardOptions() {
|
|
2351
|
+
return {
|
|
2352
|
+
...jsonOptions(),
|
|
2353
|
+
"cohort-start": { type: "string" },
|
|
2354
|
+
"cohort-end": { type: "string" },
|
|
2355
|
+
"play-tag": { type: "string" },
|
|
2356
|
+
tag: { type: "string" },
|
|
2357
|
+
motion: { type: "string" },
|
|
2358
|
+
offer: { type: "string" },
|
|
2359
|
+
icp: { type: "string" },
|
|
2360
|
+
user: { type: "string" }
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
|
|
1958
2364
|
function analyticsQuery(values, config = {}, { accountOverride } = {}) {
|
|
1959
2365
|
return compactObject({
|
|
1960
2366
|
window: values.window,
|
|
@@ -1981,6 +2387,18 @@ function analyticsUsersQuery(values, config = {}, { accountOverride } = {}) {
|
|
|
1981
2387
|
});
|
|
1982
2388
|
}
|
|
1983
2389
|
|
|
2390
|
+
function analyticsDashboardQuery(values, config = {}, { accountOverride } = {}) {
|
|
2391
|
+
return compactObject({
|
|
2392
|
+
cohort_start_date: values["cohort-start"],
|
|
2393
|
+
cohort_end_date: values["cohort-end"],
|
|
2394
|
+
play_tag: values["play-tag"] || values.tag,
|
|
2395
|
+
motion_id: values.motion,
|
|
2396
|
+
offer_id: values.offer,
|
|
2397
|
+
icp_id: values.icp,
|
|
2398
|
+
account_user_id: resolveAccountUserId(values.user, config, { accountOverride })
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
|
|
1984
2402
|
function validateDatePair(start, end, startFlag, endFlag) {
|
|
1985
2403
|
if ((start && !end) || (!start && end)) {
|
|
1986
2404
|
throw new CommandError(`${startFlag} and ${endFlag} must be provided together.`);
|
|
@@ -2086,26 +2504,125 @@ function provenancePayload(provenance) {
|
|
|
2086
2504
|
|
|
2087
2505
|
function compactObject(object) {
|
|
2088
2506
|
return Object.fromEntries(
|
|
2089
|
-
Object.entries(object).filter(([, value]) =>
|
|
2507
|
+
Object.entries(object).filter(([, value]) => {
|
|
2508
|
+
if (value === undefined || value === null) return false;
|
|
2509
|
+
if (Array.isArray(value)) return true;
|
|
2510
|
+
|
|
2511
|
+
return String(value).trim() !== "";
|
|
2512
|
+
})
|
|
2090
2513
|
);
|
|
2091
2514
|
}
|
|
2092
2515
|
|
|
2093
|
-
async function
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2516
|
+
async function readLocalPackageMetadata() {
|
|
2517
|
+
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
2518
|
+
return {
|
|
2519
|
+
name: packageJson.name || PACKAGE_NAME,
|
|
2520
|
+
version: packageJson.version
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
async function fetchLatestPackageVersion({ fetchImpl, registry }) {
|
|
2525
|
+
if (!fetchImpl) throw new Error("This Node runtime does not provide fetch.");
|
|
2526
|
+
|
|
2527
|
+
const response = await fetchImpl(registryLatestPackageUrl(registry), {
|
|
2528
|
+
headers: {
|
|
2529
|
+
accept: "application/vnd.npm.install-v1+json, application/json"
|
|
2097
2530
|
}
|
|
2531
|
+
});
|
|
2532
|
+
const bodyText = await response.text();
|
|
2533
|
+
const body = bodyText ? JSON.parse(bodyText) : {};
|
|
2098
2534
|
|
|
2099
|
-
|
|
2535
|
+
if (!response.ok) {
|
|
2536
|
+
throw new Error(body?.error || body?.message || `Registry returned HTTP ${response.status}.`);
|
|
2100
2537
|
}
|
|
2101
2538
|
|
|
2102
|
-
|
|
2103
|
-
|
|
2539
|
+
const version = body?.version?.toString().trim();
|
|
2540
|
+
if (!version) throw new Error("Registry response did not include a version.");
|
|
2541
|
+
|
|
2542
|
+
return version;
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
function registryLatestPackageUrl(registry) {
|
|
2546
|
+
const base = new URL(registry || DEFAULT_NPM_REGISTRY);
|
|
2547
|
+
if (!base.pathname.endsWith("/")) base.pathname = `${base.pathname}/`;
|
|
2548
|
+
|
|
2549
|
+
return new URL(`${encodeURIComponent(PACKAGE_NAME)}/latest`, base).toString();
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
function updateCheckPayload({ currentVersion, latestVersion, status, updateAvailable, registry, error, now }) {
|
|
2553
|
+
return {
|
|
2554
|
+
kind: "update_check",
|
|
2555
|
+
package_name: PACKAGE_NAME,
|
|
2556
|
+
current_version: currentVersion,
|
|
2557
|
+
latest_version: latestVersion,
|
|
2558
|
+
update_available: updateAvailable,
|
|
2559
|
+
status,
|
|
2560
|
+
install_command: `npm install --global ${PACKAGE_NAME}`,
|
|
2561
|
+
registry,
|
|
2562
|
+
checked_at: now.toISOString(),
|
|
2563
|
+
error: error || null
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
function compareVersions(currentVersion, latestVersion) {
|
|
2568
|
+
const current = parseVersion(currentVersion);
|
|
2569
|
+
const latest = parseVersion(latestVersion);
|
|
2570
|
+
|
|
2571
|
+
for (let index = 0; index < 3; index += 1) {
|
|
2572
|
+
if (current.parts[index] !== latest.parts[index]) return current.parts[index] - latest.parts[index];
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
if (current.prerelease === latest.prerelease) return 0;
|
|
2576
|
+
if (!current.prerelease) return 1;
|
|
2577
|
+
if (!latest.prerelease) return -1;
|
|
2578
|
+
|
|
2579
|
+
return current.prerelease.localeCompare(latest.prerelease);
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
function parseVersion(version) {
|
|
2583
|
+
const [core, prerelease = ""] = String(version || "").split("-", 2);
|
|
2584
|
+
const parts = core.split(".").map((part) => Number.parseInt(part, 10));
|
|
2585
|
+
|
|
2586
|
+
return {
|
|
2587
|
+
parts: [parts[0] || 0, parts[1] || 0, parts[2] || 0],
|
|
2588
|
+
prerelease
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
function tagList(value) {
|
|
2593
|
+
if (value === undefined) return undefined;
|
|
2594
|
+
|
|
2595
|
+
return String(value)
|
|
2596
|
+
.split(/[\r\n,;]+/)
|
|
2597
|
+
.map((tag) => tag.trim().toLowerCase())
|
|
2598
|
+
.filter(Boolean)
|
|
2599
|
+
.filter((tag, index, tags) => tags.indexOf(tag) === index);
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
function filterRecordsByTag(records, value, field) {
|
|
2603
|
+
const tag = tagList(value)?.[0];
|
|
2604
|
+
if (!tag) return records;
|
|
2605
|
+
|
|
2606
|
+
return Array.isArray(records) ? records.filter((record) => (tagList(record?.[field]) || []).includes(tag)) : [];
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
async function icpCreatePayload(values) {
|
|
2610
|
+
if (values.payload) {
|
|
2611
|
+
if (values.name || values.notes || values.tags !== undefined || values["discovery-keyword"]) {
|
|
2612
|
+
throw new CommandError("Choose one ICP input mode: either --payload <file.json> or the simple --name/--notes/--discovery-keyword/tags flags.");
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
return readJsonPayload(values.payload);
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
if (!values.name) {
|
|
2619
|
+
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
2620
|
}
|
|
2105
2621
|
|
|
2106
2622
|
return compactObject({
|
|
2107
2623
|
name: values.name,
|
|
2108
2624
|
notes: values.notes,
|
|
2625
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
2109
2626
|
discovery_keyword: values["discovery-keyword"]
|
|
2110
2627
|
});
|
|
2111
2628
|
}
|
|
@@ -2246,6 +2763,17 @@ function normalizePositiveInteger(value) {
|
|
|
2246
2763
|
return parsed;
|
|
2247
2764
|
}
|
|
2248
2765
|
|
|
2766
|
+
function normalizeOptionalPositiveInteger(value, flagName) {
|
|
2767
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
2768
|
+
|
|
2769
|
+
const parsed = normalizePositiveInteger(value);
|
|
2770
|
+
if (parsed === null || String(parsed) !== String(value).trim()) {
|
|
2771
|
+
throw new CommandError(`${flagName} must be a positive integer.`);
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
return parsed;
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2249
2777
|
function normalizeLookupType(value) {
|
|
2250
2778
|
const normalized = String(value || "").trim().toLowerCase();
|
|
2251
2779
|
if (normalized === "email" || normalized === "phone") return normalized;
|
|
@@ -2394,6 +2922,22 @@ function writeJson(stream, value) {
|
|
|
2394
2922
|
writeLine(stream, JSON.stringify(value, null, 2));
|
|
2395
2923
|
}
|
|
2396
2924
|
|
|
2925
|
+
function renderUpdateCheck(payload, context) {
|
|
2926
|
+
writeLine(context.stdout, `Package: ${payload.package_name}`);
|
|
2927
|
+
writeLine(context.stdout, `Current version: ${display(payload.current_version, "-")}`);
|
|
2928
|
+
writeLine(context.stdout, `Latest version: ${display(payload.latest_version, "unknown")}`);
|
|
2929
|
+
|
|
2930
|
+
if (payload.status === "update_available") {
|
|
2931
|
+
writeLine(context.stdout, "Status: update available");
|
|
2932
|
+
writeLine(context.stdout, `Update: ${payload.install_command}`);
|
|
2933
|
+
} else if (payload.status === "current") {
|
|
2934
|
+
writeLine(context.stdout, "Status: current");
|
|
2935
|
+
} else {
|
|
2936
|
+
writeLine(context.stdout, "Status: unknown");
|
|
2937
|
+
if (payload.error) writeLine(context.stdout, `Error: ${payload.error}`);
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2397
2941
|
async function sleep(milliseconds) {
|
|
2398
2942
|
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
2399
2943
|
}
|
|
@@ -2410,9 +2954,48 @@ function renderLists(lists, context) {
|
|
|
2410
2954
|
function renderList(list, context) {
|
|
2411
2955
|
writeLine(context.stdout, `List: ${display(list?.name)} (${display(list?.prefix_id)})`);
|
|
2412
2956
|
writeLine(context.stdout, `Prospects: ${display(list?.prospect_count, 0)}`);
|
|
2957
|
+
if (Array.isArray(list?.tags)) writeLine(context.stdout, `Tags: ${display(list.tags.join(", "), "-")}`);
|
|
2413
2958
|
if (list?.description) writeLine(context.stdout, `Description: ${list.description}`);
|
|
2414
2959
|
}
|
|
2415
2960
|
|
|
2961
|
+
function renderTags(tags, context) {
|
|
2962
|
+
if (!Array.isArray(tags) || tags.length === 0) return writeLine(context.stdout, "No tags found.");
|
|
2963
|
+
|
|
2964
|
+
writeLine(context.stdout, "TAG\tICPS\tLISTS\tMOTIONS\tTOTAL");
|
|
2965
|
+
for (const tag of tags) {
|
|
2966
|
+
writeLine(
|
|
2967
|
+
context.stdout,
|
|
2968
|
+
[
|
|
2969
|
+
display(tag.name),
|
|
2970
|
+
display(tag.icp_count, 0),
|
|
2971
|
+
display(tag.list_count, 0),
|
|
2972
|
+
display(tag.motion_count, 0),
|
|
2973
|
+
display(tag.total_count, 0)
|
|
2974
|
+
].join("\t")
|
|
2975
|
+
);
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
function renderTagDetails(payload, context) {
|
|
2980
|
+
const icps = Array.isArray(payload?.icps) ? payload.icps : [];
|
|
2981
|
+
const lists = Array.isArray(payload?.lists) ? payload.lists : [];
|
|
2982
|
+
const motions = Array.isArray(payload?.motions) ? payload.motions : [];
|
|
2983
|
+
|
|
2984
|
+
writeLine(context.stdout, `Tag: ${display(payload?.tag)}`);
|
|
2985
|
+
writeLine(context.stdout, `ICPs: ${icps.length}`);
|
|
2986
|
+
writeLine(context.stdout, `Lists: ${lists.length}`);
|
|
2987
|
+
writeLine(context.stdout, `Motions: ${motions.length}`);
|
|
2988
|
+
writeLine(context.stdout);
|
|
2989
|
+
writeLine(context.stdout, "ICPs");
|
|
2990
|
+
renderIcps(icps, context);
|
|
2991
|
+
writeLine(context.stdout);
|
|
2992
|
+
writeLine(context.stdout, "Lists");
|
|
2993
|
+
renderLists(lists, context);
|
|
2994
|
+
writeLine(context.stdout);
|
|
2995
|
+
writeLine(context.stdout, "Motions");
|
|
2996
|
+
renderMotions(motions, context);
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2416
2999
|
function renderUsers(users, context) {
|
|
2417
3000
|
if (!Array.isArray(users) || users.length === 0) return writeLine(context.stdout, "No account users found.");
|
|
2418
3001
|
|
|
@@ -2482,16 +3065,23 @@ function renderOffers(offers, context) {
|
|
|
2482
3065
|
}
|
|
2483
3066
|
}
|
|
2484
3067
|
|
|
3068
|
+
function renderOffer(offer, context) {
|
|
3069
|
+
writeLine(context.stdout, `Offer: ${display(offer?.name)} (${display(offer?.prefix_id)})`);
|
|
3070
|
+
if (offer?.description) writeLine(context.stdout, `Description: ${offer.description}`);
|
|
3071
|
+
if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
|
|
3072
|
+
}
|
|
3073
|
+
|
|
2485
3074
|
function renderIcps(icps, context) {
|
|
2486
3075
|
if (!Array.isArray(icps) || icps.length === 0) return writeLine(context.stdout, "No ICPs found.");
|
|
2487
3076
|
|
|
2488
|
-
writeLine(context.stdout, "ICP ID\tNAME\tDISCOVERY KEYWORD\tAGENT");
|
|
3077
|
+
writeLine(context.stdout, "ICP ID\tNAME\tTAGS\tDISCOVERY KEYWORD\tAGENT");
|
|
2489
3078
|
for (const icp of icps) {
|
|
2490
3079
|
writeLine(
|
|
2491
3080
|
context.stdout,
|
|
2492
3081
|
[
|
|
2493
3082
|
display(icp.prefix_id),
|
|
2494
3083
|
display(icp.name),
|
|
3084
|
+
display(Array.isArray(icp.tags) && icp.tags.length > 0 ? icp.tags.join(",") : "-"),
|
|
2495
3085
|
display(icp.discovery_keyword),
|
|
2496
3086
|
display(icp.agent?.name)
|
|
2497
3087
|
].join("\t")
|
|
@@ -2499,6 +3089,14 @@ function renderIcps(icps, context) {
|
|
|
2499
3089
|
}
|
|
2500
3090
|
}
|
|
2501
3091
|
|
|
3092
|
+
function renderIcp(icp, context) {
|
|
3093
|
+
writeLine(context.stdout, `ICP: ${display(icp?.name)} (${display(icp?.prefix_id)})`);
|
|
3094
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
3095
|
+
if (icp?.notes) writeLine(context.stdout, `Notes: ${icp.notes}`);
|
|
3096
|
+
if (icp?.discovery_keyword) writeLine(context.stdout, `Discovery keyword: ${icp.discovery_keyword}`);
|
|
3097
|
+
if (icp?.agent?.name) writeLine(context.stdout, `Agent: ${icp.agent.name}`);
|
|
3098
|
+
}
|
|
3099
|
+
|
|
2502
3100
|
function renderCompanies(payload, context) {
|
|
2503
3101
|
const companies = Array.isArray(payload?.companies) ? payload.companies : [];
|
|
2504
3102
|
if (companies.length === 0) return writeLine(context.stdout, "No companies found.");
|
|
@@ -2563,6 +3161,7 @@ function renderMotion(motion, context) {
|
|
|
2563
3161
|
if (motion?.offer?.name) writeLine(context.stdout, `Offer: ${motion.offer.name} (${display(motion.offer.prefix_id)})`);
|
|
2564
3162
|
if (motion?.icp?.name) writeLine(context.stdout, `ICP: ${motion.icp.name} (${display(motion.icp.prefix_id)})`);
|
|
2565
3163
|
if (motion?.list?.name) writeLine(context.stdout, `List: ${motion.list.name} (${display(motion.list.prefix_id)})`);
|
|
3164
|
+
if (Array.isArray(motion?.play_tags)) writeLine(context.stdout, `Tags: ${display(motion.play_tags.join(", "), "-")}`);
|
|
2566
3165
|
if (motion?.principal_account_user?.id) {
|
|
2567
3166
|
writeLine(
|
|
2568
3167
|
context.stdout,
|
|
@@ -2630,6 +3229,27 @@ function renderProspects(payload, context, { wide = false, profiles = false } =
|
|
|
2630
3229
|
}
|
|
2631
3230
|
}
|
|
2632
3231
|
|
|
3232
|
+
function renderProspectCheck(payload, context) {
|
|
3233
|
+
const prospects = Array.isArray(payload?.prospects) ? payload.prospects : [];
|
|
3234
|
+
const totalCount = display(payload?.meta?.total_count, prospects.length);
|
|
3235
|
+
if (prospects.length === 0) return writeLine(context.stdout, "No suspect prospects found.");
|
|
3236
|
+
|
|
3237
|
+
writeLine(context.stdout, `Suspect prospects: ${totalCount}`);
|
|
3238
|
+
writeLine(context.stdout, "PROSPECT ID\tSTAGE\tNAME\tREPORTED COMPANY\tCERTIFIED\tREASON\tURL");
|
|
3239
|
+
for (const prospect of prospects) {
|
|
3240
|
+
const certification = prospect.company_certification || {};
|
|
3241
|
+
writeLine(context.stdout, [
|
|
3242
|
+
display(prospect.prefix_id),
|
|
3243
|
+
display(prospect.account_prospect?.pipeline_stage),
|
|
3244
|
+
display(prospect.display_name || prospect.name),
|
|
3245
|
+
display(certification.reported_company || prospect.company),
|
|
3246
|
+
certification.status === "certified" ? "yes" : "no",
|
|
3247
|
+
display(certification.reason, "missing_employment_citation"),
|
|
3248
|
+
display(prospect.app_url)
|
|
3249
|
+
].join("\t"));
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
|
|
2633
3253
|
function renderProspect(prospect, context) {
|
|
2634
3254
|
writeLine(context.stdout, `Prospect: ${display(prospect?.display_name || prospect?.name)} (${display(prospect?.prefix_id)})`);
|
|
2635
3255
|
if (prospect?.company) writeLine(context.stdout, `Company: ${prospect.company}`);
|
|
@@ -2639,6 +3259,21 @@ function renderProspect(prospect, context) {
|
|
|
2639
3259
|
if (nextActionLabel(prospect?.queue)) writeLine(context.stdout, `Next action: ${nextActionLabel(prospect.queue)}`);
|
|
2640
3260
|
}
|
|
2641
3261
|
|
|
3262
|
+
function renderProspectDisposition(payload, context, { action }) {
|
|
3263
|
+
const prospect = payload?.prospect || {};
|
|
3264
|
+
const accountProspect = payload?.account_prospect || {};
|
|
3265
|
+
const actionLabel = {
|
|
3266
|
+
reject: "Rejected",
|
|
3267
|
+
nurture: "Moved to nurture",
|
|
3268
|
+
restore: "Restored"
|
|
3269
|
+
}[action] || display(payload?.status, "Updated");
|
|
3270
|
+
|
|
3271
|
+
writeLine(context.stdout, `${actionLabel} prospect ${display(prospect.display_name || prospect.name)} (${display(prospect.prefix_id)}).`);
|
|
3272
|
+
if (accountProspect.status) writeLine(context.stdout, `Status: ${accountProspect.status}`);
|
|
3273
|
+
if (accountProspect.inactive_reason) writeLine(context.stdout, `Inactive reason: ${accountProspect.inactive_reason}`);
|
|
3274
|
+
if (payload?.system_list?.name) writeLine(context.stdout, `List: ${payload.system_list.name} (${display(payload.system_list.prefix_id)})`);
|
|
3275
|
+
}
|
|
3276
|
+
|
|
2642
3277
|
function renderProspectTimeline(payload, context) {
|
|
2643
3278
|
const prospect = payload?.prospect || {};
|
|
2644
3279
|
const timeline = Array.isArray(payload?.timeline) ? payload.timeline : [];
|
|
@@ -3161,6 +3796,32 @@ function renderMotionAnalytics(payload, context) {
|
|
|
3161
3796
|
writeCountTable(context, "Prospect cohorts by produced day", payload?.prospects_by_day, ["DATE", "PRODUCED", "ACTIVE", "ACTIVE %", "INACTIVE", "STAGES"], dailyProspectRow);
|
|
3162
3797
|
}
|
|
3163
3798
|
|
|
3799
|
+
function renderMotionDiscoveryRun(payload, context) {
|
|
3800
|
+
const motion = payload?.motion || {};
|
|
3801
|
+
const label = entityLabel(motion) || payload?.motion_id;
|
|
3802
|
+
const prefix = payload?.enqueued ? "Discovery queued" : "Discovery not queued";
|
|
3803
|
+
writeLine(context.stdout, `${prefix} for ${display(label)}.`);
|
|
3804
|
+
writeLine(context.stdout, `Reason: ${display(payload?.reason)}`);
|
|
3805
|
+
writeLine(context.stdout, `Target count: ${display(payload?.target_count)}`);
|
|
3806
|
+
}
|
|
3807
|
+
|
|
3808
|
+
function renderAnalyticsDashboard(payload, context) {
|
|
3809
|
+
writeLine(context.stdout, `Dashboard analytics (${display(payload?.cohort?.label, "selected cohort")})`);
|
|
3810
|
+
if (payload?.cohort) {
|
|
3811
|
+
writeLine(context.stdout, `Cohort: ${payload.cohort.start_date} to ${payload.cohort.end_date} (${display(payload.cohort.field, "account_prospects.created_at")})`);
|
|
3812
|
+
}
|
|
3813
|
+
if (payload?.activity) {
|
|
3814
|
+
writeLine(context.stdout, `Activity: ${payload.activity.start_date} to ${payload.activity.end_date} (${display(payload.activity.field, "events.created_at")})`);
|
|
3815
|
+
}
|
|
3816
|
+
writeDashboardFilters(payload, context);
|
|
3817
|
+
writeLine(context.stdout, `Prospects: ${display(payload?.cohort_size, 0)}`);
|
|
3818
|
+
writeLine(context.stdout, `Companies: ${display(payload?.cohort_company_target_count, 0)}`);
|
|
3819
|
+
writeLine(context.stdout, `People/company: ${display(payload?.cohort_people_per_company_average, "0.0")}`);
|
|
3820
|
+
writeLine(context.stdout, `Active: ${display(payload?.active_cohort_count, 0)} (${display(payload?.active_cohort_company_target_count, 0)} companies, ${percentageLabel(payload?.active_cohort_percentage)})`);
|
|
3821
|
+
writeLine(context.stdout, `Inactive: ${display(payload?.inactive_cohort_count, 0)}`);
|
|
3822
|
+
writeCountTable(context, "Current pipeline stages", payload?.pipeline_stage_counts, ["STAGE", "COUNT"], countRow);
|
|
3823
|
+
}
|
|
3824
|
+
|
|
3164
3825
|
function renderAnalyticsProspectCohortAnalysis(payload, context) {
|
|
3165
3826
|
const cohorts = Array.isArray(payload?.cohorts) ? payload.cohorts : [];
|
|
3166
3827
|
writeLine(context.stdout, `Prospect cohort analysis (${display(payload?.weeks, cohorts.length)} weeks)`);
|
|
@@ -3235,6 +3896,19 @@ function writeAnalyticsScope(payload, context) {
|
|
|
3235
3896
|
}
|
|
3236
3897
|
}
|
|
3237
3898
|
|
|
3899
|
+
function writeDashboardFilters(payload, context) {
|
|
3900
|
+
const filters = payload?.filters || {};
|
|
3901
|
+
if (filters.motion) writeLine(context.stdout, `Motion: ${entityLabel(filters.motion)}`);
|
|
3902
|
+
if (filters.play_tag) writeLine(context.stdout, `Tag: ${filters.play_tag}`);
|
|
3903
|
+
if (filters.offer) writeLine(context.stdout, `Offer: ${entityLabel(filters.offer)}`);
|
|
3904
|
+
if (filters.icp) writeLine(context.stdout, `ICP: ${entityLabel(filters.icp)}`);
|
|
3905
|
+
if (filters.account_user) {
|
|
3906
|
+
writeLine(context.stdout, `User: ${entityLabel(filters.account_user)}`);
|
|
3907
|
+
} else {
|
|
3908
|
+
writeLine(context.stdout, "User: all account users");
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
|
|
3238
3912
|
function writeAnalyticsPlatform(payload, context) {
|
|
3239
3913
|
if (!payload?.platform) return;
|
|
3240
3914
|
|
|
@@ -3674,6 +4348,77 @@ function prospectsToCsv(prospects) {
|
|
|
3674
4348
|
].join("\n");
|
|
3675
4349
|
}
|
|
3676
4350
|
|
|
4351
|
+
function prospectCheckToCsv(prospects) {
|
|
4352
|
+
const headers = [
|
|
4353
|
+
"prefix_id",
|
|
4354
|
+
"display_name",
|
|
4355
|
+
"name",
|
|
4356
|
+
"title",
|
|
4357
|
+
"reported_company",
|
|
4358
|
+
"company_certification_status",
|
|
4359
|
+
"company_certification_reason",
|
|
4360
|
+
"email",
|
|
4361
|
+
"linkedin_url",
|
|
4362
|
+
"app_url",
|
|
4363
|
+
"account_prospect_status",
|
|
4364
|
+
"pipeline_stage",
|
|
4365
|
+
"assigned_to_account_user_id",
|
|
4366
|
+
"motion_prefix_id",
|
|
4367
|
+
"motion_name",
|
|
4368
|
+
"updated_at"
|
|
4369
|
+
];
|
|
4370
|
+
|
|
4371
|
+
const rows = prospects.map((prospect) => {
|
|
4372
|
+
const certification = prospect.company_certification || {};
|
|
4373
|
+
return {
|
|
4374
|
+
prefix_id: prospect.prefix_id,
|
|
4375
|
+
display_name: prospect.display_name,
|
|
4376
|
+
name: prospect.name,
|
|
4377
|
+
title: prospect.title,
|
|
4378
|
+
reported_company: certification.reported_company || prospect.company,
|
|
4379
|
+
company_certification_status: certification.status,
|
|
4380
|
+
company_certification_reason: certification.reason,
|
|
4381
|
+
email: prospect.email,
|
|
4382
|
+
linkedin_url: prospect.linkedin_url,
|
|
4383
|
+
app_url: prospect.app_url,
|
|
4384
|
+
account_prospect_status: prospect.account_prospect?.status,
|
|
4385
|
+
pipeline_stage: prospect.account_prospect?.pipeline_stage,
|
|
4386
|
+
assigned_to_account_user_id: prospect.account_prospect?.assigned_to_account_user_id,
|
|
4387
|
+
motion_prefix_id: prospect.account_prospect?.motion?.prefix_id,
|
|
4388
|
+
motion_name: prospect.account_prospect?.motion?.name,
|
|
4389
|
+
updated_at: prospect.updated_at
|
|
4390
|
+
};
|
|
4391
|
+
});
|
|
4392
|
+
|
|
4393
|
+
return [
|
|
4394
|
+
headers.join(","),
|
|
4395
|
+
...rows.map((row) => headers.map((header) => csvField(row[header])).join(","))
|
|
4396
|
+
].join("\n");
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
function withProspectAppUrls(payload, host) {
|
|
4400
|
+
if (!payload || !Array.isArray(payload.prospects)) return payload;
|
|
4401
|
+
|
|
4402
|
+
return {
|
|
4403
|
+
...payload,
|
|
4404
|
+
prospects: payload.prospects.map((prospect) => ({
|
|
4405
|
+
...prospect,
|
|
4406
|
+
app_url: prospectAppUrl(prospect, host)
|
|
4407
|
+
}))
|
|
4408
|
+
};
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4411
|
+
function prospectAppUrl(prospect, host) {
|
|
4412
|
+
const prospectId = String(prospect?.prefix_id || "").trim();
|
|
4413
|
+
if (!prospectId) return undefined;
|
|
4414
|
+
|
|
4415
|
+
try {
|
|
4416
|
+
return new URL(`/prospects/${encodeURIComponent(prospectId)}`, normalizeHost(host)).toString();
|
|
4417
|
+
} catch {
|
|
4418
|
+
return undefined;
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
|
|
3677
4422
|
function sequenceExportRowsToCsv(rows) {
|
|
3678
4423
|
return [
|
|
3679
4424
|
SEQUENCE_EXPORT_CSV_COLUMNS.join(","),
|
|
@@ -3774,6 +4519,7 @@ const HELP_TOPICS = new Map([
|
|
|
3774
4519
|
" Setup & identity",
|
|
3775
4520
|
" audienti auth status",
|
|
3776
4521
|
" audienti config list",
|
|
4522
|
+
" audienti update check",
|
|
3777
4523
|
" audienti users list",
|
|
3778
4524
|
" audienti users select <account_user_id|email|name|me>",
|
|
3779
4525
|
" audienti users activity [account_user_id|me]",
|
|
@@ -3782,9 +4528,12 @@ const HELP_TOPICS = new Map([
|
|
|
3782
4528
|
" audienti motions list",
|
|
3783
4529
|
" audienti motions show <motn_id>",
|
|
3784
4530
|
" audienti motions analytics <motn_id>",
|
|
4531
|
+
" audienti motions run-discovery <motn_id>",
|
|
3785
4532
|
" audienti motions prospects <motn_id>",
|
|
3786
4533
|
" audienti motions create --payload <file.json>",
|
|
3787
|
-
" audienti motions update <motn_id> --status <state>",
|
|
4534
|
+
" audienti motions update <motn_id> [--status <state>] [--tags <tag[,tag...]>]",
|
|
4535
|
+
" audienti motions add-tag <motn_id> <tag>",
|
|
4536
|
+
" audienti motions remove-tag <motn_id> <tag>",
|
|
3788
4537
|
" audienti motions activate <motn_id>",
|
|
3789
4538
|
" audienti motions pause <motn_id>",
|
|
3790
4539
|
" audienti motions delete <motn_id> --confirm <yes|true|Y|y>",
|
|
@@ -3794,8 +4543,12 @@ const HELP_TOPICS = new Map([
|
|
|
3794
4543
|
"",
|
|
3795
4544
|
" Prospects",
|
|
3796
4545
|
" audienti prospects list [filters]",
|
|
4546
|
+
" audienti prospects check [filters]",
|
|
3797
4547
|
" audienti prospects show <prsp_id>",
|
|
3798
4548
|
" audienti prospects assign <prsp_id> --assigned-user <id|me|unassign>",
|
|
4549
|
+
" audienti prospects reject <prsp_id>",
|
|
4550
|
+
" audienti prospects nurture <prsp_id> [--reason <reason>]",
|
|
4551
|
+
" audienti prospects restore <prsp_id>",
|
|
3799
4552
|
" audienti prospects timeline <prsp_id>",
|
|
3800
4553
|
" audienti prospects import <linkedin_url> [--motion <motn_id>]",
|
|
3801
4554
|
" audienti prospects import-batch --file <csv|jsonl|json>",
|
|
@@ -3803,10 +4556,21 @@ const HELP_TOPICS = new Map([
|
|
|
3803
4556
|
" audienti prospects add-profile <prsp_id> --url <profile_url|email|phone>",
|
|
3804
4557
|
"",
|
|
3805
4558
|
" Lists & targeting inputs",
|
|
3806
|
-
" audienti lists list",
|
|
4559
|
+
" audienti lists list [--tag <tag>]",
|
|
3807
4560
|
" audienti lists prospects <list_id>",
|
|
4561
|
+
" audienti lists add-tag <list_id> <tag>",
|
|
4562
|
+
" audienti lists remove-tag <list_id> <tag>",
|
|
4563
|
+
" audienti tags list",
|
|
4564
|
+
" audienti tags show <tag>",
|
|
3808
4565
|
" audienti offers list",
|
|
3809
|
-
" audienti
|
|
4566
|
+
" audienti offers show <offr_id>",
|
|
4567
|
+
" audienti offers update <offr_id> [--name <text>]",
|
|
4568
|
+
" audienti offers delete <offr_id> --confirm <yes|true|Y|y>",
|
|
4569
|
+
" audienti icps list [--tag <tag>]",
|
|
4570
|
+
" audienti icps show <icp_id>",
|
|
4571
|
+
" audienti icps update <icp_id> [--tags <tag[,tag...]>]",
|
|
4572
|
+
" audienti icps add-tag <icp_id> <tag>",
|
|
4573
|
+
" audienti icps remove-tag <icp_id> <tag>",
|
|
3810
4574
|
" audienti companies search --query <text>",
|
|
3811
4575
|
"",
|
|
3812
4576
|
" Writer",
|
|
@@ -3821,6 +4585,7 @@ const HELP_TOPICS = new Map([
|
|
|
3821
4585
|
"",
|
|
3822
4586
|
" Analytics",
|
|
3823
4587
|
" audienti analytics prospects --window 24h",
|
|
4588
|
+
" audienti analytics dashboard --play-tag <tag>",
|
|
3824
4589
|
" audienti analytics prospects cohort-analysis --weeks 4 --motion <motn_id>",
|
|
3825
4590
|
" audienti analytics users --user me --window 30d",
|
|
3826
4591
|
" audienti analytics visibility --window 24h --user me",
|
|
@@ -3835,6 +4600,7 @@ const HELP_TOPICS = new Map([
|
|
|
3835
4600
|
" Inspect a prospect: audienti prospects show <prsp_id> --json",
|
|
3836
4601
|
" Preview a campaign: audienti writer test-run <prsp_id>",
|
|
3837
4602
|
" Analyze one motion: audienti motions analytics <motn_id>",
|
|
4603
|
+
" Count one campaign: audienti analytics dashboard --play-tag <tag>",
|
|
3838
4604
|
" Audit your work: audienti analytics users --user me --window 30d",
|
|
3839
4605
|
"",
|
|
3840
4606
|
"Global options:",
|
|
@@ -3935,6 +4701,46 @@ const HELP_TOPICS = new Map([
|
|
|
3935
4701
|
" Default account user: account user name and id, or none selected"
|
|
3936
4702
|
].join("\n")],
|
|
3937
4703
|
|
|
4704
|
+
["update", [
|
|
4705
|
+
"Usage:",
|
|
4706
|
+
" audienti update check [--json] [--registry <url>]",
|
|
4707
|
+
"",
|
|
4708
|
+
"Status: implemented",
|
|
4709
|
+
"",
|
|
4710
|
+
"Purpose:",
|
|
4711
|
+
" Check whether this local Audienti CLI install is behind the latest published package.",
|
|
4712
|
+
"",
|
|
4713
|
+
"Commands:",
|
|
4714
|
+
" audienti update check Compare the local package version to the npm registry"
|
|
4715
|
+
].join("\n")],
|
|
4716
|
+
|
|
4717
|
+
["update check", [
|
|
4718
|
+
"Usage:",
|
|
4719
|
+
" audienti update check [--json] [--registry <url>]",
|
|
4720
|
+
"",
|
|
4721
|
+
"Status: implemented",
|
|
4722
|
+
"",
|
|
4723
|
+
"Purpose:",
|
|
4724
|
+
" Report whether this local CLI should be updated.",
|
|
4725
|
+
"",
|
|
4726
|
+
"Output shape:",
|
|
4727
|
+
" package_name: @audienti/cli",
|
|
4728
|
+
" current_version: local package version",
|
|
4729
|
+
" latest_version: latest registry version, or null when unknown",
|
|
4730
|
+
" update_available: true | false | null",
|
|
4731
|
+
" status: current | update_available | unknown",
|
|
4732
|
+
" install_command: npm install --global @audienti/cli",
|
|
4733
|
+
" registry: registry URL used for the check",
|
|
4734
|
+
" checked_at: ISO timestamp",
|
|
4735
|
+
" error: string | null",
|
|
4736
|
+
"",
|
|
4737
|
+
"Options:",
|
|
4738
|
+
" --registry <url> Alternate npm-compatible registry. Default: https://registry.npmjs.org",
|
|
4739
|
+
"",
|
|
4740
|
+
"Example:",
|
|
4741
|
+
" audienti update check --json"
|
|
4742
|
+
].join("\n")],
|
|
4743
|
+
|
|
3938
4744
|
["accounts", [
|
|
3939
4745
|
"Usage:",
|
|
3940
4746
|
" audienti accounts list [--json]",
|
|
@@ -4047,12 +4853,15 @@ const HELP_TOPICS = new Map([
|
|
|
4047
4853
|
["offers", [
|
|
4048
4854
|
"Usage:",
|
|
4049
4855
|
" audienti offers list [--json]",
|
|
4856
|
+
" audienti offers show <offr_id> [--json]",
|
|
4050
4857
|
" audienti offers create --name <text> [--json]",
|
|
4858
|
+
" audienti offers update <offr_id> [--name <text>] [--json]",
|
|
4859
|
+
" audienti offers delete <offr_id> --confirm <yes|true|Y|y> [--json]",
|
|
4051
4860
|
"",
|
|
4052
4861
|
"Status: implemented",
|
|
4053
4862
|
"",
|
|
4054
4863
|
"Purpose:",
|
|
4055
|
-
"
|
|
4864
|
+
" Manage the offers available to the current account so an agent can choose offer_id for motion creation."
|
|
4056
4865
|
].join("\n")],
|
|
4057
4866
|
|
|
4058
4867
|
["offers list", [
|
|
@@ -4102,10 +4911,60 @@ const HELP_TOPICS = new Map([
|
|
|
4102
4911
|
" }"
|
|
4103
4912
|
].join("\n")],
|
|
4104
4913
|
|
|
4914
|
+
["offers show", [
|
|
4915
|
+
"Usage:",
|
|
4916
|
+
` ${OFFERS_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
4917
|
+
"",
|
|
4918
|
+
"Status: implemented",
|
|
4919
|
+
"",
|
|
4920
|
+
"Input shape:",
|
|
4921
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
4922
|
+
"",
|
|
4923
|
+
"API:",
|
|
4924
|
+
" GET /api/v1/accounts/:account_id/offers/:id.json"
|
|
4925
|
+
].join("\n")],
|
|
4926
|
+
|
|
4927
|
+
["offers update", [
|
|
4928
|
+
"Usage:",
|
|
4929
|
+
` ${OFFERS_UPDATE_USAGE.slice("Usage: ".length)}`,
|
|
4930
|
+
"",
|
|
4931
|
+
"Status: implemented",
|
|
4932
|
+
"",
|
|
4933
|
+
"Purpose:",
|
|
4934
|
+
" Update simple offer fields without changing linked motions.",
|
|
4935
|
+
"",
|
|
4936
|
+
"Input shape:",
|
|
4937
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
4938
|
+
" name: string | optional",
|
|
4939
|
+
" description: string | optional",
|
|
4940
|
+
" url: string | optional",
|
|
4941
|
+
"",
|
|
4942
|
+
"API:",
|
|
4943
|
+
" PATCH /api/v1/accounts/:account_id/offers/:id.json"
|
|
4944
|
+
].join("\n")],
|
|
4945
|
+
|
|
4946
|
+
["offers delete", [
|
|
4947
|
+
"Usage:",
|
|
4948
|
+
` ${OFFERS_DELETE_USAGE.slice("Usage: ".length)}`,
|
|
4949
|
+
"",
|
|
4950
|
+
"Status: implemented",
|
|
4951
|
+
"",
|
|
4952
|
+
"Input shape:",
|
|
4953
|
+
" offr_id: offr_ prefixed id or integer id",
|
|
4954
|
+
" confirm: one of yes, true, Y, y",
|
|
4955
|
+
"",
|
|
4956
|
+
"API:",
|
|
4957
|
+
" DELETE /api/v1/accounts/:account_id/offers/:id.json"
|
|
4958
|
+
].join("\n")],
|
|
4959
|
+
|
|
4105
4960
|
["icps", [
|
|
4106
4961
|
"Usage:",
|
|
4107
|
-
" audienti icps list [--json]",
|
|
4962
|
+
" audienti icps list [--tag <tag>] [--json]",
|
|
4963
|
+
" audienti icps show <icp_id> [--json]",
|
|
4108
4964
|
" audienti icps create (--name <text> | --payload <file.json>) [--json]",
|
|
4965
|
+
" audienti icps update <icp_id> [--tags <tag[,tag...]>] [--json]",
|
|
4966
|
+
" audienti icps add-tag <icp_id> <tag> [--json]",
|
|
4967
|
+
" audienti icps remove-tag <icp_id> <tag> [--json]",
|
|
4109
4968
|
"",
|
|
4110
4969
|
"Status: implemented",
|
|
4111
4970
|
"",
|
|
@@ -4115,10 +4974,13 @@ const HELP_TOPICS = new Map([
|
|
|
4115
4974
|
|
|
4116
4975
|
["icps list", [
|
|
4117
4976
|
"Usage:",
|
|
4118
|
-
" audienti icps list [--json] [--account <acct_id>]",
|
|
4977
|
+
" audienti icps list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4119
4978
|
"",
|
|
4120
4979
|
"Status: implemented",
|
|
4121
4980
|
"",
|
|
4981
|
+
"Options:",
|
|
4982
|
+
" --tag <tag> Filter locally to ICPs whose tags include the normalized tag",
|
|
4983
|
+
"",
|
|
4122
4984
|
"API:",
|
|
4123
4985
|
" GET /api/v1/accounts/:account_id/icps.json",
|
|
4124
4986
|
"",
|
|
@@ -4127,13 +4989,14 @@ const HELP_TOPICS = new Map([
|
|
|
4127
4989
|
" prefix_id: icpp_",
|
|
4128
4990
|
" name: string",
|
|
4129
4991
|
" notes: string | null",
|
|
4992
|
+
" tags: [string]",
|
|
4130
4993
|
" discovery_keyword: string | null",
|
|
4131
4994
|
" agent: { id, name } | null"
|
|
4132
4995
|
].join("\n")],
|
|
4133
4996
|
|
|
4134
4997
|
["icps create", [
|
|
4135
4998
|
"Usage:",
|
|
4136
|
-
" audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] | --payload <file.json>) [--json] [--account <acct_id>]",
|
|
4999
|
+
" audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] | --payload <file.json>) [--json] [--account <acct_id>]",
|
|
4137
5000
|
"",
|
|
4138
5001
|
"Status: implemented",
|
|
4139
5002
|
"",
|
|
@@ -4143,6 +5006,7 @@ const HELP_TOPICS = new Map([
|
|
|
4143
5006
|
"Input shape:",
|
|
4144
5007
|
" name: string Required ICP name",
|
|
4145
5008
|
" notes: string | optional",
|
|
5009
|
+
" tags: comma-separated tag list | optional",
|
|
4146
5010
|
" discovery_keyword: string | optional",
|
|
4147
5011
|
" payload: file.json | optional full ICP object using the account API create shape",
|
|
4148
5012
|
"",
|
|
@@ -4154,7 +5018,8 @@ const HELP_TOPICS = new Map([
|
|
|
4154
5018
|
" \"icp\": {",
|
|
4155
5019
|
" \"name\": \"Renewal-stage IT leaders\",",
|
|
4156
5020
|
" \"notes\": \"IT leaders reviewing vendors before renewal or QBR.\",",
|
|
4157
|
-
" \"discovery_keyword\": \"renewal\"",
|
|
5021
|
+
" \"discovery_keyword\": \"renewal\",",
|
|
5022
|
+
" \"tags\": [\"enterprise\", \"renewal\"]",
|
|
4158
5023
|
" }",
|
|
4159
5024
|
" }",
|
|
4160
5025
|
"",
|
|
@@ -4175,6 +5040,90 @@ const HELP_TOPICS = new Map([
|
|
|
4175
5040
|
" }"
|
|
4176
5041
|
].join("\n")],
|
|
4177
5042
|
|
|
5043
|
+
["icps show", [
|
|
5044
|
+
"Usage:",
|
|
5045
|
+
` ${ICPS_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
5046
|
+
"",
|
|
5047
|
+
"Status: implemented",
|
|
5048
|
+
"",
|
|
5049
|
+
"Input shape:",
|
|
5050
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5051
|
+
"",
|
|
5052
|
+
"API:",
|
|
5053
|
+
" GET /api/v1/accounts/:account_id/icps/:id.json"
|
|
5054
|
+
].join("\n")],
|
|
5055
|
+
|
|
5056
|
+
["icps update", [
|
|
5057
|
+
"Usage:",
|
|
5058
|
+
" audienti icps update <icp_id> [--name <text>] [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] [--json] [--account <acct_id>]",
|
|
5059
|
+
"",
|
|
5060
|
+
"Status: implemented",
|
|
5061
|
+
"",
|
|
5062
|
+
"Purpose:",
|
|
5063
|
+
" Update simple ICP fields or replace the ICP's full tag set.",
|
|
5064
|
+
"",
|
|
5065
|
+
"Input shape:",
|
|
5066
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5067
|
+
" name: string | optional",
|
|
5068
|
+
" notes: string | optional",
|
|
5069
|
+
" discovery_keyword: string | optional",
|
|
5070
|
+
" tags: comma-separated tag list | optional",
|
|
5071
|
+
"",
|
|
5072
|
+
"API:",
|
|
5073
|
+
" PATCH /api/v1/accounts/:account_id/icps/:id.json",
|
|
5074
|
+
"",
|
|
5075
|
+
"JSON body:",
|
|
5076
|
+
" {",
|
|
5077
|
+
" \"icp\": {",
|
|
5078
|
+
" \"tags\": [\"enterprise\", \"renewal\"]",
|
|
5079
|
+
" }",
|
|
5080
|
+
" }"
|
|
5081
|
+
].join("\n")],
|
|
5082
|
+
|
|
5083
|
+
["icps add-tag", [
|
|
5084
|
+
"Usage:",
|
|
5085
|
+
" audienti icps add-tag <icp_id> <tag> [--json] [--account <acct_id>]",
|
|
5086
|
+
"",
|
|
5087
|
+
"Status: implemented",
|
|
5088
|
+
"",
|
|
5089
|
+
"Purpose:",
|
|
5090
|
+
" Add one normalized tag to an ICP.",
|
|
5091
|
+
"",
|
|
5092
|
+
"Input shape:",
|
|
5093
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5094
|
+
" tag: string",
|
|
5095
|
+
"",
|
|
5096
|
+
"API:",
|
|
5097
|
+
" POST /api/v1/accounts/:account_id/icps/:id/add_tag.json",
|
|
5098
|
+
"",
|
|
5099
|
+
"JSON body:",
|
|
5100
|
+
" {",
|
|
5101
|
+
" \"tag\": \"enterprise\"",
|
|
5102
|
+
" }"
|
|
5103
|
+
].join("\n")],
|
|
5104
|
+
|
|
5105
|
+
["icps remove-tag", [
|
|
5106
|
+
"Usage:",
|
|
5107
|
+
" audienti icps remove-tag <icp_id> <tag> [--json] [--account <acct_id>]",
|
|
5108
|
+
"",
|
|
5109
|
+
"Status: implemented",
|
|
5110
|
+
"",
|
|
5111
|
+
"Purpose:",
|
|
5112
|
+
" Remove one normalized tag from an ICP.",
|
|
5113
|
+
"",
|
|
5114
|
+
"Input shape:",
|
|
5115
|
+
" icp_id: icpp_ prefixed id or integer id",
|
|
5116
|
+
" tag: string",
|
|
5117
|
+
"",
|
|
5118
|
+
"API:",
|
|
5119
|
+
" DELETE /api/v1/accounts/:account_id/icps/:id/remove_tag.json",
|
|
5120
|
+
"",
|
|
5121
|
+
"JSON body:",
|
|
5122
|
+
" {",
|
|
5123
|
+
" \"tag\": \"enterprise\"",
|
|
5124
|
+
" }"
|
|
5125
|
+
].join("\n")],
|
|
5126
|
+
|
|
4178
5127
|
["companies", [
|
|
4179
5128
|
"Usage:",
|
|
4180
5129
|
" audienti companies search --query <text> [--json]",
|
|
@@ -4206,12 +5155,68 @@ const HELP_TOPICS = new Map([
|
|
|
4206
5155
|
" companies[].location: string | null"
|
|
4207
5156
|
].join("\n")],
|
|
4208
5157
|
|
|
5158
|
+
["tags", [
|
|
5159
|
+
"Usage:",
|
|
5160
|
+
" audienti tags list [--json]",
|
|
5161
|
+
" audienti tags show <tag> [--json]",
|
|
5162
|
+
"",
|
|
5163
|
+
"Status: implemented",
|
|
5164
|
+
"",
|
|
5165
|
+
"Purpose:",
|
|
5166
|
+
" Show the shared vocabulary from ICP tags, list tags, and motion play_tags currently in use.",
|
|
5167
|
+
"",
|
|
5168
|
+
"Run `audienti tags list help` or `audienti tags show help` for output shape."
|
|
5169
|
+
].join("\n")],
|
|
5170
|
+
|
|
5171
|
+
["tags list", [
|
|
5172
|
+
"Usage:",
|
|
5173
|
+
" audienti tags list [--json] [--account <acct_id>]",
|
|
5174
|
+
"",
|
|
5175
|
+
"Status: implemented",
|
|
5176
|
+
"",
|
|
5177
|
+
"Purpose:",
|
|
5178
|
+
" List normalized tags currently used by account ICPs, lists, and motions so new records can match existing labels.",
|
|
5179
|
+
"",
|
|
5180
|
+
"API:",
|
|
5181
|
+
" GET /api/v1/accounts/:account_id/tags.json",
|
|
5182
|
+
"",
|
|
5183
|
+
"Output shape:",
|
|
5184
|
+
" tags[].name: normalized tag string",
|
|
5185
|
+
" tags[].icp_count: number of ICPs using the tag",
|
|
5186
|
+
" tags[].list_count: number of lists using the tag",
|
|
5187
|
+
" tags[].motion_count: number of motions using the tag",
|
|
5188
|
+
" tags[].total_count: icp_count + list_count + motion_count"
|
|
5189
|
+
].join("\n")],
|
|
5190
|
+
|
|
5191
|
+
["tags show", [
|
|
5192
|
+
"Usage:",
|
|
5193
|
+
" audienti tags show <tag> [--json] [--account <acct_id>]",
|
|
5194
|
+
"",
|
|
5195
|
+
"Status: implemented",
|
|
5196
|
+
"",
|
|
5197
|
+
"Purpose:",
|
|
5198
|
+
" Show the ICPs, lists, and motions currently using one normalized tag.",
|
|
5199
|
+
"",
|
|
5200
|
+
"API:",
|
|
5201
|
+
" GET /api/v1/accounts/:account_id/icps.json",
|
|
5202
|
+
" GET /api/v1/accounts/:account_id/lists.json",
|
|
5203
|
+
" GET /api/v1/accounts/:account_id/motions.json",
|
|
5204
|
+
"",
|
|
5205
|
+
"Output shape:",
|
|
5206
|
+
" tag: normalized tag string",
|
|
5207
|
+
" icps[]: ICP rows whose tags include tag",
|
|
5208
|
+
" lists[]: list rows whose tags include tag",
|
|
5209
|
+
" motions[]: motion rows whose play_tags include tag"
|
|
5210
|
+
].join("\n")],
|
|
5211
|
+
|
|
4209
5212
|
["lists", [
|
|
4210
5213
|
"Usage:",
|
|
4211
|
-
" audienti lists list [--json]",
|
|
4212
|
-
" audienti lists create --name <text> [--json]",
|
|
5214
|
+
" audienti lists list [--tag <tag>] [--json]",
|
|
5215
|
+
" audienti lists create --name <text> [--tags <tag[,tag...]>] [--json]",
|
|
4213
5216
|
" audienti lists show <list_id> [--json]",
|
|
4214
|
-
" audienti lists update <list_id> [--json]",
|
|
5217
|
+
" audienti lists update <list_id> [--tags <tag[,tag...]>] [--json]",
|
|
5218
|
+
" audienti lists add-tag <list_id> <tag> [--json]",
|
|
5219
|
+
" audienti lists remove-tag <list_id> <tag> [--json]",
|
|
4215
5220
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json]",
|
|
4216
5221
|
" audienti lists prospects <list_id> [--json]",
|
|
4217
5222
|
" audienti lists add-prospects <list_id> <prsp_id> [prsp_id...] [--json]",
|
|
@@ -4225,10 +5230,13 @@ const HELP_TOPICS = new Map([
|
|
|
4225
5230
|
|
|
4226
5231
|
["lists list", [
|
|
4227
5232
|
"Usage:",
|
|
4228
|
-
" audienti lists list [--json] [--account <acct_id>]",
|
|
5233
|
+
" audienti lists list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4229
5234
|
"",
|
|
4230
5235
|
"Status: implemented",
|
|
4231
5236
|
"",
|
|
5237
|
+
"Options:",
|
|
5238
|
+
" --tag <tag> Filter locally to lists whose tags include the normalized tag",
|
|
5239
|
+
"",
|
|
4232
5240
|
"API:",
|
|
4233
5241
|
" GET /api/v1/accounts/:account_id/lists.json",
|
|
4234
5242
|
"",
|
|
@@ -4239,12 +5247,13 @@ const HELP_TOPICS = new Map([
|
|
|
4239
5247
|
" description: string | null",
|
|
4240
5248
|
" prospect_count: integer",
|
|
4241
5249
|
" protected_system_list: boolean",
|
|
4242
|
-
" hubspot_synced: boolean"
|
|
5250
|
+
" hubspot_synced: boolean",
|
|
5251
|
+
" tags: [string]"
|
|
4243
5252
|
].join("\n")],
|
|
4244
5253
|
|
|
4245
5254
|
["lists create", [
|
|
4246
5255
|
"Usage:",
|
|
4247
|
-
" audienti lists create --name <text> [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
5256
|
+
" audienti lists create --name <text> [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
4248
5257
|
"",
|
|
4249
5258
|
"Status: implemented",
|
|
4250
5259
|
"",
|
|
@@ -4254,6 +5263,7 @@ const HELP_TOPICS = new Map([
|
|
|
4254
5263
|
"Input shape:",
|
|
4255
5264
|
" name: string Required list name",
|
|
4256
5265
|
" description: string | optional",
|
|
5266
|
+
" tags: comma-separated tag list | optional",
|
|
4257
5267
|
" campaign_hook: string | optional",
|
|
4258
5268
|
" audience_note: string | optional",
|
|
4259
5269
|
"",
|
|
@@ -4262,10 +5272,11 @@ const HELP_TOPICS = new Map([
|
|
|
4262
5272
|
"",
|
|
4263
5273
|
"JSON body:",
|
|
4264
5274
|
" {",
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
5275
|
+
" \"list\": {",
|
|
5276
|
+
" \"name\": \"CIO renewal targets\",",
|
|
5277
|
+
" \"description\": \"Accounts to review before QBR outreach.\",",
|
|
5278
|
+
" \"tags\": [\"sarit\", \"pj\"],",
|
|
5279
|
+
" \"campaign_brief\": {",
|
|
4269
5280
|
" \"hook\": \"Vendor accountability before renewal\",",
|
|
4270
5281
|
" \"audience_note\": \"IT leaders running QBRs and renewals\"",
|
|
4271
5282
|
" }",
|
|
@@ -4288,7 +5299,7 @@ const HELP_TOPICS = new Map([
|
|
|
4288
5299
|
|
|
4289
5300
|
["lists update", [
|
|
4290
5301
|
"Usage:",
|
|
4291
|
-
" audienti lists update <list_id> [--name <text>] [--description <text>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
5302
|
+
" audienti lists update <list_id> [--name <text>] [--description <text>] [--tags <tag[,tag...]>] [--campaign-hook <text>] [--audience-note <text>] [--json] [--account <acct_id>]",
|
|
4292
5303
|
"",
|
|
4293
5304
|
"Status: implemented",
|
|
4294
5305
|
"",
|
|
@@ -4299,6 +5310,7 @@ const HELP_TOPICS = new Map([
|
|
|
4299
5310
|
" list_id: list_ prefix id",
|
|
4300
5311
|
" list.name: string | optional",
|
|
4301
5312
|
" list.description: string | optional",
|
|
5313
|
+
" list.tags: comma-separated tag list | optional",
|
|
4302
5314
|
" list.campaign_brief.hook: string | optional",
|
|
4303
5315
|
" list.campaign_brief.audience_note: string | optional",
|
|
4304
5316
|
"",
|
|
@@ -4306,6 +5318,50 @@ const HELP_TOPICS = new Map([
|
|
|
4306
5318
|
" PATCH /api/v1/accounts/:account_id/lists/:id.json"
|
|
4307
5319
|
].join("\n")],
|
|
4308
5320
|
|
|
5321
|
+
["lists add-tag", [
|
|
5322
|
+
"Usage:",
|
|
5323
|
+
` ${LISTS_ADD_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5324
|
+
"",
|
|
5325
|
+
"Status: implemented",
|
|
5326
|
+
"",
|
|
5327
|
+
"Purpose:",
|
|
5328
|
+
" Add one normalized tag to a list without changing prospect membership.",
|
|
5329
|
+
"",
|
|
5330
|
+
"Input shape:",
|
|
5331
|
+
" list_id: list_ prefix id",
|
|
5332
|
+
" tag: string",
|
|
5333
|
+
"",
|
|
5334
|
+
"API:",
|
|
5335
|
+
" POST /api/v1/accounts/:account_id/lists/:id/add_tag.json",
|
|
5336
|
+
"",
|
|
5337
|
+
"JSON body:",
|
|
5338
|
+
" {",
|
|
5339
|
+
" \"tag\": \"sarit\"",
|
|
5340
|
+
" }"
|
|
5341
|
+
].join("\n")],
|
|
5342
|
+
|
|
5343
|
+
["lists remove-tag", [
|
|
5344
|
+
"Usage:",
|
|
5345
|
+
` ${LISTS_REMOVE_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5346
|
+
"",
|
|
5347
|
+
"Status: implemented",
|
|
5348
|
+
"",
|
|
5349
|
+
"Purpose:",
|
|
5350
|
+
" Remove one normalized tag from a list.",
|
|
5351
|
+
"",
|
|
5352
|
+
"Input shape:",
|
|
5353
|
+
" list_id: list_ prefix id",
|
|
5354
|
+
" tag: string",
|
|
5355
|
+
"",
|
|
5356
|
+
"API:",
|
|
5357
|
+
" DELETE /api/v1/accounts/:account_id/lists/:id/remove_tag.json",
|
|
5358
|
+
"",
|
|
5359
|
+
"JSON body:",
|
|
5360
|
+
" {",
|
|
5361
|
+
" \"tag\": \"sarit\"",
|
|
5362
|
+
" }"
|
|
5363
|
+
].join("\n")],
|
|
5364
|
+
|
|
4309
5365
|
["lists delete", [
|
|
4310
5366
|
"Usage:",
|
|
4311
5367
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]",
|
|
@@ -4398,14 +5454,17 @@ const HELP_TOPICS = new Map([
|
|
|
4398
5454
|
|
|
4399
5455
|
["motions", [
|
|
4400
5456
|
"Usage:",
|
|
4401
|
-
" audienti motions list [--json]",
|
|
5457
|
+
" audienti motions list [--tag <tag>] [--json]",
|
|
4402
5458
|
" audienti motions show <motn_id> [--json]",
|
|
4403
5459
|
" audienti motions status <motn_id> [--json]",
|
|
5460
|
+
" audienti motions run-discovery <motn_id> [--target-count <n>] [--json]",
|
|
4404
5461
|
" audienti motions analytics <motn_id> [--window 30d] [--json]",
|
|
4405
5462
|
" audienti motions prospects <motn_id> [--json]",
|
|
4406
5463
|
" audienti motions add-prospects <motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4407
5464
|
" audienti motions create --payload <file.json> [--json]",
|
|
4408
|
-
" audienti motions update <motn_id> --status <draft|preparing|active|paused|archived> [--json]",
|
|
5465
|
+
" audienti motions update <motn_id> [--status <draft|preparing|active|paused|archived>] [--tags <tag[,tag...]>] [--json]",
|
|
5466
|
+
" audienti motions add-tag <motn_id> <tag> [--json]",
|
|
5467
|
+
" audienti motions remove-tag <motn_id> <tag> [--json]",
|
|
4409
5468
|
" audienti motions activate <motn_id> [--json]",
|
|
4410
5469
|
" audienti motions pause <motn_id> [--json]",
|
|
4411
5470
|
" audienti motions archive <motn_id> [--json]",
|
|
@@ -4413,7 +5472,7 @@ const HELP_TOPICS = new Map([
|
|
|
4413
5472
|
" audienti motions clone <motn_id> --name <text> [--json]",
|
|
4414
5473
|
" audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4415
5474
|
"",
|
|
4416
|
-
"Status: read, create, status update, delete, clone, status, and prospect attachment commands implemented",
|
|
5475
|
+
"Status: read, create, status update, delete, clone, status, discovery launch, and prospect attachment commands implemented",
|
|
4417
5476
|
"",
|
|
4418
5477
|
"CLI synonym:",
|
|
4419
5478
|
" `plays` is accepted anywhere `motions` is accepted",
|
|
@@ -4424,10 +5483,13 @@ const HELP_TOPICS = new Map([
|
|
|
4424
5483
|
|
|
4425
5484
|
["motions list", [
|
|
4426
5485
|
"Usage:",
|
|
4427
|
-
" audienti motions list [--json] [--account <acct_id>]",
|
|
5486
|
+
" audienti motions list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4428
5487
|
"",
|
|
4429
5488
|
"Status: implemented",
|
|
4430
5489
|
"",
|
|
5490
|
+
"Options:",
|
|
5491
|
+
" --tag <tag> Filter locally to motions whose play_tags include the normalized tag",
|
|
5492
|
+
"",
|
|
4431
5493
|
"API:",
|
|
4432
5494
|
" GET /api/v1/accounts/:account_id/motions.json",
|
|
4433
5495
|
"",
|
|
@@ -4440,7 +5502,8 @@ const HELP_TOPICS = new Map([
|
|
|
4440
5502
|
" offer.prefix_id: offr_",
|
|
4441
5503
|
" icp.prefix_id: icpp_",
|
|
4442
5504
|
" list.prefix_id: list_ | null",
|
|
4443
|
-
" principal_account_user.id: integer"
|
|
5505
|
+
" principal_account_user.id: integer",
|
|
5506
|
+
" play_tags: [string]"
|
|
4444
5507
|
].join("\n")],
|
|
4445
5508
|
|
|
4446
5509
|
["motions show", [
|
|
@@ -4498,6 +5561,27 @@ const HELP_TOPICS = new Map([
|
|
|
4498
5561
|
" GET /api/v1/accounts/:account_id/analytics/prospects.json?motion_id=:motion_id"
|
|
4499
5562
|
].join("\n")],
|
|
4500
5563
|
|
|
5564
|
+
["motions run-discovery", [
|
|
5565
|
+
"Usage:",
|
|
5566
|
+
` ${MOTIONS_RUN_DISCOVERY_USAGE.slice("Usage: ".length)}`,
|
|
5567
|
+
"",
|
|
5568
|
+
"Status: implemented",
|
|
5569
|
+
"",
|
|
5570
|
+
"Purpose:",
|
|
5571
|
+
" Queue an immediate discovery run for one discovery-capable motion or play.",
|
|
5572
|
+
"",
|
|
5573
|
+
"Options:",
|
|
5574
|
+
" --target-count <n> Override the manual replenishment target count for this launch.",
|
|
5575
|
+
"",
|
|
5576
|
+
"Output shape:",
|
|
5577
|
+
" enqueued: true when Motions::DiscoverJob was queued",
|
|
5578
|
+
" reason: launched | run_in_progress | lock_contention | target_met | enqueue_failed",
|
|
5579
|
+
" target_count: requested target count",
|
|
5580
|
+
"",
|
|
5581
|
+
"API:",
|
|
5582
|
+
" POST /api/v1/accounts/:account_id/motions/:id/run_discovery.json"
|
|
5583
|
+
].join("\n")],
|
|
5584
|
+
|
|
4501
5585
|
["motions prospects", [
|
|
4502
5586
|
"Usage:",
|
|
4503
5587
|
" audienti motions prospects <motn_id> [--json] [--account <acct_id>]",
|
|
@@ -4568,7 +5652,8 @@ const HELP_TOPICS = new Map([
|
|
|
4568
5652
|
" principal_account_user_id: integer | me | optional",
|
|
4569
5653
|
" icp_id: icpp_ prefix id | optional",
|
|
4570
5654
|
" list_id: list_ prefix id | optional",
|
|
4571
|
-
"
|
|
5655
|
+
" play_tags: [string] | optional",
|
|
5656
|
+
" inbound_channels: [linkedin | reddit] | optional",
|
|
4572
5657
|
" lopa_profiles: [{ url: string, source_type: creator | competitor | partner | customer | other }] | optional",
|
|
4573
5658
|
"",
|
|
4574
5659
|
"JSON example:",
|
|
@@ -4579,7 +5664,8 @@ const HELP_TOPICS = new Map([
|
|
|
4579
5664
|
" \"status\": \"draft\",",
|
|
4580
5665
|
" \"offer_id\": \"offr_abc123\",",
|
|
4581
5666
|
" \"principal_account_user_id\": 42,",
|
|
4582
|
-
" \"list_id\": \"list_abc123\"",
|
|
5667
|
+
" \"list_id\": \"list_abc123\",",
|
|
5668
|
+
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
4583
5669
|
" }",
|
|
4584
5670
|
"",
|
|
4585
5671
|
"Behavior:",
|
|
@@ -4622,23 +5708,69 @@ const HELP_TOPICS = new Map([
|
|
|
4622
5708
|
"Status: implemented",
|
|
4623
5709
|
"",
|
|
4624
5710
|
"Purpose:",
|
|
4625
|
-
" Change one motion or play's lifecycle status.",
|
|
5711
|
+
" Change one motion or play's lifecycle status or replace its tag set.",
|
|
4626
5712
|
"",
|
|
4627
5713
|
"Input shape:",
|
|
4628
5714
|
" motn_id: motn_ prefix id",
|
|
4629
|
-
" status: draft | preparing | active | paused | archived",
|
|
5715
|
+
" status: draft | preparing | active | paused | archived | optional",
|
|
5716
|
+
" tags: comma-separated tag list | optional",
|
|
4630
5717
|
"",
|
|
4631
5718
|
"Behavior:",
|
|
4632
|
-
" Updates only the
|
|
5719
|
+
" Updates only the provided fields. Sending --tags replaces the motion's full tag set.",
|
|
4633
5720
|
"",
|
|
4634
5721
|
"API:",
|
|
4635
5722
|
" PATCH /api/v1/accounts/:account_id/motions/:id.json",
|
|
4636
5723
|
"",
|
|
4637
5724
|
"JSON body:",
|
|
4638
5725
|
" {",
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
5726
|
+
" \"motion\": {",
|
|
5727
|
+
" \"status\": \"paused\",",
|
|
5728
|
+
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
5729
|
+
" }",
|
|
5730
|
+
" }"
|
|
5731
|
+
].join("\n")],
|
|
5732
|
+
|
|
5733
|
+
["motions add-tag", [
|
|
5734
|
+
"Usage:",
|
|
5735
|
+
` ${MOTIONS_ADD_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5736
|
+
"",
|
|
5737
|
+
"Status: implemented",
|
|
5738
|
+
"",
|
|
5739
|
+
"Purpose:",
|
|
5740
|
+
" Add one normalized tag to a motion or play.",
|
|
5741
|
+
"",
|
|
5742
|
+
"Input shape:",
|
|
5743
|
+
" motn_id: motn_ prefix id",
|
|
5744
|
+
" tag: string",
|
|
5745
|
+
"",
|
|
5746
|
+
"API:",
|
|
5747
|
+
" POST /api/v1/accounts/:account_id/motions/:id/add_tag.json",
|
|
5748
|
+
"",
|
|
5749
|
+
"JSON body:",
|
|
5750
|
+
" {",
|
|
5751
|
+
" \"tag\": \"sarit\"",
|
|
5752
|
+
" }"
|
|
5753
|
+
].join("\n")],
|
|
5754
|
+
|
|
5755
|
+
["motions remove-tag", [
|
|
5756
|
+
"Usage:",
|
|
5757
|
+
` ${MOTIONS_REMOVE_TAG_USAGE.slice("Usage: ".length)}`,
|
|
5758
|
+
"",
|
|
5759
|
+
"Status: implemented",
|
|
5760
|
+
"",
|
|
5761
|
+
"Purpose:",
|
|
5762
|
+
" Remove one normalized tag from a motion or play.",
|
|
5763
|
+
"",
|
|
5764
|
+
"Input shape:",
|
|
5765
|
+
" motn_id: motn_ prefix id",
|
|
5766
|
+
" tag: string",
|
|
5767
|
+
"",
|
|
5768
|
+
"API:",
|
|
5769
|
+
" DELETE /api/v1/accounts/:account_id/motions/:id/remove_tag.json",
|
|
5770
|
+
"",
|
|
5771
|
+
"JSON body:",
|
|
5772
|
+
" {",
|
|
5773
|
+
" \"tag\": \"sarit\"",
|
|
4642
5774
|
" }"
|
|
4643
5775
|
].join("\n")],
|
|
4644
5776
|
|
|
@@ -4732,8 +5864,12 @@ const HELP_TOPICS = new Map([
|
|
|
4732
5864
|
["prospects", [
|
|
4733
5865
|
"Usage:",
|
|
4734
5866
|
" audienti prospects list [--json] [filters]",
|
|
5867
|
+
" audienti prospects check [--json|--csv] [filters]",
|
|
4735
5868
|
" audienti prospects show <prsp_id> [--json]",
|
|
4736
5869
|
" audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json]",
|
|
5870
|
+
" audienti prospects reject <prsp_id> [--json]",
|
|
5871
|
+
" audienti prospects nurture <prsp_id> [--reason <reason>] [--json]",
|
|
5872
|
+
" audienti prospects restore <prsp_id> [--json]",
|
|
4737
5873
|
" audienti prospects timeline <prsp_id> [--json]",
|
|
4738
5874
|
" audienti prospects message-types <prsp_id> [--json]",
|
|
4739
5875
|
" audienti prospects write <prsp_id> --type <surface_key> [--json]",
|
|
@@ -4747,7 +5883,7 @@ const HELP_TOPICS = new Map([
|
|
|
4747
5883
|
" audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--json]",
|
|
4748
5884
|
" audienti prospects import-status <primp_id> [--json]",
|
|
4749
5885
|
"",
|
|
4750
|
-
"Status: read commands, assignment, per-prospect draft preview, sequence preview, and import implemented
|
|
5886
|
+
"Status: read commands, assignment, disposition, per-prospect draft preview, sequence preview, and import implemented",
|
|
4751
5887
|
"",
|
|
4752
5888
|
"Filters:",
|
|
4753
5889
|
" --query <text>",
|
|
@@ -4816,6 +5952,43 @@ const HELP_TOPICS = new Map([
|
|
|
4816
5952
|
" audienti prospects list --all --csv"
|
|
4817
5953
|
].join("\n")],
|
|
4818
5954
|
|
|
5955
|
+
["prospects check", [
|
|
5956
|
+
"Usage:",
|
|
5957
|
+
" audienti prospects check [--json|--csv] [filters] [--account <acct_id>]",
|
|
5958
|
+
"",
|
|
5959
|
+
"Status: implemented",
|
|
5960
|
+
"",
|
|
5961
|
+
"Description:",
|
|
5962
|
+
" Lists suspect people prospects that do not have a certified company employment citation.",
|
|
5963
|
+
" Imported or reported company text is shown for investigation but does not count as certification.",
|
|
5964
|
+
"",
|
|
5965
|
+
"Filters:",
|
|
5966
|
+
" --query <text> Search name, title, company, email, profile URL",
|
|
5967
|
+
" --motion <motn_id> Filter to a motion",
|
|
5968
|
+
" --play <motn_id> Filter to a play using the same motion relationship",
|
|
5969
|
+
" --list <list_id> Filter to a prospect list",
|
|
5970
|
+
" --stage <stage> Filter to a pipeline stage",
|
|
5971
|
+
" --assigned-user <id|me|unassigned> Filter by assigned account user",
|
|
5972
|
+
" --limit <n> Max rows for one page; with --all it caps total rows up to 1000",
|
|
5973
|
+
" --page <n> 1-based page number",
|
|
5974
|
+
" --offset <n> Row offset for manual pagination",
|
|
5975
|
+
" --all Fetch every matching suspect prospect up to 1000 rows",
|
|
5976
|
+
" --csv Export CSV with app_url for operator review",
|
|
5977
|
+
"",
|
|
5978
|
+
"Output shape:",
|
|
5979
|
+
" prospects[].company_certification.status: missing",
|
|
5980
|
+
" prospects[].company_certification.reason: missing_employment_citation",
|
|
5981
|
+
" prospects[].app_url: product URL for operator inspection",
|
|
5982
|
+
" meta.total_count: total matching suspect prospects",
|
|
5983
|
+
"",
|
|
5984
|
+
"API:",
|
|
5985
|
+
" GET /api/v1/accounts/:account_id/prospects.json?data_quality=missing_certified_company",
|
|
5986
|
+
"",
|
|
5987
|
+
"Examples:",
|
|
5988
|
+
" audienti prospects check --motion <motn_id> --all --csv",
|
|
5989
|
+
" audienti prospects check --assigned-user me --json"
|
|
5990
|
+
].join("\n")],
|
|
5991
|
+
|
|
4819
5992
|
["prospects assign", [
|
|
4820
5993
|
"Usage:",
|
|
4821
5994
|
` ${PROSPECTS_ASSIGN_USAGE.slice("Usage: ".length)}`,
|
|
@@ -4852,6 +6025,48 @@ const HELP_TOPICS = new Map([
|
|
|
4852
6025
|
" GET /api/v1/accounts/:account_id/prospects/:id.json"
|
|
4853
6026
|
].join("\n")],
|
|
4854
6027
|
|
|
6028
|
+
["prospects reject", [
|
|
6029
|
+
"Usage:",
|
|
6030
|
+
` ${PROSPECTS_REJECT_USAGE.slice("Usage: ".length)}`,
|
|
6031
|
+
"",
|
|
6032
|
+
"Status: implemented",
|
|
6033
|
+
"",
|
|
6034
|
+
"Purpose:",
|
|
6035
|
+
" Reject one prospect through the shared disposition and account DNC path.",
|
|
6036
|
+
"",
|
|
6037
|
+
"API:",
|
|
6038
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/reject.json"
|
|
6039
|
+
].join("\n")],
|
|
6040
|
+
|
|
6041
|
+
["prospects nurture", [
|
|
6042
|
+
"Usage:",
|
|
6043
|
+
` ${PROSPECTS_NURTURE_USAGE.slice("Usage: ".length)}`,
|
|
6044
|
+
"",
|
|
6045
|
+
"Status: implemented",
|
|
6046
|
+
"",
|
|
6047
|
+
"Purpose:",
|
|
6048
|
+
" Move one prospect to an inactive nurture disposition through the shared disposition path.",
|
|
6049
|
+
"",
|
|
6050
|
+
"Input shape:",
|
|
6051
|
+
" reason: nurture | non_responsive | not_fit. Defaults to nurture.",
|
|
6052
|
+
"",
|
|
6053
|
+
"API:",
|
|
6054
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/nurture.json"
|
|
6055
|
+
].join("\n")],
|
|
6056
|
+
|
|
6057
|
+
["prospects restore", [
|
|
6058
|
+
"Usage:",
|
|
6059
|
+
` ${PROSPECTS_RESTORE_USAGE.slice("Usage: ".length)}`,
|
|
6060
|
+
"",
|
|
6061
|
+
"Status: implemented",
|
|
6062
|
+
"",
|
|
6063
|
+
"Purpose:",
|
|
6064
|
+
" Restore one rejected or inactive prospect through the shared disposition path.",
|
|
6065
|
+
"",
|
|
6066
|
+
"API:",
|
|
6067
|
+
" POST /api/v1/accounts/:account_id/prospects/:id/restore.json"
|
|
6068
|
+
].join("\n")],
|
|
6069
|
+
|
|
4855
6070
|
["prospects timeline", [
|
|
4856
6071
|
"Usage:",
|
|
4857
6072
|
" audienti prospects timeline <prsp_id> [--json] [--types <post,comment,reaction>] [--limit <n>] [--account <acct_id>]",
|
|
@@ -5209,26 +6424,6 @@ const HELP_TOPICS = new Map([
|
|
|
5209
6424
|
" GET /api/v1/accounts/:account_id/prospect_imports/:id.json"
|
|
5210
6425
|
].join("\n")],
|
|
5211
6426
|
|
|
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
6427
|
["tools", [
|
|
5233
6428
|
"Usage:",
|
|
5234
6429
|
" audienti tools get <email|phone> --url <linkedin_url> [--json]",
|
|
@@ -5358,6 +6553,7 @@ const HELP_TOPICS = new Map([
|
|
|
5358
6553
|
["analytics", [
|
|
5359
6554
|
"Usage:",
|
|
5360
6555
|
" 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]",
|
|
6556
|
+
" audienti analytics dashboard [--cohort-start YYYY-MM-DD --cohort-end YYYY-MM-DD] [--play-tag <tag>] [--motion <motn_id>] [--json]",
|
|
5361
6557
|
" audienti analytics prospects cohort-analysis [--weeks <n>] [--window 24h] [--motion <motn_id>] [--user <account_user_id|email|name|me>] [--json]",
|
|
5362
6558
|
" 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
6559
|
" audienti analytics visibility [--window 24h] [--user <account_user_id|email|name|me>] [--json]",
|
|
@@ -5371,13 +6567,42 @@ const HELP_TOPICS = new Map([
|
|
|
5371
6567
|
" --start <YYYY-MM-DD> --end <YYYY-MM-DD> For user analytics, select the events.created_at activity range instead of --window.",
|
|
5372
6568
|
" --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
6569
|
" --motion <motn_id> For prospect and user analytics, filter AccountProspect.motion_id to one motion/play.",
|
|
6570
|
+
" --play-tag <tag> For dashboard analytics, filter to motions/lists tagged with a campaign tag.",
|
|
5374
6571
|
" --provenance <source> Optional lower-level AccountProspect.intake_source filter.",
|
|
5375
6572
|
" --platform <linkedin|email|gmail> For user analytics, filter events.platform. --channel is accepted as an alias.",
|
|
5376
6573
|
" cohort-analysis loops over recent weekly AccountProspect.created_at cohorts and compares their current stages.",
|
|
5377
6574
|
" --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
6575
|
"",
|
|
5379
6576
|
"Output:",
|
|
5380
|
-
" Account-scoped analytics for prospects, users, visibility engagement, and ContentOps publishing."
|
|
6577
|
+
" Account-scoped analytics for prospects, campaign dashboard counts, users, visibility engagement, and ContentOps publishing."
|
|
6578
|
+
].join("\n")],
|
|
6579
|
+
|
|
6580
|
+
["analytics dashboard", [
|
|
6581
|
+
"Usage:",
|
|
6582
|
+
` ${ANALYTICS_DASHBOARD_USAGE.slice("Usage: ".length)}`,
|
|
6583
|
+
"",
|
|
6584
|
+
"Status: implemented",
|
|
6585
|
+
"",
|
|
6586
|
+
"Purpose:",
|
|
6587
|
+
" Return the dashboard outreach read model through the CLI, including distinct company target counts for a motion, tag, offer, ICP, or user-filtered cohort.",
|
|
6588
|
+
"",
|
|
6589
|
+
"Options:",
|
|
6590
|
+
" --cohort-start <YYYY-MM-DD> --cohort-end <YYYY-MM-DD> Select the AccountProspect.created_at cohort.",
|
|
6591
|
+
" --play-tag <tag> Filter to motions/lists tagged with a campaign tag. --tag is accepted as an alias.",
|
|
6592
|
+
" --motion <motn_id> Filter to one motion/play.",
|
|
6593
|
+
" --offer <offr_id> Filter to one offer.",
|
|
6594
|
+
" --icp <icp_id> Filter to one ICP.",
|
|
6595
|
+
" --user <account_user_id|email|name|me> Filter to prospects assigned to one account user.",
|
|
6596
|
+
"",
|
|
6597
|
+
"Output shape:",
|
|
6598
|
+
" cohort_size: people in the selected cohort",
|
|
6599
|
+
" cohort_company_target_count: distinct company targets in that cohort",
|
|
6600
|
+
" cohort_people_per_company_average: people per company target",
|
|
6601
|
+
" active_cohort_count and active_cohort_company_target_count: still-active campaign cohort counts",
|
|
6602
|
+
" pipeline_stage_counts[]: current stage distribution",
|
|
6603
|
+
"",
|
|
6604
|
+
"API:",
|
|
6605
|
+
" GET /api/v1/accounts/:account_id/analytics/dashboard.json"
|
|
5381
6606
|
].join("\n")],
|
|
5382
6607
|
|
|
5383
6608
|
["analytics prospects", [
|
|
@@ -5529,6 +6754,7 @@ const HELP_TOPICS = new Map([
|
|
|
5529
6754
|
" audienti motions pause <motn_id>",
|
|
5530
6755
|
" audienti motions delete <motn_id> --confirm yes",
|
|
5531
6756
|
" audienti motions status <motn_id>",
|
|
6757
|
+
" audienti motions run-discovery <motn_id>",
|
|
5532
6758
|
"",
|
|
5533
6759
|
"3. Add a new prospect from LinkedIn and poll enrichment",
|
|
5534
6760
|
" audienti lists create --name \"Target list\"",
|
|
@@ -5550,6 +6776,9 @@ const HELP_TOPICS = new Map([
|
|
|
5550
6776
|
" audienti prospects add-profile <prsp_id> --url prospect@example.com",
|
|
5551
6777
|
" audienti prospects report-bad-profile <prsp_id> <prof_id>",
|
|
5552
6778
|
" audienti prospects add-note <prsp_id> --type steer --message \"Meeting will not happen\" --engagement-type action.meeting.canceled",
|
|
6779
|
+
" audienti prospects reject <prsp_id>",
|
|
6780
|
+
" audienti prospects nurture <prsp_id>",
|
|
6781
|
+
" audienti prospects restore <prsp_id>",
|
|
5553
6782
|
" audienti prospects sequence-preview <prsp_id>",
|
|
5554
6783
|
" audienti writer test-run <prsp_id>",
|
|
5555
6784
|
" audienti prospects sequence-export <prsp_id> --csv",
|
|
@@ -5567,6 +6796,7 @@ const HELP_TOPICS = new Map([
|
|
|
5567
6796
|
"7. Inspect account analytics",
|
|
5568
6797
|
" audienti users activity me --window 7d",
|
|
5569
6798
|
" audienti analytics prospects --window 24h",
|
|
6799
|
+
" audienti analytics dashboard --play-tag wine_campaign",
|
|
5570
6800
|
" audienti analytics users --user me --window 30d",
|
|
5571
6801
|
" audienti analytics visibility --window 24h --user me",
|
|
5572
6802
|
" audienti analytics content --window week",
|
|
@@ -5578,7 +6808,6 @@ const HELP_TOPICS = new Map([
|
|
|
5578
6808
|
" Prefer prospects import for new LinkedIn people and add-prospects commands for records that already exist.",
|
|
5579
6809
|
"",
|
|
5580
6810
|
"Current gaps to plan around:",
|
|
5581
|
-
" Prospect disposition still lacks a dedicated CLI mutation.",
|
|
5582
6811
|
" Operator outcome writeback is implemented for prospect rows, not visibility rows."
|
|
5583
6812
|
].join("\n")]
|
|
5584
6813
|
]);
|