@audienti/cli 0.1.84 → 0.1.86

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 CHANGED
@@ -4,6 +4,22 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.86] - 2026-09-28
8
+
9
+ ### Added
10
+
11
+ - `audienti motions profile-signals <motn_id> list|add|remove` manages the social profiles a motion tracks, including your own LinkedIn profile with `--owned --social-cookie <id>`.
12
+
13
+ ### Changed
14
+
15
+ - `motions show` no longer lists agent provenance for discovery signals, because signals now belong to the motion (#1811).
16
+
17
+ ## [0.1.85] - 2026-09-28
18
+
19
+ ### Changed
20
+
21
+ - Social account lists and lookups skip accounts an admin has offboarded. Opening an offboarded account through the API returns 403 with code `offboarded`.
22
+
7
23
  ## [0.1.84] - 2026-09-28
8
24
 
9
25
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.84",
3
+ "version": "0.1.86",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -632,6 +632,23 @@ export class AudientiClient {
632
632
  });
633
633
  }
634
634
 
635
+ motionProfileSignals(accountId, motionId) {
636
+ return this.requestJson(accountPath(accountId, ["motions", motionId, "profile_signals"]));
637
+ }
638
+
639
+ addMotionProfileSignal(accountId, motionId, body) {
640
+ return this.requestJson(accountPath(accountId, ["motions", motionId, "profile_signals"]), {
641
+ method: "POST",
642
+ body
643
+ });
644
+ }
645
+
646
+ removeMotionProfileSignal(accountId, motionId, signalId) {
647
+ return this.requestJson(accountPath(accountId, ["motions", motionId, "profile_signals", signalId]), {
648
+ method: "DELETE"
649
+ });
650
+ }
651
+
635
652
  removeMotionAbmCompany(accountId, motionId, rowId) {
636
653
  return this.requestJson(accountPath(accountId, ["motions", motionId, "abm_companies", rowId]), {
637
654
  method: "DELETE"
package/src/cli.js CHANGED
@@ -183,6 +183,9 @@ const MOTIONS_QUICK_START_USAGE = "Usage: audienti motions quick-start --url <co
183
183
  const MOTIONS_ABM_COMPANIES_LIST_USAGE = "Usage: audienti motions abm-companies <motn_id> list [--json] [--account <acct_id>]";
184
184
  const MOTIONS_ABM_COMPANIES_ADD_USAGE = "Usage: audienti motions abm-companies <motn_id> add (<domain_or_linkedin_url>... | --file <txt|json>) [--json] [--account <acct_id>]";
185
185
  const MOTIONS_ABM_COMPANIES_REMOVE_USAGE = "Usage: audienti motions abm-companies <motn_id> remove <row_id> [--json] [--account <acct_id>]";
186
+ const MOTIONS_PROFILE_SIGNALS_LIST_USAGE = "Usage: audienti motions profile-signals <motn_id> list [--json] [--account <acct_id>]";
187
+ const MOTIONS_PROFILE_SIGNALS_ADD_USAGE = "Usage: audienti motions profile-signals <motn_id> add (<profile_url> [--category <competitor|influencer|partner|customer|recruiter>] | --owned --social-cookie <id>) [--roles <commenters,reactors>] [--json] [--account <acct_id>]";
188
+ const MOTIONS_PROFILE_SIGNALS_REMOVE_USAGE = "Usage: audienti motions profile-signals <motn_id> remove <signal_id> [--json] [--account <acct_id>]";
186
189
  const ICPS_SHOW_USAGE = "Usage: audienti icps show <icp_id> [--json] [--account <acct_id>]";
187
190
  const ICPS_LIST_USAGE = "Usage: audienti icps list [--status <active|archived|all>] [--tag <tag>] [--json] [--account <acct_id>]";
188
191
  const ICPS_UPDATE_USAGE = "Usage: audienti icps update <icp_id> ([--name <text>] [--notes <text>] [--discovery-keyword <text>] [--tags <tag[,tag...]>] | --payload <file.json>) [--json] [--account <acct_id>]";
@@ -403,6 +406,7 @@ async function dispatch(argv, context) {
403
406
  if (normalizedResource === "motions" && action === "signals") return motionsSignals(rest, context, { accountOverride });
404
407
  if (normalizedResource === "motions" && action === "status") return motionsStatus(rest, context, { accountOverride });
405
408
  if (normalizedResource === "motions" && ["abm-companies", "company-filters"].includes(action)) return motionsAbmCompanies(rest, context, { accountOverride });
409
+ if (normalizedResource === "motions" && action === "profile-signals") return motionsProfileSignals(rest, context, { accountOverride });
406
410
  if (normalizedResource === "motions" && action === "analytics") return motionsAnalytics(rest, context, { accountOverride });
407
411
  if (normalizedResource === "motions" && action === "prospects") return motionsProspects(rest, context, { accountOverride });
408
412
  if (normalizedResource === "motions" && action === "add-prospects") return motionsAddProspects(rest, context, { accountOverride });
@@ -3310,6 +3314,73 @@ async function motionsAbmCompaniesRemove(motionId, args, context, { accountOverr
3310
3314
  renderMotionAbmCompanies(payload, context);
3311
3315
  }
3312
3316
 
3317
+ const MOTIONS_PROFILE_SIGNALS_USAGE = "Usage: audienti motions profile-signals <motn_id> <list|add|remove> [args] [--json] [--account <acct_id>]";
3318
+
3319
+ async function motionsProfileSignals(args, context, { accountOverride } = {}) {
3320
+ const [motionId, subaction, ...rest] = args;
3321
+ if (!motionId || !subaction) throw new CommandError(MOTIONS_PROFILE_SIGNALS_USAGE);
3322
+
3323
+ if (subaction === "list") return motionsProfileSignalsList(motionId, rest, context, { accountOverride });
3324
+ if (subaction === "add") return motionsProfileSignalsAdd(motionId, rest, context, { accountOverride });
3325
+ if (["remove", "delete"].includes(subaction)) return motionsProfileSignalsRemove(motionId, rest, context, { accountOverride });
3326
+
3327
+ throw new CommandError(MOTIONS_PROFILE_SIGNALS_USAGE);
3328
+ }
3329
+
3330
+ async function motionsProfileSignalsList(motionId, args, context, { accountOverride } = {}) {
3331
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
3332
+ if (positionals.length > 0) throw new CommandError(MOTIONS_PROFILE_SIGNALS_LIST_USAGE);
3333
+
3334
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3335
+ const payload = await client.motionProfileSignals(accountId, motionId);
3336
+ if (values.json) return writeJson(context.stdout, payload);
3337
+
3338
+ renderMotionProfileSignals(payload, context);
3339
+ }
3340
+
3341
+ async function motionsProfileSignalsAdd(motionId, args, context, { accountOverride } = {}) {
3342
+ const { values, positionals } = parseCommandArgs(args, {
3343
+ ...jsonOptions(),
3344
+ category: { type: "string" },
3345
+ owned: { type: "boolean" },
3346
+ "social-cookie": { type: "string" },
3347
+ roles: { type: "string" }
3348
+ });
3349
+ const owned = Boolean(values.owned);
3350
+ if (owned ? (positionals.length > 0 || !values["social-cookie"]) : positionals.length !== 1) {
3351
+ throw new CommandError(MOTIONS_PROFILE_SIGNALS_ADD_USAGE);
3352
+ }
3353
+
3354
+ const profileSignal = owned
3355
+ ? { category: "owned", social_cookie_id: values["social-cookie"] }
3356
+ : { url: positionals[0], ...(values.category ? { category: values.category } : {}) };
3357
+ if (values.roles !== undefined) {
3358
+ const roles = String(values.roles).split(",").map((role) => role.trim().toLowerCase()).filter(Boolean);
3359
+ if (roles.some((role) => !["commenters", "reactors"].includes(role))) throw new CommandError(MOTIONS_PROFILE_SIGNALS_ADD_USAGE);
3360
+ profileSignal.commenters_enabled = roles.includes("commenters");
3361
+ profileSignal.reactors_enabled = roles.includes("reactors");
3362
+ }
3363
+
3364
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3365
+ const payload = await client.addMotionProfileSignal(accountId, motionId, { profile_signal: profileSignal });
3366
+ if (values.json) return writeJson(context.stdout, payload);
3367
+
3368
+ writeLine(context.stdout, `Tracking ${display(payload?.profile_signal?.canonical_url)} for motion ${display(payload?.motion_id || motionId)}.`);
3369
+ renderMotionProfileSignals(payload, context);
3370
+ }
3371
+
3372
+ async function motionsProfileSignalsRemove(motionId, args, context, { accountOverride } = {}) {
3373
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
3374
+ if (positionals.length !== 1) throw new CommandError(MOTIONS_PROFILE_SIGNALS_REMOVE_USAGE);
3375
+
3376
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3377
+ const payload = await client.removeMotionProfileSignal(accountId, motionId, positionals[0]);
3378
+ if (values.json) return writeJson(context.stdout, payload);
3379
+
3380
+ writeLine(context.stdout, `Removed profile signal ${display(positionals[0])} from motion ${display(payload?.motion_id || motionId)}.`);
3381
+ renderMotionProfileSignals(payload, context);
3382
+ }
3383
+
3313
3384
  async function motionsDelete(args, context, { accountOverride } = {}) {
3314
3385
  const { values, positionals } = parseCommandArgs(args, {
3315
3386
  ...jsonOptions(),
@@ -7272,20 +7343,15 @@ function renderMotionDiscoverySignals(payload, context) {
7272
7343
  const counts = payload?.counts || {};
7273
7344
  const motionId = payload?.prefix_id ? ` (${display(payload.prefix_id)})` : "";
7274
7345
 
7275
- writeLine(context.stdout, `Motion-owned discovery signals${motionId}: ${display(counts.total, "0")} total, ${display(counts.actionable, "0")} actionable, ${display(counts.pending, "0")} pending, ${display(counts.held, "0")} held`);
7346
+ writeLine(context.stdout, `Motion-owned discovery signals${motionId}: ${display(counts.total, "0")} total, ${display(counts.actionable, "0")} actionable, ${display(counts.inactive, "0")} inactive`);
7276
7347
  if (rows.length === 0) return;
7277
7348
 
7278
7349
  for (const row of rows) {
7279
- const provenance = Array.isArray(row.agent_provenance)
7280
- ? row.agent_provenance.map((entry) => [entry.agent_name, entry.agent_id].filter(Boolean).join(" · ")).filter(Boolean).join(", ")
7281
- : "";
7282
- const status = row.actionable ? "actionable" : display(row.status, "pending");
7350
+ const status = row.actionable ? "actionable" : display(row.status, "inactive");
7283
7351
  const sourceCounts = row.source_counts || {};
7284
7352
  const detail = [
7285
7353
  row.canonical_url || row.topic?.slug || row.source_key,
7286
- `sources=${display(sourceCounts.total, "0")}/${display(sourceCounts.accepted, "0")}/${display(sourceCounts.rejected, "0")}`,
7287
- provenance ? `agents=${provenance}` : null,
7288
- !row.actionable && row.motion_attribution_reason ? `reason=${singleLine(row.motion_attribution_reason)}` : null
7354
+ `sources=${display(sourceCounts.total, "0")}/${display(sourceCounts.accepted, "0")}/${display(sourceCounts.rejected, "0")}`
7289
7355
  ].filter(Boolean).join("; ");
7290
7356
  writeLine(context.stdout, `- [${status}] ${display(row.type, "signal")}: ${display(row.label, "unnamed")} (${detail})`);
7291
7357
  }
@@ -7306,6 +7372,18 @@ function renderMotionAbmCompanies(payload, context, { showEmpty = true } = {}) {
7306
7372
  ]));
7307
7373
  }
7308
7374
 
7375
+ function renderMotionProfileSignals(payload, context) {
7376
+ const rows = Array.isArray(payload?.profile_signals) ? payload.profile_signals : [];
7377
+ if (rows.length === 0) return writeLine(context.stdout, "No profile signals found.");
7378
+
7379
+ writeAlignedTable(context, ["SIGNAL ID", "CATEGORY", "PROFILE", "STATUS"], rows.map((row) => [
7380
+ display(row.id),
7381
+ display(row.source_kind === "owned" ? "owned" : row.category),
7382
+ display(row.canonical_url),
7383
+ display(row.status)
7384
+ ]));
7385
+ }
7386
+
7309
7387
  function renderMotionAbmCompanyErrors(payload, context) {
7310
7388
  const errors = Array.isArray(payload?.errors) ? payload.errors : [];
7311
7389
  if (errors.length === 0) return;
@@ -11931,6 +12009,9 @@ const HELP_TOPICS = new Map([
11931
12009
  " audienti motions abm-companies <motn_id> list [--json]",
11932
12010
  " audienti motions abm-companies <motn_id> add (<domain_or_linkedin_url>... | --file <txt|json>) [--json]",
11933
12011
  " audienti motions abm-companies <motn_id> remove <row_id> [--json]",
12012
+ " audienti motions profile-signals <motn_id> list [--json]",
12013
+ " audienti motions profile-signals <motn_id> add (<profile_url> [--category <type>] | --owned --social-cookie <id>) [--roles <commenters,reactors>] [--json]",
12014
+ " audienti motions profile-signals <motn_id> remove <signal_id> [--json]",
11934
12015
  " audienti motions create --payload <file.json> [--json]",
11935
12016
  ` ${MOTIONS_UPDATE_USAGE.slice("Usage: ".length).replace(" [--account <acct_id>]", "")}`,
11936
12017
  " audienti motions add-tag <motn_id> <tag> [--json]",
@@ -12017,7 +12098,7 @@ const HELP_TOPICS = new Map([
12017
12098
  " inbound_channels: enabled inbound collectors for inbound motions",
12018
12099
  " lopa_profiles[]: tracked LinkedIn profile rows for LOPA motions",
12019
12100
  " signal_rows[]: outbound signal configuration rows",
12020
- " discovery_signals: Motion-owned Topic/profile signals with attribution state and Agent provenance",
12101
+ " discovery_signals: Motion-owned Topic/profile signals with status and source counts",
12021
12102
  " abm_companies[]: motion-scoped positive company filter rows",
12022
12103
  "",
12023
12104
  "API:",
@@ -12032,15 +12113,33 @@ const HELP_TOPICS = new Map([
12032
12113
  "",
12033
12114
  "Purpose:",
12034
12115
  " Read the Topic and tracked-profile signals owned by one Motion.",
12035
- " Actionable rows have exact Motion attribution; pending and held rows remain inspectable with their reason and evidence.",
12116
+ " Active rows feed discovery; paused or inactive rows stay visible but do not feed discovery.",
12036
12117
  "",
12037
12118
  "Output:",
12038
- " Shows attribution state, canonical source URL or Topic, accepted/rejected source counts, and retained Agent provenance.",
12119
+ " Shows status, canonical source URL or Topic, and accepted/rejected source counts.",
12039
12120
  "",
12040
12121
  "API:",
12041
12122
  " GET /api/v1/accounts/:account_id/motions/:id/signals.json"
12042
12123
  ].join("\n")],
12043
12124
 
12125
+ ["motions profile-signals", [
12126
+ "Usage:",
12127
+ ` ${MOTIONS_PROFILE_SIGNALS_LIST_USAGE.slice("Usage: ".length)}`,
12128
+ ` ${MOTIONS_PROFILE_SIGNALS_ADD_USAGE.slice("Usage: ".length)}`,
12129
+ ` ${MOTIONS_PROFILE_SIGNALS_REMOVE_USAGE.slice("Usage: ".length)}`,
12130
+ "",
12131
+ "Status: implemented",
12132
+ "",
12133
+ "Purpose:",
12134
+ " List, add, or remove the social profiles a motion tracks for discovery signals.",
12135
+ " --owned tracks your own LinkedIn profile through a connected session in this account.",
12136
+ "",
12137
+ "API:",
12138
+ " GET /api/v1/accounts/:account_id/motions/:motion_id/profile_signals.json",
12139
+ " POST /api/v1/accounts/:account_id/motions/:motion_id/profile_signals.json",
12140
+ " DELETE /api/v1/accounts/:account_id/motions/:motion_id/profile_signals/:id.json"
12141
+ ].join("\n")],
12142
+
12044
12143
  ["motions abm-companies", [
12045
12144
  "Usage:",
12046
12145
  ` ${MOTIONS_ABM_COMPANIES_LIST_USAGE.slice("Usage: ".length)}`,