@audienti/cli 0.1.10 → 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 +43 -0
- package/README.md +32 -1
- package/package.json +1 -1
- package/src/api-client.js +104 -0
- package/src/cli.js +1488 -130
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
|
-
const USERS_ACTIVITY_USAGE = "Usage: audienti users activity
|
|
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,19 +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 });
|
|
146
|
+
if (normalizedResource === "users" && action === "select") return usersSelect(rest, context, { accountOverride });
|
|
126
147
|
if (normalizedResource === "users" && action === "activity") return usersActivity(rest, context, { accountOverride });
|
|
127
148
|
if (normalizedResource === "offers" && action === "list") return offersList(rest, context, { accountOverride });
|
|
149
|
+
if (normalizedResource === "offers" && action === "show") return offersShow(rest, context, { accountOverride });
|
|
128
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 });
|
|
129
153
|
if (normalizedResource === "icps" && action === "list") return icpsList(rest, context, { accountOverride });
|
|
154
|
+
if (normalizedResource === "icps" && action === "show") return icpsShow(rest, context, { accountOverride });
|
|
130
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 });
|
|
131
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 });
|
|
132
162
|
if (normalizedResource === "lists" && action === "list") return listsList(rest, context, { accountOverride });
|
|
133
163
|
if (normalizedResource === "lists" && action === "create") return listsCreate(rest, context, { accountOverride });
|
|
134
164
|
if (normalizedResource === "lists" && action === "show") return listsShow(rest, context, { accountOverride });
|
|
135
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 });
|
|
136
168
|
if (normalizedResource === "lists" && action === "delete") return listsDelete(rest, context, { accountOverride });
|
|
137
169
|
if (normalizedResource === "lists" && action === "prospects") return listProspects(rest, context, { accountOverride });
|
|
138
170
|
if (normalizedResource === "lists" && action === "add-prospects") return listsAddProspects(rest, context, { accountOverride });
|
|
@@ -145,13 +177,20 @@ async function dispatch(argv, context) {
|
|
|
145
177
|
if (normalizedResource === "motions" && action === "add-prospects") return motionsAddProspects(rest, context, { accountOverride });
|
|
146
178
|
if (normalizedResource === "motions" && action === "create") return motionsCreate(rest, context, { accountOverride });
|
|
147
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 });
|
|
148
182
|
if (normalizedResource === "motions" && ["activate", "pause", "archive"].includes(action)) return motionsStatusShortcut(action, rest, context, { accountOverride });
|
|
149
183
|
if (normalizedResource === "motions" && action === "delete") return motionsDelete(rest, context, { accountOverride });
|
|
150
184
|
if (normalizedResource === "motions" && action === "clone") return motionsClone(rest, context, { accountOverride });
|
|
151
185
|
if (normalizedResource === "motions" && action === "move-prospects") return motionsMoveProspects(rest, context, { accountOverride });
|
|
186
|
+
if (normalizedResource === "motions" && action === "run-discovery") return motionsRunDiscovery(rest, context, { accountOverride });
|
|
152
187
|
if (normalizedResource === "prospects" && action === "list") return prospectsList(rest, context, { accountOverride });
|
|
188
|
+
if (normalizedResource === "prospects" && action === "check") return prospectsCheck(rest, context, { accountOverride });
|
|
153
189
|
if (normalizedResource === "prospects" && action === "show") return prospectsShow(rest, context, { accountOverride });
|
|
154
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 });
|
|
155
194
|
if (normalizedResource === "prospects" && action === "timeline") return prospectsTimeline(rest, context, { accountOverride });
|
|
156
195
|
if (normalizedResource === "prospects" && action === "message-types") return prospectsMessageTypes(rest, context, { accountOverride });
|
|
157
196
|
if (normalizedResource === "prospects" && action === "write") return prospectsWrite(rest, context, { accountOverride });
|
|
@@ -173,6 +212,7 @@ async function dispatch(argv, context) {
|
|
|
173
212
|
if (normalizedResource === "analytics" && ["users", "user"].includes(action)) return analyticsUsers(rest, context, { accountOverride });
|
|
174
213
|
if (normalizedResource === "analytics" && ["visibility", "visops"].includes(action)) return analyticsVisibility(rest, context, { accountOverride });
|
|
175
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 });
|
|
176
216
|
|
|
177
217
|
throw new CommandError(usage(), { exitCode: resource ? 1 : 0 });
|
|
178
218
|
}
|
|
@@ -274,6 +314,14 @@ async function authStatus(args, context, { accountOverride } = {}) {
|
|
|
274
314
|
} else {
|
|
275
315
|
writeLine(context.stdout, "Active account: none selected");
|
|
276
316
|
}
|
|
317
|
+
|
|
318
|
+
const accountUser = defaultAccountUserConfig(config, { accountOverride });
|
|
319
|
+
if (accountUser.id) {
|
|
320
|
+
const name = accountUser.name ? `${accountUser.name} ` : "";
|
|
321
|
+
writeLine(context.stdout, `Default account user: ${name}(${accountUser.id})`);
|
|
322
|
+
} else {
|
|
323
|
+
writeLine(context.stdout, "Default account user: none selected");
|
|
324
|
+
}
|
|
277
325
|
}
|
|
278
326
|
|
|
279
327
|
async function authLogout(args, context) {
|
|
@@ -295,7 +343,10 @@ async function configList(args, context) {
|
|
|
295
343
|
host: config.host || null,
|
|
296
344
|
token: config.token ? maskToken(config.token) : null,
|
|
297
345
|
accountId: config.accountId || null,
|
|
298
|
-
accountName: config.accountName || null
|
|
346
|
+
accountName: config.accountName || null,
|
|
347
|
+
accountUserId: config.accountUserId || null,
|
|
348
|
+
accountUserName: config.accountUserName || null,
|
|
349
|
+
accountUserEmail: config.accountUserEmail || null
|
|
299
350
|
};
|
|
300
351
|
|
|
301
352
|
if (values.json) return writeJson(context.stdout, payload);
|
|
@@ -311,6 +362,58 @@ async function configList(args, context) {
|
|
|
311
362
|
} else {
|
|
312
363
|
writeLine(context.stdout, "Active account: none selected");
|
|
313
364
|
}
|
|
365
|
+
|
|
366
|
+
if (payload.accountUserId) {
|
|
367
|
+
const name = payload.accountUserName ? `${payload.accountUserName} ` : "";
|
|
368
|
+
writeLine(context.stdout, `Default account user: ${name}(${payload.accountUserId})`);
|
|
369
|
+
} else {
|
|
370
|
+
writeLine(context.stdout, "Default account user: none selected");
|
|
371
|
+
}
|
|
372
|
+
}
|
|
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;
|
|
314
417
|
}
|
|
315
418
|
|
|
316
419
|
async function accountsList(args, context, { accountOverride } = {}) {
|
|
@@ -359,7 +462,10 @@ async function accountsSelect(args, context) {
|
|
|
359
462
|
await writeConfig({
|
|
360
463
|
...config,
|
|
361
464
|
accountId: account.prefix_id,
|
|
362
|
-
accountName: account.name
|
|
465
|
+
accountName: account.name,
|
|
466
|
+
accountUserId: account.prefix_id === config.accountId ? config.accountUserId : undefined,
|
|
467
|
+
accountUserName: account.prefix_id === config.accountId ? config.accountUserName : undefined,
|
|
468
|
+
accountUserEmail: account.prefix_id === config.accountId ? config.accountUserEmail : undefined
|
|
363
469
|
}, { env: context.env });
|
|
364
470
|
|
|
365
471
|
writeLine(context.stdout, `Selected account ${account.name} (${account.prefix_id}).`);
|
|
@@ -389,12 +495,55 @@ function resolveAccountSelection(accounts, term) {
|
|
|
389
495
|
throw new CommandError(`Account term "${requested}" matched multiple accounts: ${options}.`);
|
|
390
496
|
}
|
|
391
497
|
|
|
498
|
+
function resolveAccountUserSelection(users, term) {
|
|
499
|
+
const requested = String(term || "").trim();
|
|
500
|
+
if (!requested) return null;
|
|
501
|
+
|
|
502
|
+
if (requested.toLowerCase() === "me") {
|
|
503
|
+
const currentUsers = users.filter((candidate) => candidate.current);
|
|
504
|
+
if (currentUsers.length === 1) return currentUsers[0];
|
|
505
|
+
if (currentUsers.length > 1) throw new CommandError("The token matched multiple current account users.");
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const exactId = users.find((candidate) => String(candidate.id) === requested);
|
|
510
|
+
if (exactId) return exactId;
|
|
511
|
+
|
|
512
|
+
const normalizedRequested = requested.toLowerCase();
|
|
513
|
+
const exactEmail = users.find((candidate) => String(candidate.email || "").toLowerCase() === normalizedRequested);
|
|
514
|
+
if (exactEmail) return exactEmail;
|
|
515
|
+
|
|
516
|
+
const exactName = users.find((candidate) => String(candidate.name || "").toLowerCase() === normalizedRequested);
|
|
517
|
+
if (exactName) return exactName;
|
|
518
|
+
|
|
519
|
+
const matches = users.filter((candidate) => {
|
|
520
|
+
const id = String(candidate.id || "").toLowerCase();
|
|
521
|
+
const name = String(candidate.name || "").toLowerCase();
|
|
522
|
+
const email = String(candidate.email || "").toLowerCase();
|
|
523
|
+
return id.includes(normalizedRequested) || name.includes(normalizedRequested) || email.includes(normalizedRequested);
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
if (matches.length === 1) return matches[0];
|
|
527
|
+
if (matches.length === 0) return null;
|
|
528
|
+
|
|
529
|
+
const options = matches.map(accountUserLabel).join(", ");
|
|
530
|
+
throw new CommandError(`Account user term "${requested}" matched multiple account users: ${options}.`);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function accountUserLabel(accountUser) {
|
|
534
|
+
const name = accountUser?.name || accountUser?.email || `Account user ${accountUser?.id}`;
|
|
535
|
+
return `${name} (${accountUser?.id})`;
|
|
536
|
+
}
|
|
537
|
+
|
|
392
538
|
async function listsList(args, context, { accountOverride } = {}) {
|
|
393
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
394
|
-
|
|
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>]");
|
|
395
544
|
|
|
396
545
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
397
|
-
const lists = await client.lists(accountId);
|
|
546
|
+
const lists = filterRecordsByTag(await client.lists(accountId), values.tag, "tags");
|
|
398
547
|
if (values.json) return writeJson(context.stdout, lists);
|
|
399
548
|
|
|
400
549
|
renderLists(lists, context);
|
|
@@ -411,6 +560,29 @@ async function usersList(args, context, { accountOverride } = {}) {
|
|
|
411
560
|
renderUsers(users, context);
|
|
412
561
|
}
|
|
413
562
|
|
|
563
|
+
async function usersSelect(args, context, { accountOverride } = {}) {
|
|
564
|
+
const { positionals } = parseCommandArgs(args, {});
|
|
565
|
+
if (positionals.length !== 1) throw new CommandError("Usage: audienti users select <account_user_id|email|name|me> [--account <acct_id>]");
|
|
566
|
+
|
|
567
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
568
|
+
const users = await client.users(accountId);
|
|
569
|
+
const accountUser = resolveAccountUserSelection(users, positionals[0]);
|
|
570
|
+
if (!accountUser) {
|
|
571
|
+
throw new CommandError(`Account user ${positionals[0]} does not exist or is not visible in account ${accountId}.`);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
await writeConfig({
|
|
575
|
+
...config,
|
|
576
|
+
accountId,
|
|
577
|
+
accountName: accountOverride && accountOverride !== config.accountId ? undefined : config.accountName,
|
|
578
|
+
accountUserId: String(accountUser.id),
|
|
579
|
+
accountUserName: accountUser.name,
|
|
580
|
+
accountUserEmail: accountUser.email
|
|
581
|
+
}, { env: context.env });
|
|
582
|
+
|
|
583
|
+
writeLine(context.stdout, `Selected account user ${accountUserLabel(accountUser)}.`);
|
|
584
|
+
}
|
|
585
|
+
|
|
414
586
|
async function usersActivity(args, context, { accountOverride } = {}) {
|
|
415
587
|
const { values, positionals } = parseCommandArgs(args, {
|
|
416
588
|
...jsonOptions(),
|
|
@@ -421,10 +593,10 @@ async function usersActivity(args, context, { accountOverride } = {}) {
|
|
|
421
593
|
limit: { type: "string" },
|
|
422
594
|
page: { type: "string" }
|
|
423
595
|
});
|
|
424
|
-
if (positionals.length
|
|
596
|
+
if (positionals.length > 1) throw new CommandError(USERS_ACTIVITY_USAGE);
|
|
425
597
|
|
|
426
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
427
|
-
const payload = await client.userActivity(accountId, positionals[0], compactObject({
|
|
598
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
599
|
+
const payload = await client.userActivity(accountId, resolveAccountUserId(positionals[0] || "me", config, { accountOverride }), compactObject({
|
|
428
600
|
mode: values.mode,
|
|
429
601
|
window: values.window,
|
|
430
602
|
platform: values.platform,
|
|
@@ -448,6 +620,17 @@ async function offersList(args, context, { accountOverride } = {}) {
|
|
|
448
620
|
renderOffers(offers, context);
|
|
449
621
|
}
|
|
450
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
|
+
|
|
451
634
|
async function offersCreate(args, context, { accountOverride } = {}) {
|
|
452
635
|
const { values, positionals } = parseCommandArgs(args, {
|
|
453
636
|
...jsonOptions(),
|
|
@@ -474,27 +657,85 @@ async function offersCreate(args, context, { accountOverride } = {}) {
|
|
|
474
657
|
if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
|
|
475
658
|
}
|
|
476
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
|
+
|
|
477
703
|
async function icpsList(args, context, { accountOverride } = {}) {
|
|
478
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
479
|
-
|
|
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>]");
|
|
480
709
|
|
|
481
710
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
482
|
-
const icps = await client.icps(accountId);
|
|
711
|
+
const icps = filterRecordsByTag(await client.icps(accountId), values.tag, "tags");
|
|
483
712
|
if (values.json) return writeJson(context.stdout, icps);
|
|
484
713
|
|
|
485
714
|
renderIcps(icps, context);
|
|
486
715
|
}
|
|
487
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
|
+
|
|
488
728
|
async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
489
729
|
const { values, positionals } = parseCommandArgs(args, {
|
|
490
730
|
...jsonOptions(),
|
|
491
731
|
payload: { type: "string" },
|
|
492
732
|
name: { type: "string" },
|
|
493
733
|
notes: { type: "string" },
|
|
734
|
+
tags: { type: "string" },
|
|
494
735
|
"discovery-keyword": { type: "string" }
|
|
495
736
|
});
|
|
496
737
|
if (positionals.length > 0) {
|
|
497
|
-
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>]");
|
|
498
739
|
}
|
|
499
740
|
|
|
500
741
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -504,9 +745,58 @@ async function icpsCreate(args, context, { accountOverride } = {}) {
|
|
|
504
745
|
|
|
505
746
|
writeLine(context.stdout, `Created ICP ${display(icp?.name)} (${display(icp?.prefix_id)}).`);
|
|
506
747
|
if (icp?.notes) writeLine(context.stdout, `Notes: ${icp.notes}`);
|
|
748
|
+
if (Array.isArray(icp?.tags)) writeLine(context.stdout, `Tags: ${display(icp.tags.join(", "), "-")}`);
|
|
507
749
|
if (icp?.discovery_keyword) writeLine(context.stdout, `Discovery keyword: ${icp.discovery_keyword}`);
|
|
508
750
|
}
|
|
509
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
|
+
|
|
510
800
|
async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
511
801
|
const { values, positionals } = parseCommandArgs(args, {
|
|
512
802
|
...jsonOptions(),
|
|
@@ -523,16 +813,47 @@ async function companiesSearch(args, context, { accountOverride } = {}) {
|
|
|
523
813
|
renderCompanies(payload, context);
|
|
524
814
|
}
|
|
525
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
|
+
|
|
526
846
|
async function listsCreate(args, context, { accountOverride } = {}) {
|
|
527
847
|
const { values, positionals } = parseCommandArgs(args, {
|
|
528
848
|
...jsonOptions(),
|
|
529
849
|
name: { type: "string" },
|
|
530
850
|
description: { type: "string" },
|
|
851
|
+
tags: { type: "string" },
|
|
531
852
|
"campaign-hook": { type: "string" },
|
|
532
853
|
"audience-note": { type: "string" }
|
|
533
854
|
});
|
|
534
855
|
if (positionals.length > 0 || !values.name) {
|
|
535
|
-
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>]");
|
|
536
857
|
}
|
|
537
858
|
|
|
538
859
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -544,6 +865,7 @@ async function listsCreate(args, context, { accountOverride } = {}) {
|
|
|
544
865
|
list: compactObject({
|
|
545
866
|
name: values.name,
|
|
546
867
|
description: values.description,
|
|
868
|
+
tags: tagList(values.tags),
|
|
547
869
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
548
870
|
})
|
|
549
871
|
});
|
|
@@ -569,13 +891,14 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
569
891
|
...jsonOptions(),
|
|
570
892
|
name: { type: "string" },
|
|
571
893
|
description: { type: "string" },
|
|
894
|
+
tags: { type: "string" },
|
|
572
895
|
"campaign-hook": { type: "string" },
|
|
573
896
|
"audience-note": { type: "string" }
|
|
574
897
|
});
|
|
575
898
|
const hasCampaignUpdate = values["campaign-hook"] || values["audience-note"];
|
|
576
|
-
const hasUpdateField = values.name || values.description || hasCampaignUpdate;
|
|
899
|
+
const hasUpdateField = values.name || values.description || values.tags !== undefined || hasCampaignUpdate;
|
|
577
900
|
if (positionals.length !== 1 || !hasUpdateField) {
|
|
578
|
-
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>]");
|
|
579
902
|
}
|
|
580
903
|
|
|
581
904
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
@@ -587,6 +910,7 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
587
910
|
list: compactObject({
|
|
588
911
|
name: values.name,
|
|
589
912
|
description: values.description,
|
|
913
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
590
914
|
campaign_brief: Object.keys(campaignBrief).length > 0 ? campaignBrief : undefined
|
|
591
915
|
})
|
|
592
916
|
});
|
|
@@ -596,6 +920,26 @@ async function listsUpdate(args, context, { accountOverride } = {}) {
|
|
|
596
920
|
if (payload?.description) writeLine(context.stdout, `Description: ${payload.description}`);
|
|
597
921
|
}
|
|
598
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
|
+
|
|
599
943
|
async function listsDelete(args, context, { accountOverride } = {}) {
|
|
600
944
|
const { values, positionals } = parseCommandArgs(args, {
|
|
601
945
|
...jsonOptions(),
|
|
@@ -695,11 +1039,14 @@ async function listsRemoveProspects(args, context, { accountOverride } = {}) {
|
|
|
695
1039
|
}
|
|
696
1040
|
|
|
697
1041
|
async function motionsList(args, context, { accountOverride } = {}) {
|
|
698
|
-
const { values, positionals } = parseCommandArgs(args,
|
|
699
|
-
|
|
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>]");
|
|
700
1047
|
|
|
701
1048
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
702
|
-
const motions = await client.motions(accountId);
|
|
1049
|
+
const motions = filterRecordsByTag(await client.motions(accountId), values.tag, "play_tags");
|
|
703
1050
|
if (values.json) return writeJson(context.stdout, motions);
|
|
704
1051
|
|
|
705
1052
|
renderMotions(motions, context);
|
|
@@ -727,6 +1074,22 @@ async function motionsStatus(args, context, { accountOverride } = {}) {
|
|
|
727
1074
|
renderMotionStatus(status, context);
|
|
728
1075
|
}
|
|
729
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
|
+
|
|
730
1093
|
async function motionsAnalytics(args, context, { accountOverride } = {}) {
|
|
731
1094
|
const { values, positionals } = parseCommandArgs(args, {
|
|
732
1095
|
...jsonOptions(),
|
|
@@ -788,11 +1151,11 @@ async function motionsAddProspects(args, context, { accountOverride } = {}) {
|
|
|
788
1151
|
}
|
|
789
1152
|
|
|
790
1153
|
const [motionId, ...prospectIds] = positionals;
|
|
791
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1154
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
792
1155
|
const { payload, rejected } = await performBulkMutation(() =>
|
|
793
1156
|
client.addMotionProspects(accountId, motionId, compactObject({
|
|
794
1157
|
prospect_ids: prospectIds,
|
|
795
|
-
assigned_user_id: values["assigned-user"]
|
|
1158
|
+
assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
|
|
796
1159
|
})));
|
|
797
1160
|
if (values.json) {
|
|
798
1161
|
writeJson(context.stdout, payload);
|
|
@@ -844,13 +1207,26 @@ async function motionsDelete(args, context, { accountOverride } = {}) {
|
|
|
844
1207
|
async function motionsUpdate(args, context, { accountOverride } = {}) {
|
|
845
1208
|
const { values, positionals } = parseCommandArgs(args, {
|
|
846
1209
|
...jsonOptions(),
|
|
847
|
-
status: { type: "string" }
|
|
1210
|
+
status: { type: "string" },
|
|
1211
|
+
tags: { type: "string" }
|
|
848
1212
|
});
|
|
849
|
-
|
|
1213
|
+
const hasUpdateField = values.status || values.tags !== undefined;
|
|
1214
|
+
if (positionals.length !== 1 || !hasUpdateField) {
|
|
850
1215
|
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
851
1216
|
}
|
|
852
1217
|
|
|
853
|
-
|
|
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);
|
|
854
1230
|
}
|
|
855
1231
|
|
|
856
1232
|
async function motionsStatusShortcut(action, args, context, { accountOverride } = {}) {
|
|
@@ -869,10 +1245,7 @@ async function motionsStatusShortcut(action, args, context, { accountOverride }
|
|
|
869
1245
|
}
|
|
870
1246
|
|
|
871
1247
|
async function updateMotionStatus(motionId, status, context, { accountOverride, json } = {}) {
|
|
872
|
-
const normalizedStatus =
|
|
873
|
-
if (!MOTION_STATUS_VALUES.has(normalizedStatus)) {
|
|
874
|
-
throw new CommandError(MOTIONS_UPDATE_USAGE);
|
|
875
|
-
}
|
|
1248
|
+
const normalizedStatus = normalizeMotionStatus(status);
|
|
876
1249
|
|
|
877
1250
|
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
878
1251
|
const motion = await client.updateMotion(accountId, motionId, {
|
|
@@ -886,6 +1259,37 @@ async function updateMotionStatus(motionId, status, context, { accountOverride,
|
|
|
886
1259
|
renderMotion(motion, context);
|
|
887
1260
|
}
|
|
888
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
|
+
|
|
889
1293
|
async function motionsClone(args, context, { accountOverride } = {}) {
|
|
890
1294
|
const { values, positionals } = parseCommandArgs(args, {
|
|
891
1295
|
...jsonOptions(),
|
|
@@ -933,7 +1337,47 @@ async function motionsMoveProspects(args, context, { accountOverride } = {}) {
|
|
|
933
1337
|
}
|
|
934
1338
|
|
|
935
1339
|
async function prospectsList(args, context, { accountOverride } = {}) {
|
|
936
|
-
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 {
|
|
937
1381
|
...jsonOptions(),
|
|
938
1382
|
all: { type: "boolean" },
|
|
939
1383
|
csv: { type: "boolean" },
|
|
@@ -950,16 +1394,18 @@ async function prospectsList(args, context, { accountOverride } = {}) {
|
|
|
950
1394
|
page: { type: "string" },
|
|
951
1395
|
profiles: { type: "boolean" },
|
|
952
1396
|
wide: { type: "boolean" }
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
function validateProspectFilterValues(values) {
|
|
956
1401
|
if (values.page && values.offset) throw new CommandError("Choose one pagination mode: use either --page or --offset.");
|
|
957
1402
|
if (values.all && (values.page || values.offset)) throw new CommandError("--all cannot be combined with --page or --offset.");
|
|
958
1403
|
if (values.motion && values.play) throw new CommandError("Choose one motion filter: use either --motion or --play.");
|
|
959
1404
|
if (values.company && values["company-profile"]) throw new CommandError("Choose one company filter: use either --company or --company-profile.");
|
|
1405
|
+
}
|
|
960
1406
|
|
|
961
|
-
|
|
962
|
-
|
|
1407
|
+
function prospectQueryFromValues(values, config, { accountOverride } = {}) {
|
|
1408
|
+
return compactObject({
|
|
963
1409
|
query: values.query,
|
|
964
1410
|
company: values.company,
|
|
965
1411
|
company_profile_id: values["company-profile"],
|
|
@@ -967,19 +1413,12 @@ async function prospectsList(args, context, { accountOverride } = {}) {
|
|
|
967
1413
|
play_id: values.play,
|
|
968
1414
|
list_id: values.list,
|
|
969
1415
|
stage: values.stage,
|
|
970
|
-
assigned_user_id: values["assigned-user"],
|
|
1416
|
+
assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride }),
|
|
971
1417
|
limit: values.limit,
|
|
972
1418
|
offset: values.offset,
|
|
973
1419
|
page: values.page,
|
|
974
1420
|
include_profiles: values.profiles
|
|
975
1421
|
});
|
|
976
|
-
const payload = values.all ?
|
|
977
|
-
await fetchAllProspects(client, accountId, query, { totalLimit: parseProspectTotalLimit(values.limit) }) :
|
|
978
|
-
await client.prospects(accountId, query);
|
|
979
|
-
if (values.json) return writeJson(context.stdout, payload);
|
|
980
|
-
if (values.csv) return writeLine(context.stdout, prospectsToCsv(payload?.prospects || []));
|
|
981
|
-
|
|
982
|
-
renderProspects(payload, context, { wide: values.wide || values.all, profiles: values.profiles });
|
|
983
1422
|
}
|
|
984
1423
|
|
|
985
1424
|
async function prospectsAssign(args, context, { accountOverride } = {}) {
|
|
@@ -991,11 +1430,12 @@ async function prospectsAssign(args, context, { accountOverride } = {}) {
|
|
|
991
1430
|
throw new CommandError(PROSPECTS_ASSIGN_USAGE);
|
|
992
1431
|
}
|
|
993
1432
|
|
|
994
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1433
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1434
|
+
const assignedUserId = resolveAccountUserId(values["assigned-user"], config, { accountOverride });
|
|
995
1435
|
const { payload, rejected } = await performBulkMutation(() =>
|
|
996
1436
|
client.assignProspects(accountId, {
|
|
997
1437
|
prospect_ids: positionals,
|
|
998
|
-
assigned_user_id:
|
|
1438
|
+
assigned_user_id: assignedUserId
|
|
999
1439
|
}));
|
|
1000
1440
|
if (values.json) {
|
|
1001
1441
|
writeJson(context.stdout, payload);
|
|
@@ -1004,7 +1444,7 @@ async function prospectsAssign(args, context, { accountOverride } = {}) {
|
|
|
1004
1444
|
|
|
1005
1445
|
const successLabel = values["assigned-user"] === "unassign" ?
|
|
1006
1446
|
`Unassigned ${successCount(payload)} prospects.` :
|
|
1007
|
-
`Assigned ${successCount(payload)} prospects to ${display(
|
|
1447
|
+
`Assigned ${successCount(payload)} prospects to ${display(assignedUserId)}.`;
|
|
1008
1448
|
renderBulkMutationResult(payload, context, {
|
|
1009
1449
|
successLabel,
|
|
1010
1450
|
zeroSuccessLabel: "No prospects were assigned."
|
|
@@ -1023,6 +1463,32 @@ async function prospectsShow(args, context, { accountOverride } = {}) {
|
|
|
1023
1463
|
renderProspect(prospect, context);
|
|
1024
1464
|
}
|
|
1025
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
|
+
|
|
1026
1492
|
async function prospectsTimeline(args, context, { accountOverride } = {}) {
|
|
1027
1493
|
const { values, positionals } = parseCommandArgs(args, {
|
|
1028
1494
|
...jsonOptions(),
|
|
@@ -1413,12 +1879,12 @@ async function prospectsImport(args, context, { accountOverride } = {}) {
|
|
|
1413
1879
|
throw new CommandError("Usage: audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]");
|
|
1414
1880
|
}
|
|
1415
1881
|
|
|
1416
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1882
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1417
1883
|
const payload = await client.prospectImport(accountId, compactObject({
|
|
1418
1884
|
linkedin_url: positionals[0],
|
|
1419
1885
|
list_id: values.list,
|
|
1420
1886
|
motion_id: values.motion,
|
|
1421
|
-
assigned_user_id: values["assigned-user"]
|
|
1887
|
+
assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
|
|
1422
1888
|
}));
|
|
1423
1889
|
if (values.json) return writeJson(context.stdout, payload);
|
|
1424
1890
|
|
|
@@ -1440,7 +1906,7 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
|
|
|
1440
1906
|
const rows = await readProspectImportBatchFile(values.file);
|
|
1441
1907
|
if (rows.length === 0) throw new CommandError("Import batch file did not contain any prospects.");
|
|
1442
1908
|
|
|
1443
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1909
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1444
1910
|
const result = {
|
|
1445
1911
|
summary: {
|
|
1446
1912
|
total: rows.length,
|
|
@@ -1456,7 +1922,7 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
|
|
|
1456
1922
|
linkedin_url: row.linkedin_url,
|
|
1457
1923
|
list_id: row.list_id || values.list,
|
|
1458
1924
|
motion_id: row.motion_id || values.motion,
|
|
1459
|
-
assigned_user_id: row.assigned_user_id || values["assigned-user"]
|
|
1925
|
+
assigned_user_id: resolveAccountUserId(row.assigned_user_id || values["assigned-user"], config, { accountOverride })
|
|
1460
1926
|
});
|
|
1461
1927
|
|
|
1462
1928
|
try {
|
|
@@ -1614,8 +2080,8 @@ async function analyticsProspects(args, context, { accountOverride } = {}) {
|
|
|
1614
2080
|
const { values, positionals } = parseCommandArgs(args, analyticsProspectsOptions());
|
|
1615
2081
|
if (positionals.length > 0) throw new CommandError(ANALYTICS_PROSPECTS_USAGE);
|
|
1616
2082
|
|
|
1617
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1618
|
-
const payload = await client.analyticsProspects(accountId, analyticsQuery(values));
|
|
2083
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2084
|
+
const payload = await client.analyticsProspects(accountId, analyticsQuery(values, config, { accountOverride }));
|
|
1619
2085
|
if (values.json) return writeJson(context.stdout, payload);
|
|
1620
2086
|
|
|
1621
2087
|
renderAnalyticsProspects(payload, context);
|
|
@@ -1634,13 +2100,13 @@ async function analyticsProspectsCohortAnalysis(args, context, { accountOverride
|
|
|
1634
2100
|
|
|
1635
2101
|
const weeks = normalizedCohortAnalysisWeeks(values.weeks);
|
|
1636
2102
|
const cohorts = weeklyCohorts({ weeks, now: currentDate(context) });
|
|
1637
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
2103
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
1638
2104
|
const rows = [];
|
|
1639
2105
|
|
|
1640
2106
|
for (const cohort of cohorts) {
|
|
1641
2107
|
const payload = await client.analyticsProspects(accountId, compactObject({
|
|
1642
2108
|
window: values.window,
|
|
1643
|
-
account_user_id: values.user,
|
|
2109
|
+
account_user_id: resolveAccountUserId(values.user, config, { accountOverride }),
|
|
1644
2110
|
motion_id: values.motion,
|
|
1645
2111
|
provenance: values.provenance,
|
|
1646
2112
|
cohort_start: cohort.start_date,
|
|
@@ -1669,8 +2135,8 @@ async function analyticsUsers(args, context, { accountOverride } = {}) {
|
|
|
1669
2135
|
validateDatePair(values.start, values.end, "--start", "--end");
|
|
1670
2136
|
validateDatePair(values["cohort-start"], values["cohort-end"], "--cohort-start", "--cohort-end");
|
|
1671
2137
|
|
|
1672
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1673
|
-
const payload = await client.analyticsUsers(accountId, analyticsUsersQuery(values));
|
|
2138
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2139
|
+
const payload = await client.analyticsUsers(accountId, analyticsUsersQuery(values, config, { accountOverride }));
|
|
1674
2140
|
if (values.json) return writeJson(context.stdout, payload);
|
|
1675
2141
|
|
|
1676
2142
|
renderAnalyticsUsers(payload, context);
|
|
@@ -1680,8 +2146,8 @@ async function analyticsVisibility(args, context, { accountOverride } = {}) {
|
|
|
1680
2146
|
const { values, positionals } = parseCommandArgs(args, analyticsOptions());
|
|
1681
2147
|
if (positionals.length > 0) throw new CommandError("Usage: audienti analytics visibility [--window 24h] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]");
|
|
1682
2148
|
|
|
1683
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1684
|
-
const payload = await client.analyticsVisibility(accountId, analyticsQuery(values));
|
|
2149
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2150
|
+
const payload = await client.analyticsVisibility(accountId, analyticsQuery(values, config, { accountOverride }));
|
|
1685
2151
|
if (values.json) return writeJson(context.stdout, payload);
|
|
1686
2152
|
|
|
1687
2153
|
renderAnalyticsVisibility(payload, context);
|
|
@@ -1691,13 +2157,25 @@ async function analyticsContent(args, context, { accountOverride } = {}) {
|
|
|
1691
2157
|
const { values, positionals } = parseCommandArgs(args, analyticsOptions());
|
|
1692
2158
|
if (positionals.length > 0) throw new CommandError("Usage: audienti analytics content [--window 24h] [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]");
|
|
1693
2159
|
|
|
1694
|
-
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1695
|
-
const payload = await client.analyticsContent(accountId, analyticsQuery(values));
|
|
2160
|
+
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
2161
|
+
const payload = await client.analyticsContent(accountId, analyticsQuery(values, config, { accountOverride }));
|
|
1696
2162
|
if (values.json) return writeJson(context.stdout, payload);
|
|
1697
2163
|
|
|
1698
2164
|
renderAnalyticsContent(payload, context);
|
|
1699
2165
|
}
|
|
1700
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
|
+
|
|
1701
2179
|
function parseCommandArgs(args, options) {
|
|
1702
2180
|
try {
|
|
1703
2181
|
return parseArgs({
|
|
@@ -1739,6 +2217,25 @@ async function requireAccountContext(context, { accountOverride } = {}) {
|
|
|
1739
2217
|
};
|
|
1740
2218
|
}
|
|
1741
2219
|
|
|
2220
|
+
function resolveAccountUserId(value, config = {}, { accountOverride } = {}) {
|
|
2221
|
+
const rawValue = String(value || "").trim();
|
|
2222
|
+
if (!rawValue) return undefined;
|
|
2223
|
+
if (rawValue.toLowerCase() !== "me") return rawValue;
|
|
2224
|
+
|
|
2225
|
+
return defaultAccountUserConfig(config, { accountOverride }).id || "me";
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
function defaultAccountUserConfig(config = {}, { accountOverride } = {}) {
|
|
2229
|
+
if (!config.accountUserId) return {};
|
|
2230
|
+
if (accountOverride && accountOverride !== config.accountId) return {};
|
|
2231
|
+
|
|
2232
|
+
return {
|
|
2233
|
+
id: String(config.accountUserId),
|
|
2234
|
+
name: config.accountUserName,
|
|
2235
|
+
email: config.accountUserEmail
|
|
2236
|
+
};
|
|
2237
|
+
}
|
|
2238
|
+
|
|
1742
2239
|
function clientFromConfig(config, context) {
|
|
1743
2240
|
return new AudientiClient({
|
|
1744
2241
|
host: config.host || DEFAULT_HOST,
|
|
@@ -1850,21 +2347,35 @@ function analyticsUsersOptions() {
|
|
|
1850
2347
|
};
|
|
1851
2348
|
}
|
|
1852
2349
|
|
|
1853
|
-
function
|
|
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
|
+
|
|
2364
|
+
function analyticsQuery(values, config = {}, { accountOverride } = {}) {
|
|
1854
2365
|
return compactObject({
|
|
1855
2366
|
window: values.window,
|
|
1856
2367
|
cohort_start: values["cohort-start"],
|
|
1857
2368
|
cohort_end: values["cohort-end"],
|
|
1858
2369
|
motion_id: values.motion,
|
|
1859
2370
|
provenance: values.provenance,
|
|
1860
|
-
account_user_id: values.user
|
|
2371
|
+
account_user_id: resolveAccountUserId(values.user, config, { accountOverride })
|
|
1861
2372
|
});
|
|
1862
2373
|
}
|
|
1863
2374
|
|
|
1864
|
-
function analyticsUsersQuery(values) {
|
|
2375
|
+
function analyticsUsersQuery(values, config = {}, { accountOverride } = {}) {
|
|
1865
2376
|
const hasDateRange = Boolean(values.start || values.end);
|
|
1866
2377
|
return compactObject({
|
|
1867
|
-
account_user_id: values.user || "me",
|
|
2378
|
+
account_user_id: resolveAccountUserId(values.user || "me", config, { accountOverride }),
|
|
1868
2379
|
window: hasDateRange ? undefined : (values.window || "30d"),
|
|
1869
2380
|
start_date: values.start,
|
|
1870
2381
|
end_date: values.end,
|
|
@@ -1876,6 +2387,18 @@ function analyticsUsersQuery(values) {
|
|
|
1876
2387
|
});
|
|
1877
2388
|
}
|
|
1878
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
|
+
|
|
1879
2402
|
function validateDatePair(start, end, startFlag, endFlag) {
|
|
1880
2403
|
if ((start && !end) || (!start && end)) {
|
|
1881
2404
|
throw new CommandError(`${startFlag} and ${endFlag} must be provided together.`);
|
|
@@ -1981,26 +2504,125 @@ function provenancePayload(provenance) {
|
|
|
1981
2504
|
|
|
1982
2505
|
function compactObject(object) {
|
|
1983
2506
|
return Object.fromEntries(
|
|
1984
|
-
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
|
+
})
|
|
1985
2513
|
);
|
|
1986
2514
|
}
|
|
1987
2515
|
|
|
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"
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
const bodyText = await response.text();
|
|
2533
|
+
const body = bodyText ? JSON.parse(bodyText) : {};
|
|
2534
|
+
|
|
2535
|
+
if (!response.ok) {
|
|
2536
|
+
throw new Error(body?.error || body?.message || `Registry returned HTTP ${response.status}.`);
|
|
2537
|
+
}
|
|
2538
|
+
|
|
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
|
+
|
|
1988
2609
|
async function icpCreatePayload(values) {
|
|
1989
2610
|
if (values.payload) {
|
|
1990
|
-
if (values.name || values.notes || values["discovery-keyword"]) {
|
|
1991
|
-
throw new CommandError("Choose one ICP input mode: either --payload <file.json> or the simple --name/--notes/--discovery-keyword flags.");
|
|
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.");
|
|
1992
2613
|
}
|
|
1993
2614
|
|
|
1994
2615
|
return readJsonPayload(values.payload);
|
|
1995
2616
|
}
|
|
1996
2617
|
|
|
1997
2618
|
if (!values.name) {
|
|
1998
|
-
throw new CommandError("Usage: audienti icps create (--name <text> [--notes <text>] [--discovery-keyword <text>] | --payload <file.json>) [--json] [--account <acct_id>]");
|
|
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>]");
|
|
1999
2620
|
}
|
|
2000
2621
|
|
|
2001
2622
|
return compactObject({
|
|
2002
2623
|
name: values.name,
|
|
2003
2624
|
notes: values.notes,
|
|
2625
|
+
tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
2004
2626
|
discovery_keyword: values["discovery-keyword"]
|
|
2005
2627
|
});
|
|
2006
2628
|
}
|
|
@@ -2141,6 +2763,17 @@ function normalizePositiveInteger(value) {
|
|
|
2141
2763
|
return parsed;
|
|
2142
2764
|
}
|
|
2143
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
|
+
|
|
2144
2777
|
function normalizeLookupType(value) {
|
|
2145
2778
|
const normalized = String(value || "").trim().toLowerCase();
|
|
2146
2779
|
if (normalized === "email" || normalized === "phone") return normalized;
|
|
@@ -2289,6 +2922,22 @@ function writeJson(stream, value) {
|
|
|
2289
2922
|
writeLine(stream, JSON.stringify(value, null, 2));
|
|
2290
2923
|
}
|
|
2291
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
|
+
|
|
2292
2941
|
async function sleep(milliseconds) {
|
|
2293
2942
|
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
2294
2943
|
}
|
|
@@ -2305,9 +2954,48 @@ function renderLists(lists, context) {
|
|
|
2305
2954
|
function renderList(list, context) {
|
|
2306
2955
|
writeLine(context.stdout, `List: ${display(list?.name)} (${display(list?.prefix_id)})`);
|
|
2307
2956
|
writeLine(context.stdout, `Prospects: ${display(list?.prospect_count, 0)}`);
|
|
2957
|
+
if (Array.isArray(list?.tags)) writeLine(context.stdout, `Tags: ${display(list.tags.join(", "), "-")}`);
|
|
2308
2958
|
if (list?.description) writeLine(context.stdout, `Description: ${list.description}`);
|
|
2309
2959
|
}
|
|
2310
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
|
+
|
|
2311
2999
|
function renderUsers(users, context) {
|
|
2312
3000
|
if (!Array.isArray(users) || users.length === 0) return writeLine(context.stdout, "No account users found.");
|
|
2313
3001
|
|
|
@@ -2377,16 +3065,23 @@ function renderOffers(offers, context) {
|
|
|
2377
3065
|
}
|
|
2378
3066
|
}
|
|
2379
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
|
+
|
|
2380
3074
|
function renderIcps(icps, context) {
|
|
2381
3075
|
if (!Array.isArray(icps) || icps.length === 0) return writeLine(context.stdout, "No ICPs found.");
|
|
2382
3076
|
|
|
2383
|
-
writeLine(context.stdout, "ICP ID\tNAME\tDISCOVERY KEYWORD\tAGENT");
|
|
3077
|
+
writeLine(context.stdout, "ICP ID\tNAME\tTAGS\tDISCOVERY KEYWORD\tAGENT");
|
|
2384
3078
|
for (const icp of icps) {
|
|
2385
3079
|
writeLine(
|
|
2386
3080
|
context.stdout,
|
|
2387
3081
|
[
|
|
2388
3082
|
display(icp.prefix_id),
|
|
2389
3083
|
display(icp.name),
|
|
3084
|
+
display(Array.isArray(icp.tags) && icp.tags.length > 0 ? icp.tags.join(",") : "-"),
|
|
2390
3085
|
display(icp.discovery_keyword),
|
|
2391
3086
|
display(icp.agent?.name)
|
|
2392
3087
|
].join("\t")
|
|
@@ -2394,6 +3089,14 @@ function renderIcps(icps, context) {
|
|
|
2394
3089
|
}
|
|
2395
3090
|
}
|
|
2396
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
|
+
|
|
2397
3100
|
function renderCompanies(payload, context) {
|
|
2398
3101
|
const companies = Array.isArray(payload?.companies) ? payload.companies : [];
|
|
2399
3102
|
if (companies.length === 0) return writeLine(context.stdout, "No companies found.");
|
|
@@ -2458,6 +3161,7 @@ function renderMotion(motion, context) {
|
|
|
2458
3161
|
if (motion?.offer?.name) writeLine(context.stdout, `Offer: ${motion.offer.name} (${display(motion.offer.prefix_id)})`);
|
|
2459
3162
|
if (motion?.icp?.name) writeLine(context.stdout, `ICP: ${motion.icp.name} (${display(motion.icp.prefix_id)})`);
|
|
2460
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(", "), "-")}`);
|
|
2461
3165
|
if (motion?.principal_account_user?.id) {
|
|
2462
3166
|
writeLine(
|
|
2463
3167
|
context.stdout,
|
|
@@ -2525,6 +3229,27 @@ function renderProspects(payload, context, { wide = false, profiles = false } =
|
|
|
2525
3229
|
}
|
|
2526
3230
|
}
|
|
2527
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
|
+
|
|
2528
3253
|
function renderProspect(prospect, context) {
|
|
2529
3254
|
writeLine(context.stdout, `Prospect: ${display(prospect?.display_name || prospect?.name)} (${display(prospect?.prefix_id)})`);
|
|
2530
3255
|
if (prospect?.company) writeLine(context.stdout, `Company: ${prospect.company}`);
|
|
@@ -2534,6 +3259,21 @@ function renderProspect(prospect, context) {
|
|
|
2534
3259
|
if (nextActionLabel(prospect?.queue)) writeLine(context.stdout, `Next action: ${nextActionLabel(prospect.queue)}`);
|
|
2535
3260
|
}
|
|
2536
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
|
+
|
|
2537
3277
|
function renderProspectTimeline(payload, context) {
|
|
2538
3278
|
const prospect = payload?.prospect || {};
|
|
2539
3279
|
const timeline = Array.isArray(payload?.timeline) ? payload.timeline : [];
|
|
@@ -3056,6 +3796,32 @@ function renderMotionAnalytics(payload, context) {
|
|
|
3056
3796
|
writeCountTable(context, "Prospect cohorts by produced day", payload?.prospects_by_day, ["DATE", "PRODUCED", "ACTIVE", "ACTIVE %", "INACTIVE", "STAGES"], dailyProspectRow);
|
|
3057
3797
|
}
|
|
3058
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
|
+
|
|
3059
3825
|
function renderAnalyticsProspectCohortAnalysis(payload, context) {
|
|
3060
3826
|
const cohorts = Array.isArray(payload?.cohorts) ? payload.cohorts : [];
|
|
3061
3827
|
writeLine(context.stdout, `Prospect cohort analysis (${display(payload?.weeks, cohorts.length)} weeks)`);
|
|
@@ -3130,6 +3896,19 @@ function writeAnalyticsScope(payload, context) {
|
|
|
3130
3896
|
}
|
|
3131
3897
|
}
|
|
3132
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
|
+
|
|
3133
3912
|
function writeAnalyticsPlatform(payload, context) {
|
|
3134
3913
|
if (!payload?.platform) return;
|
|
3135
3914
|
|
|
@@ -3569,6 +4348,77 @@ function prospectsToCsv(prospects) {
|
|
|
3569
4348
|
].join("\n");
|
|
3570
4349
|
}
|
|
3571
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
|
+
|
|
3572
4422
|
function sequenceExportRowsToCsv(rows) {
|
|
3573
4423
|
return [
|
|
3574
4424
|
SEQUENCE_EXPORT_CSV_COLUMNS.join(","),
|
|
@@ -3662,22 +4512,28 @@ const HELP_TOPICS = new Map([
|
|
|
3662
4512
|
" audienti auth token <token> Save an API token",
|
|
3663
4513
|
" audienti accounts list See accounts available to this token",
|
|
3664
4514
|
" audienti accounts select <acct_id> Use one account by default",
|
|
4515
|
+
" audienti users select <user> Use one account user by default",
|
|
3665
4516
|
" audienti help agent-workflows Common agent/operator paths",
|
|
3666
4517
|
"",
|
|
3667
4518
|
"Work areas:",
|
|
3668
4519
|
" Setup & identity",
|
|
3669
4520
|
" audienti auth status",
|
|
3670
4521
|
" audienti config list",
|
|
4522
|
+
" audienti update check",
|
|
3671
4523
|
" audienti users list",
|
|
3672
|
-
" audienti users
|
|
4524
|
+
" audienti users select <account_user_id|email|name|me>",
|
|
4525
|
+
" audienti users activity [account_user_id|me]",
|
|
3673
4526
|
"",
|
|
3674
4527
|
" Motions / plays",
|
|
3675
4528
|
" audienti motions list",
|
|
3676
4529
|
" audienti motions show <motn_id>",
|
|
3677
4530
|
" audienti motions analytics <motn_id>",
|
|
4531
|
+
" audienti motions run-discovery <motn_id>",
|
|
3678
4532
|
" audienti motions prospects <motn_id>",
|
|
3679
4533
|
" audienti motions create --payload <file.json>",
|
|
3680
|
-
" 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>",
|
|
3681
4537
|
" audienti motions activate <motn_id>",
|
|
3682
4538
|
" audienti motions pause <motn_id>",
|
|
3683
4539
|
" audienti motions delete <motn_id> --confirm <yes|true|Y|y>",
|
|
@@ -3687,8 +4543,12 @@ const HELP_TOPICS = new Map([
|
|
|
3687
4543
|
"",
|
|
3688
4544
|
" Prospects",
|
|
3689
4545
|
" audienti prospects list [filters]",
|
|
4546
|
+
" audienti prospects check [filters]",
|
|
3690
4547
|
" audienti prospects show <prsp_id>",
|
|
3691
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>",
|
|
3692
4552
|
" audienti prospects timeline <prsp_id>",
|
|
3693
4553
|
" audienti prospects import <linkedin_url> [--motion <motn_id>]",
|
|
3694
4554
|
" audienti prospects import-batch --file <csv|jsonl|json>",
|
|
@@ -3696,10 +4556,21 @@ const HELP_TOPICS = new Map([
|
|
|
3696
4556
|
" audienti prospects add-profile <prsp_id> --url <profile_url|email|phone>",
|
|
3697
4557
|
"",
|
|
3698
4558
|
" Lists & targeting inputs",
|
|
3699
|
-
" audienti lists list",
|
|
4559
|
+
" audienti lists list [--tag <tag>]",
|
|
3700
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>",
|
|
3701
4565
|
" audienti offers list",
|
|
3702
|
-
" 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>",
|
|
3703
4574
|
" audienti companies search --query <text>",
|
|
3704
4575
|
"",
|
|
3705
4576
|
" Writer",
|
|
@@ -3714,6 +4585,7 @@ const HELP_TOPICS = new Map([
|
|
|
3714
4585
|
"",
|
|
3715
4586
|
" Analytics",
|
|
3716
4587
|
" audienti analytics prospects --window 24h",
|
|
4588
|
+
" audienti analytics dashboard --play-tag <tag>",
|
|
3717
4589
|
" audienti analytics prospects cohort-analysis --weeks 4 --motion <motn_id>",
|
|
3718
4590
|
" audienti analytics users --user me --window 30d",
|
|
3719
4591
|
" audienti analytics visibility --window 24h --user me",
|
|
@@ -3728,6 +4600,7 @@ const HELP_TOPICS = new Map([
|
|
|
3728
4600
|
" Inspect a prospect: audienti prospects show <prsp_id> --json",
|
|
3729
4601
|
" Preview a campaign: audienti writer test-run <prsp_id>",
|
|
3730
4602
|
" Analyze one motion: audienti motions analytics <motn_id>",
|
|
4603
|
+
" Count one campaign: audienti analytics dashboard --play-tag <tag>",
|
|
3731
4604
|
" Audit your work: audienti analytics users --user me --window 30d",
|
|
3732
4605
|
"",
|
|
3733
4606
|
"Global options:",
|
|
@@ -3789,7 +4662,8 @@ const HELP_TOPICS = new Map([
|
|
|
3789
4662
|
" Host: string",
|
|
3790
4663
|
" Token: masked string",
|
|
3791
4664
|
" User: string",
|
|
3792
|
-
" Active account: account name and acct_ id, or none selected"
|
|
4665
|
+
" Active account: account name and acct_ id, or none selected",
|
|
4666
|
+
" Default account user: account user name and id, or none selected"
|
|
3793
4667
|
].join("\n")],
|
|
3794
4668
|
|
|
3795
4669
|
["auth logout", [
|
|
@@ -3823,7 +4697,48 @@ const HELP_TOPICS = new Map([
|
|
|
3823
4697
|
" Exists: yes|no",
|
|
3824
4698
|
" Host: string or none",
|
|
3825
4699
|
" Token: masked string or none",
|
|
3826
|
-
" Active account: account name and acct_ id, or none selected"
|
|
4700
|
+
" Active account: account name and acct_ id, or none selected",
|
|
4701
|
+
" Default account user: account user name and id, or none selected"
|
|
4702
|
+
].join("\n")],
|
|
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"
|
|
3827
4742
|
].join("\n")],
|
|
3828
4743
|
|
|
3829
4744
|
["accounts", [
|
|
@@ -3868,12 +4783,13 @@ const HELP_TOPICS = new Map([
|
|
|
3868
4783
|
["users", [
|
|
3869
4784
|
"Usage:",
|
|
3870
4785
|
" audienti users list [--json]",
|
|
3871
|
-
" audienti users
|
|
4786
|
+
" audienti users select <account_user_id|email|name|me>",
|
|
4787
|
+
" audienti users activity [account_user_id|me] [--json]",
|
|
3872
4788
|
"",
|
|
3873
4789
|
"Status: implemented",
|
|
3874
4790
|
"",
|
|
3875
4791
|
"Purpose:",
|
|
3876
|
-
" List the account users that can be used as motion principals or assignees.",
|
|
4792
|
+
" List and select the account users that can be used as motion principals or assignees.",
|
|
3877
4793
|
"",
|
|
3878
4794
|
"CLI synonym:",
|
|
3879
4795
|
" `principals` is accepted anywhere `users` is accepted"
|
|
@@ -3897,6 +4813,24 @@ const HELP_TOPICS = new Map([
|
|
|
3897
4813
|
" current: boolean"
|
|
3898
4814
|
].join("\n")],
|
|
3899
4815
|
|
|
4816
|
+
["users select", [
|
|
4817
|
+
"Usage:",
|
|
4818
|
+
" audienti users select <account_user_id|email|name|me> [--account <acct_id>]",
|
|
4819
|
+
"",
|
|
4820
|
+
"Status: implemented",
|
|
4821
|
+
"",
|
|
4822
|
+
"Purpose:",
|
|
4823
|
+
" Save a default account user for commands that accept `me` or default to the current operator.",
|
|
4824
|
+
"",
|
|
4825
|
+
"Behavior:",
|
|
4826
|
+
" Validates the account user against `audienti users list` for the active account before saving.",
|
|
4827
|
+
" Selecting a different account with `audienti accounts select` clears the saved account user.",
|
|
4828
|
+
" Passing --account selects the account user for that account and makes it the active account.",
|
|
4829
|
+
"",
|
|
4830
|
+
"API:",
|
|
4831
|
+
" GET /api/v1/accounts/:account_id/users.json"
|
|
4832
|
+
].join("\n")],
|
|
4833
|
+
|
|
3900
4834
|
["users activity", [
|
|
3901
4835
|
"Usage:",
|
|
3902
4836
|
` ${USERS_ACTIVITY_USAGE.slice("Usage: ".length)}`,
|
|
@@ -3907,7 +4841,7 @@ const HELP_TOPICS = new Map([
|
|
|
3907
4841
|
" Inspect one workspace user's outbound activity feed and action summary.",
|
|
3908
4842
|
"",
|
|
3909
4843
|
"Input shape:",
|
|
3910
|
-
" account_user_id: integer account user id, or me for the
|
|
4844
|
+
" account_user_id: integer account user id, or me for the saved default account user when configured",
|
|
3911
4845
|
" mode: actor | account_usage",
|
|
3912
4846
|
" window: 24h | 7d | 30d",
|
|
3913
4847
|
" platform: linkedin | email | gmail",
|
|
@@ -3919,12 +4853,15 @@ const HELP_TOPICS = new Map([
|
|
|
3919
4853
|
["offers", [
|
|
3920
4854
|
"Usage:",
|
|
3921
4855
|
" audienti offers list [--json]",
|
|
4856
|
+
" audienti offers show <offr_id> [--json]",
|
|
3922
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]",
|
|
3923
4860
|
"",
|
|
3924
4861
|
"Status: implemented",
|
|
3925
4862
|
"",
|
|
3926
4863
|
"Purpose:",
|
|
3927
|
-
"
|
|
4864
|
+
" Manage the offers available to the current account so an agent can choose offer_id for motion creation."
|
|
3928
4865
|
].join("\n")],
|
|
3929
4866
|
|
|
3930
4867
|
["offers list", [
|
|
@@ -3974,10 +4911,60 @@ const HELP_TOPICS = new Map([
|
|
|
3974
4911
|
" }"
|
|
3975
4912
|
].join("\n")],
|
|
3976
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
|
+
|
|
3977
4960
|
["icps", [
|
|
3978
4961
|
"Usage:",
|
|
3979
|
-
" audienti icps list [--json]",
|
|
4962
|
+
" audienti icps list [--tag <tag>] [--json]",
|
|
4963
|
+
" audienti icps show <icp_id> [--json]",
|
|
3980
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]",
|
|
3981
4968
|
"",
|
|
3982
4969
|
"Status: implemented",
|
|
3983
4970
|
"",
|
|
@@ -3987,10 +4974,13 @@ const HELP_TOPICS = new Map([
|
|
|
3987
4974
|
|
|
3988
4975
|
["icps list", [
|
|
3989
4976
|
"Usage:",
|
|
3990
|
-
" audienti icps list [--json] [--account <acct_id>]",
|
|
4977
|
+
" audienti icps list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
3991
4978
|
"",
|
|
3992
4979
|
"Status: implemented",
|
|
3993
4980
|
"",
|
|
4981
|
+
"Options:",
|
|
4982
|
+
" --tag <tag> Filter locally to ICPs whose tags include the normalized tag",
|
|
4983
|
+
"",
|
|
3994
4984
|
"API:",
|
|
3995
4985
|
" GET /api/v1/accounts/:account_id/icps.json",
|
|
3996
4986
|
"",
|
|
@@ -3999,13 +4989,14 @@ const HELP_TOPICS = new Map([
|
|
|
3999
4989
|
" prefix_id: icpp_",
|
|
4000
4990
|
" name: string",
|
|
4001
4991
|
" notes: string | null",
|
|
4992
|
+
" tags: [string]",
|
|
4002
4993
|
" discovery_keyword: string | null",
|
|
4003
4994
|
" agent: { id, name } | null"
|
|
4004
4995
|
].join("\n")],
|
|
4005
4996
|
|
|
4006
4997
|
["icps create", [
|
|
4007
4998
|
"Usage:",
|
|
4008
|
-
" 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>]",
|
|
4009
5000
|
"",
|
|
4010
5001
|
"Status: implemented",
|
|
4011
5002
|
"",
|
|
@@ -4015,6 +5006,7 @@ const HELP_TOPICS = new Map([
|
|
|
4015
5006
|
"Input shape:",
|
|
4016
5007
|
" name: string Required ICP name",
|
|
4017
5008
|
" notes: string | optional",
|
|
5009
|
+
" tags: comma-separated tag list | optional",
|
|
4018
5010
|
" discovery_keyword: string | optional",
|
|
4019
5011
|
" payload: file.json | optional full ICP object using the account API create shape",
|
|
4020
5012
|
"",
|
|
@@ -4026,7 +5018,8 @@ const HELP_TOPICS = new Map([
|
|
|
4026
5018
|
" \"icp\": {",
|
|
4027
5019
|
" \"name\": \"Renewal-stage IT leaders\",",
|
|
4028
5020
|
" \"notes\": \"IT leaders reviewing vendors before renewal or QBR.\",",
|
|
4029
|
-
" \"discovery_keyword\": \"renewal\"",
|
|
5021
|
+
" \"discovery_keyword\": \"renewal\",",
|
|
5022
|
+
" \"tags\": [\"enterprise\", \"renewal\"]",
|
|
4030
5023
|
" }",
|
|
4031
5024
|
" }",
|
|
4032
5025
|
"",
|
|
@@ -4047,6 +5040,90 @@ const HELP_TOPICS = new Map([
|
|
|
4047
5040
|
" }"
|
|
4048
5041
|
].join("\n")],
|
|
4049
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
|
+
|
|
4050
5127
|
["companies", [
|
|
4051
5128
|
"Usage:",
|
|
4052
5129
|
" audienti companies search --query <text> [--json]",
|
|
@@ -4078,12 +5155,68 @@ const HELP_TOPICS = new Map([
|
|
|
4078
5155
|
" companies[].location: string | null"
|
|
4079
5156
|
].join("\n")],
|
|
4080
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
|
+
|
|
4081
5212
|
["lists", [
|
|
4082
5213
|
"Usage:",
|
|
4083
|
-
" audienti lists list [--json]",
|
|
4084
|
-
" audienti lists create --name <text> [--json]",
|
|
5214
|
+
" audienti lists list [--tag <tag>] [--json]",
|
|
5215
|
+
" audienti lists create --name <text> [--tags <tag[,tag...]>] [--json]",
|
|
4085
5216
|
" audienti lists show <list_id> [--json]",
|
|
4086
|
-
" 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]",
|
|
4087
5220
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json]",
|
|
4088
5221
|
" audienti lists prospects <list_id> [--json]",
|
|
4089
5222
|
" audienti lists add-prospects <list_id> <prsp_id> [prsp_id...] [--json]",
|
|
@@ -4097,10 +5230,13 @@ const HELP_TOPICS = new Map([
|
|
|
4097
5230
|
|
|
4098
5231
|
["lists list", [
|
|
4099
5232
|
"Usage:",
|
|
4100
|
-
" audienti lists list [--json] [--account <acct_id>]",
|
|
5233
|
+
" audienti lists list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4101
5234
|
"",
|
|
4102
5235
|
"Status: implemented",
|
|
4103
5236
|
"",
|
|
5237
|
+
"Options:",
|
|
5238
|
+
" --tag <tag> Filter locally to lists whose tags include the normalized tag",
|
|
5239
|
+
"",
|
|
4104
5240
|
"API:",
|
|
4105
5241
|
" GET /api/v1/accounts/:account_id/lists.json",
|
|
4106
5242
|
"",
|
|
@@ -4111,12 +5247,13 @@ const HELP_TOPICS = new Map([
|
|
|
4111
5247
|
" description: string | null",
|
|
4112
5248
|
" prospect_count: integer",
|
|
4113
5249
|
" protected_system_list: boolean",
|
|
4114
|
-
" hubspot_synced: boolean"
|
|
5250
|
+
" hubspot_synced: boolean",
|
|
5251
|
+
" tags: [string]"
|
|
4115
5252
|
].join("\n")],
|
|
4116
5253
|
|
|
4117
5254
|
["lists create", [
|
|
4118
5255
|
"Usage:",
|
|
4119
|
-
" 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>]",
|
|
4120
5257
|
"",
|
|
4121
5258
|
"Status: implemented",
|
|
4122
5259
|
"",
|
|
@@ -4126,6 +5263,7 @@ const HELP_TOPICS = new Map([
|
|
|
4126
5263
|
"Input shape:",
|
|
4127
5264
|
" name: string Required list name",
|
|
4128
5265
|
" description: string | optional",
|
|
5266
|
+
" tags: comma-separated tag list | optional",
|
|
4129
5267
|
" campaign_hook: string | optional",
|
|
4130
5268
|
" audience_note: string | optional",
|
|
4131
5269
|
"",
|
|
@@ -4134,10 +5272,11 @@ const HELP_TOPICS = new Map([
|
|
|
4134
5272
|
"",
|
|
4135
5273
|
"JSON body:",
|
|
4136
5274
|
" {",
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
5275
|
+
" \"list\": {",
|
|
5276
|
+
" \"name\": \"CIO renewal targets\",",
|
|
5277
|
+
" \"description\": \"Accounts to review before QBR outreach.\",",
|
|
5278
|
+
" \"tags\": [\"sarit\", \"pj\"],",
|
|
5279
|
+
" \"campaign_brief\": {",
|
|
4141
5280
|
" \"hook\": \"Vendor accountability before renewal\",",
|
|
4142
5281
|
" \"audience_note\": \"IT leaders running QBRs and renewals\"",
|
|
4143
5282
|
" }",
|
|
@@ -4160,7 +5299,7 @@ const HELP_TOPICS = new Map([
|
|
|
4160
5299
|
|
|
4161
5300
|
["lists update", [
|
|
4162
5301
|
"Usage:",
|
|
4163
|
-
" 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>]",
|
|
4164
5303
|
"",
|
|
4165
5304
|
"Status: implemented",
|
|
4166
5305
|
"",
|
|
@@ -4171,6 +5310,7 @@ const HELP_TOPICS = new Map([
|
|
|
4171
5310
|
" list_id: list_ prefix id",
|
|
4172
5311
|
" list.name: string | optional",
|
|
4173
5312
|
" list.description: string | optional",
|
|
5313
|
+
" list.tags: comma-separated tag list | optional",
|
|
4174
5314
|
" list.campaign_brief.hook: string | optional",
|
|
4175
5315
|
" list.campaign_brief.audience_note: string | optional",
|
|
4176
5316
|
"",
|
|
@@ -4178,6 +5318,50 @@ const HELP_TOPICS = new Map([
|
|
|
4178
5318
|
" PATCH /api/v1/accounts/:account_id/lists/:id.json"
|
|
4179
5319
|
].join("\n")],
|
|
4180
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
|
+
|
|
4181
5365
|
["lists delete", [
|
|
4182
5366
|
"Usage:",
|
|
4183
5367
|
" audienti lists delete <list_id> --confirm <yes|true|Y|y> [--json] [--account <acct_id>]",
|
|
@@ -4270,14 +5454,17 @@ const HELP_TOPICS = new Map([
|
|
|
4270
5454
|
|
|
4271
5455
|
["motions", [
|
|
4272
5456
|
"Usage:",
|
|
4273
|
-
" audienti motions list [--json]",
|
|
5457
|
+
" audienti motions list [--tag <tag>] [--json]",
|
|
4274
5458
|
" audienti motions show <motn_id> [--json]",
|
|
4275
5459
|
" audienti motions status <motn_id> [--json]",
|
|
5460
|
+
" audienti motions run-discovery <motn_id> [--target-count <n>] [--json]",
|
|
4276
5461
|
" audienti motions analytics <motn_id> [--window 30d] [--json]",
|
|
4277
5462
|
" audienti motions prospects <motn_id> [--json]",
|
|
4278
5463
|
" audienti motions add-prospects <motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4279
5464
|
" audienti motions create --payload <file.json> [--json]",
|
|
4280
|
-
" 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]",
|
|
4281
5468
|
" audienti motions activate <motn_id> [--json]",
|
|
4282
5469
|
" audienti motions pause <motn_id> [--json]",
|
|
4283
5470
|
" audienti motions archive <motn_id> [--json]",
|
|
@@ -4285,7 +5472,7 @@ const HELP_TOPICS = new Map([
|
|
|
4285
5472
|
" audienti motions clone <motn_id> --name <text> [--json]",
|
|
4286
5473
|
" audienti motions move-prospects <source_motn_id> --target <target_motn_id> <prsp_id> [prsp_id...] [--json]",
|
|
4287
5474
|
"",
|
|
4288
|
-
"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",
|
|
4289
5476
|
"",
|
|
4290
5477
|
"CLI synonym:",
|
|
4291
5478
|
" `plays` is accepted anywhere `motions` is accepted",
|
|
@@ -4296,10 +5483,13 @@ const HELP_TOPICS = new Map([
|
|
|
4296
5483
|
|
|
4297
5484
|
["motions list", [
|
|
4298
5485
|
"Usage:",
|
|
4299
|
-
" audienti motions list [--json] [--account <acct_id>]",
|
|
5486
|
+
" audienti motions list [--tag <tag>] [--json] [--account <acct_id>]",
|
|
4300
5487
|
"",
|
|
4301
5488
|
"Status: implemented",
|
|
4302
5489
|
"",
|
|
5490
|
+
"Options:",
|
|
5491
|
+
" --tag <tag> Filter locally to motions whose play_tags include the normalized tag",
|
|
5492
|
+
"",
|
|
4303
5493
|
"API:",
|
|
4304
5494
|
" GET /api/v1/accounts/:account_id/motions.json",
|
|
4305
5495
|
"",
|
|
@@ -4312,7 +5502,8 @@ const HELP_TOPICS = new Map([
|
|
|
4312
5502
|
" offer.prefix_id: offr_",
|
|
4313
5503
|
" icp.prefix_id: icpp_",
|
|
4314
5504
|
" list.prefix_id: list_ | null",
|
|
4315
|
-
" principal_account_user.id: integer"
|
|
5505
|
+
" principal_account_user.id: integer",
|
|
5506
|
+
" play_tags: [string]"
|
|
4316
5507
|
].join("\n")],
|
|
4317
5508
|
|
|
4318
5509
|
["motions show", [
|
|
@@ -4370,6 +5561,27 @@ const HELP_TOPICS = new Map([
|
|
|
4370
5561
|
" GET /api/v1/accounts/:account_id/analytics/prospects.json?motion_id=:motion_id"
|
|
4371
5562
|
].join("\n")],
|
|
4372
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
|
+
|
|
4373
5585
|
["motions prospects", [
|
|
4374
5586
|
"Usage:",
|
|
4375
5587
|
" audienti motions prospects <motn_id> [--json] [--account <acct_id>]",
|
|
@@ -4440,7 +5652,8 @@ const HELP_TOPICS = new Map([
|
|
|
4440
5652
|
" principal_account_user_id: integer | me | optional",
|
|
4441
5653
|
" icp_id: icpp_ prefix id | optional",
|
|
4442
5654
|
" list_id: list_ prefix id | optional",
|
|
4443
|
-
"
|
|
5655
|
+
" play_tags: [string] | optional",
|
|
5656
|
+
" inbound_channels: [linkedin | reddit] | optional",
|
|
4444
5657
|
" lopa_profiles: [{ url: string, source_type: creator | competitor | partner | customer | other }] | optional",
|
|
4445
5658
|
"",
|
|
4446
5659
|
"JSON example:",
|
|
@@ -4451,7 +5664,8 @@ const HELP_TOPICS = new Map([
|
|
|
4451
5664
|
" \"status\": \"draft\",",
|
|
4452
5665
|
" \"offer_id\": \"offr_abc123\",",
|
|
4453
5666
|
" \"principal_account_user_id\": 42,",
|
|
4454
|
-
" \"list_id\": \"list_abc123\"",
|
|
5667
|
+
" \"list_id\": \"list_abc123\",",
|
|
5668
|
+
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
4455
5669
|
" }",
|
|
4456
5670
|
"",
|
|
4457
5671
|
"Behavior:",
|
|
@@ -4494,23 +5708,69 @@ const HELP_TOPICS = new Map([
|
|
|
4494
5708
|
"Status: implemented",
|
|
4495
5709
|
"",
|
|
4496
5710
|
"Purpose:",
|
|
4497
|
-
" Change one motion or play's lifecycle status.",
|
|
5711
|
+
" Change one motion or play's lifecycle status or replace its tag set.",
|
|
4498
5712
|
"",
|
|
4499
5713
|
"Input shape:",
|
|
4500
5714
|
" motn_id: motn_ prefix id",
|
|
4501
|
-
" status: draft | preparing | active | paused | archived",
|
|
5715
|
+
" status: draft | preparing | active | paused | archived | optional",
|
|
5716
|
+
" tags: comma-separated tag list | optional",
|
|
4502
5717
|
"",
|
|
4503
5718
|
"Behavior:",
|
|
4504
|
-
" Updates only the
|
|
5719
|
+
" Updates only the provided fields. Sending --tags replaces the motion's full tag set.",
|
|
4505
5720
|
"",
|
|
4506
5721
|
"API:",
|
|
4507
5722
|
" PATCH /api/v1/accounts/:account_id/motions/:id.json",
|
|
4508
5723
|
"",
|
|
4509
5724
|
"JSON body:",
|
|
4510
5725
|
" {",
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
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\"",
|
|
4514
5774
|
" }"
|
|
4515
5775
|
].join("\n")],
|
|
4516
5776
|
|
|
@@ -4604,8 +5864,12 @@ const HELP_TOPICS = new Map([
|
|
|
4604
5864
|
["prospects", [
|
|
4605
5865
|
"Usage:",
|
|
4606
5866
|
" audienti prospects list [--json] [filters]",
|
|
5867
|
+
" audienti prospects check [--json|--csv] [filters]",
|
|
4607
5868
|
" audienti prospects show <prsp_id> [--json]",
|
|
4608
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]",
|
|
4609
5873
|
" audienti prospects timeline <prsp_id> [--json]",
|
|
4610
5874
|
" audienti prospects message-types <prsp_id> [--json]",
|
|
4611
5875
|
" audienti prospects write <prsp_id> --type <surface_key> [--json]",
|
|
@@ -4619,7 +5883,7 @@ const HELP_TOPICS = new Map([
|
|
|
4619
5883
|
" audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--json]",
|
|
4620
5884
|
" audienti prospects import-status <primp_id> [--json]",
|
|
4621
5885
|
"",
|
|
4622
|
-
"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",
|
|
4623
5887
|
"",
|
|
4624
5888
|
"Filters:",
|
|
4625
5889
|
" --query <text>",
|
|
@@ -4688,6 +5952,43 @@ const HELP_TOPICS = new Map([
|
|
|
4688
5952
|
" audienti prospects list --all --csv"
|
|
4689
5953
|
].join("\n")],
|
|
4690
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
|
+
|
|
4691
5992
|
["prospects assign", [
|
|
4692
5993
|
"Usage:",
|
|
4693
5994
|
` ${PROSPECTS_ASSIGN_USAGE.slice("Usage: ".length)}`,
|
|
@@ -4724,6 +6025,48 @@ const HELP_TOPICS = new Map([
|
|
|
4724
6025
|
" GET /api/v1/accounts/:account_id/prospects/:id.json"
|
|
4725
6026
|
].join("\n")],
|
|
4726
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
|
+
|
|
4727
6070
|
["prospects timeline", [
|
|
4728
6071
|
"Usage:",
|
|
4729
6072
|
" audienti prospects timeline <prsp_id> [--json] [--types <post,comment,reaction>] [--limit <n>] [--account <acct_id>]",
|
|
@@ -5081,26 +6424,6 @@ const HELP_TOPICS = new Map([
|
|
|
5081
6424
|
" GET /api/v1/accounts/:account_id/prospect_imports/:id.json"
|
|
5082
6425
|
].join("\n")],
|
|
5083
6426
|
|
|
5084
|
-
["prospects disposition", [
|
|
5085
|
-
"Usage:",
|
|
5086
|
-
" audienti prospects disposition <prsp_id> --payload <file.json> [--account <acct_id>]",
|
|
5087
|
-
"",
|
|
5088
|
-
"Status: planned",
|
|
5089
|
-
"",
|
|
5090
|
-
"Input shape:",
|
|
5091
|
-
" action: defer | nurture | reject | restore",
|
|
5092
|
-
" reason: string | optional",
|
|
5093
|
-
" delay_until: ISO8601 datetime | optional",
|
|
5094
|
-
" note: string | optional",
|
|
5095
|
-
"",
|
|
5096
|
-
"JSON example:",
|
|
5097
|
-
" {",
|
|
5098
|
-
" \"action\": \"nurture\",",
|
|
5099
|
-
" \"reason\": \"not_a_fit\",",
|
|
5100
|
-
" \"note\": \"Not a fit for this motion right now.\"",
|
|
5101
|
-
" }"
|
|
5102
|
-
].join("\n")],
|
|
5103
|
-
|
|
5104
6427
|
["tools", [
|
|
5105
6428
|
"Usage:",
|
|
5106
6429
|
" audienti tools get <email|phone> --url <linkedin_url> [--json]",
|
|
@@ -5230,6 +6553,7 @@ const HELP_TOPICS = new Map([
|
|
|
5230
6553
|
["analytics", [
|
|
5231
6554
|
"Usage:",
|
|
5232
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]",
|
|
5233
6557
|
" audienti analytics prospects cohort-analysis [--weeks <n>] [--window 24h] [--motion <motn_id>] [--user <account_user_id|email|name|me>] [--json]",
|
|
5234
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]",
|
|
5235
6559
|
" audienti analytics visibility [--window 24h] [--user <account_user_id|email|name|me>] [--json]",
|
|
@@ -5243,13 +6567,42 @@ const HELP_TOPICS = new Map([
|
|
|
5243
6567
|
" --start <YYYY-MM-DD> --end <YYYY-MM-DD> For user analytics, select the events.created_at activity range instead of --window.",
|
|
5244
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.",
|
|
5245
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.",
|
|
5246
6571
|
" --provenance <source> Optional lower-level AccountProspect.intake_source filter.",
|
|
5247
6572
|
" --platform <linkedin|email|gmail> For user analytics, filter events.platform. --channel is accepted as an alias.",
|
|
5248
6573
|
" cohort-analysis loops over recent weekly AccountProspect.created_at cohorts and compares their current stages.",
|
|
5249
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.",
|
|
5250
6575
|
"",
|
|
5251
6576
|
"Output:",
|
|
5252
|
-
" 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"
|
|
5253
6606
|
].join("\n")],
|
|
5254
6607
|
|
|
5255
6608
|
["analytics prospects", [
|
|
@@ -5389,6 +6742,7 @@ const HELP_TOPICS = new Map([
|
|
|
5389
6742
|
" audienti accounts list",
|
|
5390
6743
|
" audienti accounts select <acct_id>",
|
|
5391
6744
|
" audienti users list",
|
|
6745
|
+
" audienti users select me",
|
|
5392
6746
|
" audienti offers list",
|
|
5393
6747
|
" audienti icps list",
|
|
5394
6748
|
"",
|
|
@@ -5400,6 +6754,7 @@ const HELP_TOPICS = new Map([
|
|
|
5400
6754
|
" audienti motions pause <motn_id>",
|
|
5401
6755
|
" audienti motions delete <motn_id> --confirm yes",
|
|
5402
6756
|
" audienti motions status <motn_id>",
|
|
6757
|
+
" audienti motions run-discovery <motn_id>",
|
|
5403
6758
|
"",
|
|
5404
6759
|
"3. Add a new prospect from LinkedIn and poll enrichment",
|
|
5405
6760
|
" audienti lists create --name \"Target list\"",
|
|
@@ -5421,6 +6776,9 @@ const HELP_TOPICS = new Map([
|
|
|
5421
6776
|
" audienti prospects add-profile <prsp_id> --url prospect@example.com",
|
|
5422
6777
|
" audienti prospects report-bad-profile <prsp_id> <prof_id>",
|
|
5423
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>",
|
|
5424
6782
|
" audienti prospects sequence-preview <prsp_id>",
|
|
5425
6783
|
" audienti writer test-run <prsp_id>",
|
|
5426
6784
|
" audienti prospects sequence-export <prsp_id> --csv",
|
|
@@ -5438,6 +6796,7 @@ const HELP_TOPICS = new Map([
|
|
|
5438
6796
|
"7. Inspect account analytics",
|
|
5439
6797
|
" audienti users activity me --window 7d",
|
|
5440
6798
|
" audienti analytics prospects --window 24h",
|
|
6799
|
+
" audienti analytics dashboard --play-tag wine_campaign",
|
|
5441
6800
|
" audienti analytics users --user me --window 30d",
|
|
5442
6801
|
" audienti analytics visibility --window 24h --user me",
|
|
5443
6802
|
" audienti analytics content --window week",
|
|
@@ -5449,7 +6808,6 @@ const HELP_TOPICS = new Map([
|
|
|
5449
6808
|
" Prefer prospects import for new LinkedIn people and add-prospects commands for records that already exist.",
|
|
5450
6809
|
"",
|
|
5451
6810
|
"Current gaps to plan around:",
|
|
5452
|
-
" Prospect disposition still lacks a dedicated CLI mutation.",
|
|
5453
6811
|
" Operator outcome writeback is implemented for prospect rows, not visibility rows."
|
|
5454
6812
|
].join("\n")]
|
|
5455
6813
|
]);
|