@audienti/cli 0.1.27 → 0.1.28

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,13 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.28] - 2026-07-23
8
+
9
+ ### Added
10
+
11
+ - Add `audienti prospects reenrich` for dry-running or queueing one forced LinkedIn person profile re-enrichment.
12
+ - Add `audienti prospects refresh-queue` for dry-running or applying account-scoped next-action and operator draft cache repair for one prospect.
13
+
7
14
  ## [0.1.27] - 2026-07-22
8
15
 
9
16
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -373,6 +373,20 @@ export class AudientiClient {
373
373
  });
374
374
  }
375
375
 
376
+ reenrichProspect(accountId, prospectId, body = {}) {
377
+ return this.requestJson(accountPath(accountId, ["prospects", prospectId, "reenrich"]), {
378
+ method: "POST",
379
+ body
380
+ });
381
+ }
382
+
383
+ refreshProspectQueue(accountId, prospectId, body = {}) {
384
+ return this.requestJson(accountPath(accountId, ["prospects", prospectId, "refresh_queue"]), {
385
+ method: "POST",
386
+ body
387
+ });
388
+ }
389
+
376
390
  assignProspects(accountId, body) {
377
391
  return this.requestJson(accountPath(accountId, ["prospects", "assign"]), {
378
392
  method: "POST",
package/src/cli.js CHANGED
@@ -39,6 +39,8 @@ const PROSPECTS_REPORT_BAD_PROFILE_USAGE = "Usage: audienti prospects report-bad
39
39
  const PROSPECTS_ASSIGN_USAGE = "Usage: audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json] [--account <acct_id>]";
40
40
  const PROSPECTS_SET_STATUS_USAGE = "Usage: audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected> [--json] [--account <acct_id>]";
41
41
  const PROSPECTS_REPLAN_USAGE = "Usage: audienti prospects replan <prsp_id> [--apply] [--json] [--account <acct_id>]";
42
+ const PROSPECTS_REENRICH_USAGE = "Usage: audienti prospects reenrich <prsp_id> [--profile <prof_id|citation_id>] [--apply] [--json] [--account <acct_id>]";
43
+ const PROSPECTS_REFRESH_QUEUE_USAGE = "Usage: audienti prospects refresh-queue <prsp_id> [--apply] [--json] [--account <acct_id>]";
42
44
  const PROSPECTS_REJECT_USAGE = "Usage: audienti prospects reject <prsp_id> [--json] [--account <acct_id>]";
43
45
  const PROSPECTS_NURTURE_USAGE = "Usage: audienti prospects nurture <prsp_id> [--reason <nurture|non_responsive|not_fit|bad_data_404>] [--json] [--account <acct_id>]";
44
46
  const PROSPECTS_RESTORE_USAGE = "Usage: audienti prospects restore <prsp_id> [--json] [--account <acct_id>]";
@@ -247,6 +249,8 @@ async function dispatch(argv, context) {
247
249
  if (normalizedResource === "prospects" && action === "assign") return prospectsAssign(rest, context, { accountOverride });
248
250
  if (normalizedResource === "prospects" && action === "set-status") return prospectsSetStatus(rest, context, { accountOverride });
249
251
  if (normalizedResource === "prospects" && action === "replan") return prospectsReplan(rest, context, { accountOverride });
252
+ if (normalizedResource === "prospects" && action === "reenrich") return prospectsReenrich(rest, context, { accountOverride });
253
+ if (normalizedResource === "prospects" && action === "refresh-queue") return prospectsRefreshQueue(rest, context, { accountOverride });
250
254
  if (normalizedResource === "prospects" && action === "reject") return prospectsDisposition("reject", rest, context, { accountOverride });
251
255
  if (normalizedResource === "prospects" && action === "nurture") return prospectsDisposition("nurture", rest, context, { accountOverride });
252
256
  if (normalizedResource === "prospects" && action === "restore") return prospectsDisposition("restore", rest, context, { accountOverride });
@@ -1861,6 +1865,40 @@ async function prospectsReplan(args, context, { accountOverride } = {}) {
1861
1865
  renderProspectReplan(payload, context);
1862
1866
  }
1863
1867
 
1868
+ async function prospectsReenrich(args, context, { accountOverride } = {}) {
1869
+ const { values, positionals } = parseCommandArgs(args, {
1870
+ ...jsonOptions(),
1871
+ apply: { type: "boolean" },
1872
+ profile: { type: "string" }
1873
+ });
1874
+ if (positionals.length !== 1) throw new CommandError(PROSPECTS_REENRICH_USAGE);
1875
+
1876
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1877
+ const payload = await client.reenrichProspect(accountId, positionals[0], compactObject({
1878
+ apply: values.apply,
1879
+ profile_id: values.profile
1880
+ }));
1881
+ if (values.json) return writeJson(context.stdout, payload);
1882
+
1883
+ renderProspectReenrich(payload, context);
1884
+ }
1885
+
1886
+ async function prospectsRefreshQueue(args, context, { accountOverride } = {}) {
1887
+ const { values, positionals } = parseCommandArgs(args, {
1888
+ ...jsonOptions(),
1889
+ apply: { type: "boolean" }
1890
+ });
1891
+ if (positionals.length !== 1) throw new CommandError(PROSPECTS_REFRESH_QUEUE_USAGE);
1892
+
1893
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1894
+ const payload = await client.refreshProspectQueue(accountId, positionals[0], compactObject({
1895
+ apply: values.apply
1896
+ }));
1897
+ if (values.json) return writeJson(context.stdout, payload);
1898
+
1899
+ renderProspectRefreshQueue(payload, context);
1900
+ }
1901
+
1864
1902
  async function prospectsDisposition(action, args, context, { accountOverride } = {}) {
1865
1903
  const usageText = {
1866
1904
  reject: PROSPECTS_REJECT_USAGE,
@@ -3998,6 +4036,61 @@ function renderProspectReplan(payload, context) {
3998
4036
  if (payload?.status === "coach_error") writeLine(context.stdout, "The plan was not persisted. Fix the coach error and rerun with --apply.");
3999
4037
  }
4000
4038
 
4039
+ function renderProspectReenrich(payload, context) {
4040
+ const prospect = payload?.prospect || {};
4041
+ const profile = payload?.profile || {};
4042
+ const completeness = payload?.completeness || {};
4043
+ const enrichment = payload?.enrichment || {};
4044
+ const status = payload?.status === "queued" ? "queued" : (payload?.status === "not_queued" ? "not queued" : "dry run");
4045
+
4046
+ writeLine(context.stdout, `Re-enrich ${status} for ${display(prospect.display_name || prospect.name)} (${display(prospect.prefix_id)}).`);
4047
+ writeLine(context.stdout, `Profile: ${display(profile.prefix_id)} ${display(profile.identifier)} ${display(profile.url)}`);
4048
+ writeLine(context.stdout, `Profile status: ${display(profile.status)}`);
4049
+ writeLine(context.stdout, `Thin profile signals: ${completeness.thin_profile_signals ? "yes" : "no"}`);
4050
+ writeLine(context.stdout, `Experience entries: ${sumObjectValues(completeness.experience_counts)}`);
4051
+ writeLine(context.stdout, `Substantive bio length: ${display(completeness.substantive_bio_length, 0)}`);
4052
+ if (profile.invalid_reason) writeLine(context.stdout, `Invalid reason: ${profile.invalid_reason}`);
4053
+ if (enrichment.retry_counter_reset) writeLine(context.stdout, "A stale enrichment retry counter will be cleared.");
4054
+ if (enrichment.next_enrichment_at) writeLine(context.stdout, `Next enrichment at: ${enrichment.next_enrichment_at}`);
4055
+ if (payload?.status === "dry_run") writeLine(context.stdout, "Run again with --apply to queue full enrichment.");
4056
+ if (payload?.status === "not_queued") writeLine(context.stdout, "The profile was not queued, usually because an active enrichment is already running.");
4057
+ }
4058
+
4059
+ function renderProspectRefreshQueue(payload, context) {
4060
+ const prospect = payload?.prospect || {};
4061
+ const draftCache = payload?.draft_cache || {};
4062
+ const coachCache = payload?.coach_cache || {};
4063
+ const refresh = payload?.queue_refresh || {};
4064
+ const status = payload?.status === "applied" ? "applied" : "dry run";
4065
+
4066
+ writeLine(context.stdout, `Refresh queue ${status} for ${display(prospect.display_name || prospect.name)} (${display(prospect.prefix_id)}).`);
4067
+ writeLine(context.stdout, `Coach cache: ${coachCache.present ? "present" : "empty"}`);
4068
+ if (coachCache.evaluated_at) writeLine(context.stdout, `Coach evaluated at: ${coachCache.evaluated_at}`);
4069
+ writeLine(context.stdout, `Draft cache rows: ${display(draftCache.count, 0)}`);
4070
+ writeLine(context.stdout, `Draft statuses: ${formatObjectCounts(draftCache.by_status)}`);
4071
+ writeLine(context.stdout, `Action types: ${Array.isArray(draftCache.action_types) && draftCache.action_types.length > 0 ? draftCache.action_types.join(", ") : "none"}`);
4072
+ if (payload?.applied) {
4073
+ writeLine(context.stdout, `Deleted draft rows: ${display(draftCache.deleted_count, 0)}`);
4074
+ writeLine(context.stdout, `Draft prewarm queued: ${display(refresh?.draft_prewarm?.enqueued_rows, 0)}`);
4075
+ } else {
4076
+ writeLine(context.stdout, "Run again with --apply to clear coach/draft cache and rebuild the queue row.");
4077
+ }
4078
+ }
4079
+
4080
+ function sumObjectValues(value) {
4081
+ if (!value || typeof value !== "object") return 0;
4082
+
4083
+ return Object.values(value).reduce((sum, item) => sum + Number(item || 0), 0);
4084
+ }
4085
+
4086
+ function formatObjectCounts(value) {
4087
+ if (!value || typeof value !== "object" || Object.keys(value).length === 0) return "none";
4088
+
4089
+ return Object.entries(value)
4090
+ .map(([key, count]) => `${key}:${count}`)
4091
+ .join(", ");
4092
+ }
4093
+
4001
4094
  function replanStatusLabel(payload) {
4002
4095
  if (payload?.status === "dry_run") return "dry run";
4003
4096
  if (payload?.status === "coach_error") return "coach error";
@@ -5575,6 +5668,8 @@ const HELP_TOPICS = new Map([
5575
5668
  " audienti prospects assign <prsp_id> --assigned-user <id|me|unassign>",
5576
5669
  " audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected>",
5577
5670
  " audienti prospects replan <prsp_id> [--apply]",
5671
+ " audienti prospects reenrich <prsp_id> [--apply]",
5672
+ " audienti prospects refresh-queue <prsp_id> [--apply]",
5578
5673
  " audienti prospects lock <prsp_id> [--note <text>]",
5579
5674
  " audienti prospects reject <prsp_id>",
5580
5675
  " audienti prospects nurture <prsp_id> [--reason <reason>]",
@@ -7080,6 +7175,8 @@ const HELP_TOPICS = new Map([
7080
7175
  " audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json]",
7081
7176
  " audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected> [--json]",
7082
7177
  " audienti prospects replan <prsp_id> [--apply] [--json]",
7178
+ " audienti prospects reenrich <prsp_id> [--profile <prof_id|citation_id>] [--apply] [--json]",
7179
+ " audienti prospects refresh-queue <prsp_id> [--apply] [--json]",
7083
7180
  " audienti prospects reject <prsp_id> [--json]",
7084
7181
  " audienti prospects nurture <prsp_id> [--reason <reason>] [--json]",
7085
7182
  " audienti prospects restore <prsp_id> [--json]",
@@ -7283,6 +7380,51 @@ const HELP_TOPICS = new Map([
7283
7380
  " }"
7284
7381
  ].join("\n")],
7285
7382
 
7383
+ ["prospects reenrich", [
7384
+ "Usage:",
7385
+ ` ${PROSPECTS_REENRICH_USAGE.slice("Usage: ".length)}`,
7386
+ "",
7387
+ "Status: implemented",
7388
+ "",
7389
+ "Purpose:",
7390
+ " Force a full LinkedIn person profile enrichment for one prospect from the CLI.",
7391
+ "",
7392
+ "Behavior:",
7393
+ " Defaults to a dry-run showing the selected profile, completeness signals, and whether a stale retry counter would be cleared.",
7394
+ " Pass --apply to queue ProfileEnrichJob with a maintenance origin and schedule expansion after enrichment.",
7395
+ "",
7396
+ "API:",
7397
+ " POST /api/v1/accounts/:account_id/prospects/:id/reenrich.json",
7398
+ "",
7399
+ "JSON body:",
7400
+ " {",
7401
+ " \"apply\": true,",
7402
+ " \"profile_id\": \"prof_abc123\"",
7403
+ " }"
7404
+ ].join("\n")],
7405
+
7406
+ ["prospects refresh-queue", [
7407
+ "Usage:",
7408
+ ` ${PROSPECTS_REFRESH_QUEUE_USAGE.slice("Usage: ".length)}`,
7409
+ "",
7410
+ "Status: implemented",
7411
+ "",
7412
+ "Purpose:",
7413
+ " Clear stale next-action coach and operator draft cache for one account prospect, then rebuild the queue row.",
7414
+ "",
7415
+ "Behavior:",
7416
+ " Defaults to a dry-run showing coach-cache and draft-cache state.",
7417
+ " Pass --apply to delete this prospect's account-scoped ProspectDraft rows, clear AccountProspect coach cache, and force the queue refresher.",
7418
+ "",
7419
+ "API:",
7420
+ " POST /api/v1/accounts/:account_id/prospects/:id/refresh_queue.json",
7421
+ "",
7422
+ "JSON body:",
7423
+ " {",
7424
+ " \"apply\": true",
7425
+ " }"
7426
+ ].join("\n")],
7427
+
7286
7428
  ["prospects reject", [
7287
7429
  "Usage:",
7288
7430
  ` ${PROSPECTS_REJECT_USAGE.slice("Usage: ".length)}`,