@audienti/cli 0.1.73 → 0.1.74
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 +7 -0
- package/package.json +1 -1
- package/src/api-client.js +16 -2
- package/src/cli.js +150 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,10 +4,17 @@ All notable changes to the Audienti CLI are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.1.74] - 2026-09-27
|
|
8
|
+
|
|
7
9
|
### Added
|
|
8
10
|
|
|
11
|
+
- Add `accounts show`, `company-rules show`, and `linkedin-lookups <kind>` so account details, single company rules, and LinkedIn targeting values are reachable from the CLI.
|
|
9
12
|
- Add Motion-owned discovery signal tracking to `motions show` and the `motions signals` command, including attribution holds, source counts, and retained Agent provenance.
|
|
10
13
|
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- LinkedIn lookups accept API tokens and prefixed ICP ids, so CLI lookups no longer fail with an authentication error.
|
|
17
|
+
|
|
11
18
|
## [0.1.73] - 2026-09-26
|
|
12
19
|
|
|
13
20
|
### Added
|
package/package.json
CHANGED
package/src/api-client.js
CHANGED
|
@@ -40,6 +40,14 @@ export class AudientiClient {
|
|
|
40
40
|
return this.requestJson("/api/v1/accounts.json");
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
account(accountId) {
|
|
44
|
+
return this.requestJson(accountPath(accountId, []));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
linkedinLookup(kind, query = {}) {
|
|
48
|
+
return this.requestJson(apiPath(["linkedin_lookups", kind], query));
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
mcp(message) {
|
|
44
52
|
return this.requestJson("/mcp", {
|
|
45
53
|
method: "POST",
|
|
@@ -187,6 +195,10 @@ export class AudientiClient {
|
|
|
187
195
|
return this.requestJson(accountPath(accountId, ["company_rules"]));
|
|
188
196
|
}
|
|
189
197
|
|
|
198
|
+
companyRule(accountId, ruleId) {
|
|
199
|
+
return this.requestJson(accountPath(accountId, ["company_rules", ruleId]));
|
|
200
|
+
}
|
|
201
|
+
|
|
190
202
|
createCompanyRule(accountId, body) {
|
|
191
203
|
return this.requestJson(accountPath(accountId, ["company_rules"]), {
|
|
192
204
|
method: "POST",
|
|
@@ -819,11 +831,13 @@ export class AudientiClient {
|
|
|
819
831
|
}
|
|
820
832
|
|
|
821
833
|
function accountPath(accountId, segments, query = {}) {
|
|
834
|
+
return apiPath(["accounts", accountId, ...segments], query);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function apiPath(segments, query = {}) {
|
|
822
838
|
const encodedSegments = [
|
|
823
839
|
"api",
|
|
824
840
|
"v1",
|
|
825
|
-
"accounts",
|
|
826
|
-
accountId,
|
|
827
841
|
...segments
|
|
828
842
|
].map((segment) => encodeURIComponent(segment));
|
|
829
843
|
const searchParams = new URLSearchParams();
|
package/src/cli.js
CHANGED
|
@@ -112,6 +112,18 @@ const COMPANY_RULES_CREATE_USAGE = "Usage: audienti company-rules create (--link
|
|
|
112
112
|
const COMPANY_RULES_UPDATE_USAGE = "Usage: audienti company-rules update <rule_id> [--linkedin-url <url>] [--domain <domain>] [--disposition <monitor|nurture|not_fit|reject>] [--name <text>] [--user <account_user_id|email|me|none>] [--note <text>] [--json] [--account <acct_id>]";
|
|
113
113
|
const COMPANY_RULES_REMOVE_USAGE = "Usage: audienti company-rules remove <rule_id> [--json] [--account <acct_id>]";
|
|
114
114
|
const COMPANY_RULES_APPLY_USAGE = "Usage: audienti company-rules apply (<rule_id>|--all) [--json] [--account <acct_id>]";
|
|
115
|
+
const COMPANY_RULES_SHOW_USAGE = "Usage: audienti company-rules show <rule_id> [--json] [--account <acct_id>]";
|
|
116
|
+
const ACCOUNTS_SHOW_USAGE = "Usage: audienti accounts show [<acct_id>] [--json] [--account <acct_id>]";
|
|
117
|
+
const LINKEDIN_LOOKUPS_USAGE = "Usage: audienti linkedin-lookups <company-sizes|company-types|functions|industries|job-titles|locations|seniorities> [--query <text>] [--icp <icp_id>] [--json] [--account <acct_id>]";
|
|
118
|
+
const LINKEDIN_LOOKUP_KINDS = new Map([
|
|
119
|
+
["company-sizes", { path: "company_sizes", query: "none", icp: true }],
|
|
120
|
+
["company-types", { path: "company_types", query: "none", icp: true }],
|
|
121
|
+
["functions", { path: "functions", query: "required", icp: true }],
|
|
122
|
+
["industries", { path: "industries", query: "required", icp: false }],
|
|
123
|
+
["job-titles", { path: "job_titles", query: "required", icp: true }],
|
|
124
|
+
["locations", { path: "locations", query: "required", icp: true }],
|
|
125
|
+
["seniorities", { path: "seniorities", query: "optional", icp: true }]
|
|
126
|
+
]);
|
|
115
127
|
const TASKS_LIST_USAGE = "Usage: audienti tasks list [--status <open|completed>] [--limit <n>] [--json] [--account <acct_id>]";
|
|
116
128
|
const TASKS_ADD_USAGE = "Usage: audienti tasks add --title <text> --due <time> [--prospect <prsp_id>] [--list <list_id>] [--assigned-user <id|me>] [--notes <text>] [--json] [--account <acct_id>]";
|
|
117
129
|
const TASKS_COMPLETE_USAGE = "Usage: audienti tasks complete <ptsk_id> [--json] [--account <acct_id>]";
|
|
@@ -265,6 +277,8 @@ async function dispatch(argv, context) {
|
|
|
265
277
|
if (normalizedResource === "update" && action === "check") return updateCheck(rest, context);
|
|
266
278
|
if (normalizedResource === "accounts" && action === "list") return accountsList(rest, context, { accountOverride });
|
|
267
279
|
if (normalizedResource === "accounts" && action === "select") return accountsSelect(rest, context);
|
|
280
|
+
if (normalizedResource === "accounts" && action === "show") return accountsShow(rest, context, { accountOverride });
|
|
281
|
+
if (normalizedResource === "linkedin-lookups") return linkedinLookups(action, rest, context, { accountOverride });
|
|
268
282
|
if (normalizedResource === "users" && action === "list") return usersList(rest, context, { accountOverride });
|
|
269
283
|
if (normalizedResource === "users" && action === "select") return usersSelect(rest, context, { accountOverride });
|
|
270
284
|
if (normalizedResource === "users" && action === "activity") return usersActivity(rest, context, { accountOverride });
|
|
@@ -291,6 +305,7 @@ async function dispatch(argv, context) {
|
|
|
291
305
|
if (normalizedResource === "dnc" && action === "import") return dncImport(rest, context, { accountOverride });
|
|
292
306
|
if (normalizedResource === "dnc" && ["remove", "delete"].includes(action)) return dncRemove(rest, context, { accountOverride });
|
|
293
307
|
if (normalizedResource === "company-rules" && action === "list") return companyRulesList(rest, context, { accountOverride });
|
|
308
|
+
if (normalizedResource === "company-rules" && action === "show") return companyRulesShow(rest, context, { accountOverride });
|
|
294
309
|
if (normalizedResource === "company-rules" && action === "create") return companyRulesCreate(rest, context, { accountOverride });
|
|
295
310
|
if (normalizedResource === "company-rules" && action === "update") return companyRulesUpdate(rest, context, { accountOverride });
|
|
296
311
|
if (normalizedResource === "company-rules" && ["remove", "delete"].includes(action)) return companyRulesRemove(rest, context, { accountOverride });
|
|
@@ -482,6 +497,7 @@ function normalizeResource(resource) {
|
|
|
482
497
|
if (resource === "principals") return "users";
|
|
483
498
|
if (resource === "writers") return "writer";
|
|
484
499
|
if (resource === "company_rules" || resource === "company-rules") return "company-rules";
|
|
500
|
+
if (resource === "linkedin_lookups" || resource === "linkedin-lookups") return "linkedin-lookups";
|
|
485
501
|
if (resource === "social_cookie" || resource === "social_cookies") return "social-cookies";
|
|
486
502
|
return resource === "plays" ? "motions" : resource;
|
|
487
503
|
}
|
|
@@ -802,6 +818,64 @@ async function accountsList(args, context, { accountOverride } = {}) {
|
|
|
802
818
|
}
|
|
803
819
|
}
|
|
804
820
|
|
|
821
|
+
async function accountsShow(args, context, { accountOverride } = {}) {
|
|
822
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
823
|
+
if (positionals.length > 1) throw new CommandError(ACCOUNTS_SHOW_USAGE);
|
|
824
|
+
|
|
825
|
+
const config = await requireAuthenticatedConfig(context);
|
|
826
|
+
const accountId = positionals[0] || accountOverride || config.accountId;
|
|
827
|
+
if (!accountId) {
|
|
828
|
+
throw new CommandError("No active account. Run `audienti accounts select <acct_id>`, pass `--account <acct_id>`, or give an account id.");
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
const account = await clientFromConfig(config, context).account(accountId);
|
|
832
|
+
if (values.json) return writeJson(context.stdout, account);
|
|
833
|
+
|
|
834
|
+
writeLine(context.stdout, `Account: ${display(account?.name)} (${display(account?.prefix_id || accountId)})`);
|
|
835
|
+
writeLine(context.stdout, `Personal: ${account?.personal ? "yes" : "no"}`);
|
|
836
|
+
writeLine(context.stdout, `Members: ${Array.isArray(account?.account_users) ? account.account_users.length : 0}`);
|
|
837
|
+
writeLine(context.stdout, `Created: ${display(account?.created_at, "-")}`);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
async function linkedinLookups(kind, args, context, { accountOverride } = {}) {
|
|
841
|
+
const lookup = LINKEDIN_LOOKUP_KINDS.get(String(kind || "").replaceAll("_", "-"));
|
|
842
|
+
if (!lookup) throw new CommandError(LINKEDIN_LOOKUPS_USAGE);
|
|
843
|
+
|
|
844
|
+
const { values, positionals } = parseCommandArgs(args, {
|
|
845
|
+
...jsonOptions(),
|
|
846
|
+
query: { type: "string" },
|
|
847
|
+
icp: { type: "string" }
|
|
848
|
+
});
|
|
849
|
+
const query = values.query?.trim();
|
|
850
|
+
const invalid = positionals.length > 0 ||
|
|
851
|
+
(lookup.query === "required" && !query) ||
|
|
852
|
+
(lookup.query === "none" && values.query !== undefined) ||
|
|
853
|
+
(!lookup.icp && values.icp !== undefined);
|
|
854
|
+
if (invalid) throw new CommandError(LINKEDIN_LOOKUPS_USAGE);
|
|
855
|
+
|
|
856
|
+
const config = await requireAuthenticatedConfig(context);
|
|
857
|
+
const params = { q: query };
|
|
858
|
+
if (values.icp) {
|
|
859
|
+
const accountId = accountOverride || config.accountId;
|
|
860
|
+
if (!accountId) {
|
|
861
|
+
throw new CommandError("No active account. Run `audienti accounts select <acct_id>` or pass `--account <acct_id>` to look up with --icp.");
|
|
862
|
+
}
|
|
863
|
+
params.icp_id = values.icp;
|
|
864
|
+
params.account_id = accountId;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const payload = await clientFromConfig(config, context).linkedinLookup(lookup.path, params);
|
|
868
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
869
|
+
|
|
870
|
+
const rows = Array.isArray(payload) ? payload : [];
|
|
871
|
+
if (rows.length === 0) return writeLine(context.stdout, "No results found.");
|
|
872
|
+
|
|
873
|
+
writeLine(context.stdout, "ID\tNAME\tSOURCE");
|
|
874
|
+
for (const row of rows) {
|
|
875
|
+
writeLine(context.stdout, [display(row.id, "-"), display(row.name), display(row.source, "-")].join("\t"));
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
805
879
|
async function accountsSelect(args, context) {
|
|
806
880
|
const { positionals } = parseCommandArgs(args, {});
|
|
807
881
|
if (positionals.length !== 1) throw new CommandError("Usage: audienti accounts select <acct_id>");
|
|
@@ -1339,6 +1413,22 @@ async function companyRulesList(args, context, { accountOverride } = {}) {
|
|
|
1339
1413
|
renderCompanyRules(payload, context);
|
|
1340
1414
|
}
|
|
1341
1415
|
|
|
1416
|
+
async function companyRulesShow(args, context, { accountOverride } = {}) {
|
|
1417
|
+
const { values, positionals } = parseCommandArgs(args, jsonOptions());
|
|
1418
|
+
if (positionals.length !== 1) throw new CommandError(COMPANY_RULES_SHOW_USAGE);
|
|
1419
|
+
|
|
1420
|
+
const { client, accountId } = await requireAccountContext(context, { accountOverride });
|
|
1421
|
+
const payload = await client.companyRule(accountId, positionals[0]);
|
|
1422
|
+
if (values.json) return writeJson(context.stdout, payload);
|
|
1423
|
+
|
|
1424
|
+
const rule = payload?.company_rule;
|
|
1425
|
+
writeLine(context.stdout, `Company rule ${display(rule?.name || rule?.domain || rule?.linkedin_company_identifier)} (${display(rule?.prefix_id || rule?.id)})`);
|
|
1426
|
+
writeLine(context.stdout, `Disposition: ${display(rule?.disposition)} | Scope: ${companyRuleScopeLabel(rule)} | Active: ${rule?.active ? "yes" : "no"}`);
|
|
1427
|
+
writeLine(context.stdout, `LinkedIn: ${display(rule?.linkedin_company_url || rule?.linkedin_company_identifier, "-")}`);
|
|
1428
|
+
writeLine(context.stdout, `Domain: ${display(rule?.domain, "-")}`);
|
|
1429
|
+
if (rule?.note) writeLine(context.stdout, `Note: ${rule.note}`);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1342
1432
|
async function companyRulesCreate(args, context, { accountOverride } = {}) {
|
|
1343
1433
|
const { values, positionals } = parseCommandArgs(args, companyRuleOptions());
|
|
1344
1434
|
if (positionals.length > 0 || (!values["linkedin-url"] && !values.domain) || !values.disposition) {
|
|
@@ -8411,6 +8501,7 @@ const HELP_TOPICS = new Map([
|
|
|
8411
8501
|
" Setup & identity",
|
|
8412
8502
|
" audienti auth status",
|
|
8413
8503
|
" audienti config list",
|
|
8504
|
+
" audienti accounts show [acct_id]",
|
|
8414
8505
|
" audienti update check",
|
|
8415
8506
|
" audienti setup play preflight",
|
|
8416
8507
|
" audienti users list",
|
|
@@ -8498,9 +8589,11 @@ const HELP_TOPICS = new Map([
|
|
|
8498
8589
|
" audienti icps add-tag <icp_id> <tag>",
|
|
8499
8590
|
" audienti icps remove-tag <icp_id> <tag>",
|
|
8500
8591
|
" audienti companies search --query <text>",
|
|
8592
|
+
" audienti linkedin-lookups <kind> [--query <text>]",
|
|
8501
8593
|
" audienti dnc list",
|
|
8502
8594
|
" audienti dnc add <email|citation_id|profile_url>",
|
|
8503
8595
|
" audienti company-rules list",
|
|
8596
|
+
" audienti company-rules show <rule_id>",
|
|
8504
8597
|
" audienti company-rules create (--linkedin-url <url> | --domain <domain>) --disposition <state>",
|
|
8505
8598
|
"",
|
|
8506
8599
|
" Writer",
|
|
@@ -8725,6 +8818,7 @@ const HELP_TOPICS = new Map([
|
|
|
8725
8818
|
["accounts", [
|
|
8726
8819
|
"Usage:",
|
|
8727
8820
|
" audienti accounts list [--json]",
|
|
8821
|
+
" audienti accounts show [<acct_id>] [--json]",
|
|
8728
8822
|
" audienti accounts select <acct_id>",
|
|
8729
8823
|
"",
|
|
8730
8824
|
"Status: implemented",
|
|
@@ -8783,6 +8877,51 @@ const HELP_TOPICS = new Map([
|
|
|
8783
8877
|
" audienti accounts list --json"
|
|
8784
8878
|
].join("\n")],
|
|
8785
8879
|
|
|
8880
|
+
["accounts show", [
|
|
8881
|
+
"Usage:",
|
|
8882
|
+
` ${ACCOUNTS_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
8883
|
+
"",
|
|
8884
|
+
"Status: implemented",
|
|
8885
|
+
"",
|
|
8886
|
+
"API:",
|
|
8887
|
+
" GET /api/v1/accounts/:id.json",
|
|
8888
|
+
"",
|
|
8889
|
+
"Input shape:",
|
|
8890
|
+
" acct_id: string Account prefix id; defaults to --account or the selected account",
|
|
8891
|
+
"",
|
|
8892
|
+
"Output shape:",
|
|
8893
|
+
" id, prefix_id, name, personal, owner_id, account_users[], created_at, updated_at"
|
|
8894
|
+
].join("\n")],
|
|
8895
|
+
|
|
8896
|
+
["linkedin-lookups", [
|
|
8897
|
+
"Usage:",
|
|
8898
|
+
` ${LINKEDIN_LOOKUPS_USAGE.slice("Usage: ".length)}`,
|
|
8899
|
+
"",
|
|
8900
|
+
"Status: implemented",
|
|
8901
|
+
"",
|
|
8902
|
+
"Purpose:",
|
|
8903
|
+
" Look up LinkedIn targeting values (the ids used in ICP filters).",
|
|
8904
|
+
"",
|
|
8905
|
+
"Kinds:",
|
|
8906
|
+
" job-titles, functions, locations --query required",
|
|
8907
|
+
" industries --query required; --icp not supported",
|
|
8908
|
+
" seniorities --query optional filter",
|
|
8909
|
+
" company-sizes, company-types no --query; returns the full list",
|
|
8910
|
+
"",
|
|
8911
|
+
"ICP option:",
|
|
8912
|
+
" --icp <icp_id> uses values saved on that ICP of the active account (or --account).",
|
|
8913
|
+
" For company-sizes, company-types and seniorities it also saves the list onto that ICP.",
|
|
8914
|
+
"",
|
|
8915
|
+
"API:",
|
|
8916
|
+
" GET /api/v1/linkedin_lookups/<kind>.json?q=<text>&icp_id=<icp_id>",
|
|
8917
|
+
"",
|
|
8918
|
+
"Output shape:",
|
|
8919
|
+
" [{ id, name, source? }]",
|
|
8920
|
+
"",
|
|
8921
|
+
"Example:",
|
|
8922
|
+
" audienti linkedin-lookups job-titles --query \"head of sales\" --json"
|
|
8923
|
+
].join("\n")],
|
|
8924
|
+
|
|
8786
8925
|
["accounts select", [
|
|
8787
8926
|
"Usage:",
|
|
8788
8927
|
" audienti accounts select <acct_id>",
|
|
@@ -9413,6 +9552,7 @@ const HELP_TOPICS = new Map([
|
|
|
9413
9552
|
["company-rules", [
|
|
9414
9553
|
"Usage:",
|
|
9415
9554
|
" audienti company-rules list [--json]",
|
|
9555
|
+
` ${COMPANY_RULES_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
9416
9556
|
` ${COMPANY_RULES_CREATE_USAGE.slice("Usage: ".length)}`,
|
|
9417
9557
|
` ${COMPANY_RULES_UPDATE_USAGE.slice("Usage: ".length)}`,
|
|
9418
9558
|
` ${COMPANY_RULES_REMOVE_USAGE.slice("Usage: ".length)}`,
|
|
@@ -9434,6 +9574,16 @@ const HELP_TOPICS = new Map([
|
|
|
9434
9574
|
" GET /api/v1/accounts/:account_id/company_rules.json"
|
|
9435
9575
|
].join("\n")],
|
|
9436
9576
|
|
|
9577
|
+
["company-rules show", [
|
|
9578
|
+
"Usage:",
|
|
9579
|
+
` ${COMPANY_RULES_SHOW_USAGE.slice("Usage: ".length)}`,
|
|
9580
|
+
"",
|
|
9581
|
+
"Status: implemented",
|
|
9582
|
+
"",
|
|
9583
|
+
"API:",
|
|
9584
|
+
" GET /api/v1/accounts/:account_id/company_rules/:id.json"
|
|
9585
|
+
].join("\n")],
|
|
9586
|
+
|
|
9437
9587
|
["company-rules create", [
|
|
9438
9588
|
"Usage:",
|
|
9439
9589
|
` ${COMPANY_RULES_CREATE_USAGE.slice("Usage: ".length)}`,
|