@audienti/cli 0.1.18 → 0.1.19

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,16 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.19] - 2026-07-17
8
+
9
+ ### Added
10
+
11
+ - Add `audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>]` to queue the LinkedIn Review / Blueprint report from the CLI.
12
+ - Add `audienti tools list` to show available CLI-backed tools and their report inspection commands.
13
+ - Add `audienti tools linkedin-review reports [--limit <n>]` to list recent LinkedIn Review reports and find report ids.
14
+ - Add `audienti tools linkedin-review show <rprt_id>` to print completed report content in the terminal.
15
+ - Add `audienti tools linkedin-review status <rprt_id>` to inspect report stage, run status, timestamps, and product URL while the profile review is building.
16
+
7
17
  ## [0.1.18] - 2026-07-17
8
18
 
9
19
  ### Added
package/README.md CHANGED
@@ -85,6 +85,11 @@ audienti analytics dashboard --play-tag wine_campaign
85
85
  audienti analytics users --user me --window 30d
86
86
  audienti analytics visibility --window 24h --user me
87
87
  audienti analytics content --window week
88
+ audienti tools list
89
+ audienti tools linkedin-review --url https://www.linkedin.com/in/example --icp <icp_id>
90
+ audienti tools linkedin-review reports
91
+ audienti tools linkedin-review show <rprt_id>
92
+ audienti tools linkedin-review status <rprt_id>
88
93
  ```
89
94
 
90
95
  To let an agent or operator check whether the local CLI is behind the latest
@@ -172,6 +177,18 @@ audienti prospects add-profile <prsp_id> --url https://www.linkedin.com/in/examp
172
177
  audienti prospects report-bad-profile <prsp_id> <prof_id>
173
178
  ```
174
179
 
180
+ To queue a personal LinkedIn profile authority review and ICP-fit positioning
181
+ blueprint, then check whether it is waiting on enrichment, running, completed,
182
+ or failed:
183
+
184
+ ```bash
185
+ audienti tools list
186
+ audienti tools linkedin-review --url https://www.linkedin.com/in/example --icp <icp_id>
187
+ audienti tools linkedin-review reports
188
+ audienti tools linkedin-review show <rprt_id>
189
+ audienti tools linkedin-review status <rprt_id>
190
+ ```
191
+
175
192
  To reassign or clear ownership for existing prospects:
176
193
 
177
194
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -67,4 +67,9 @@ audienti operator next --plan
67
67
  audienti analytics prospects --window 24h --json
68
68
  audienti analytics visibility --window 24h --user me --json
69
69
  audienti analytics content --window week --json
70
+ audienti tools list --json
71
+ audienti tools linkedin-review --url https://www.linkedin.com/in/example --icp <icp_id> --json
72
+ audienti tools linkedin-review reports --json
73
+ audienti tools linkedin-review show <rprt_id> --json
74
+ audienti tools linkedin-review status <rprt_id> --json
70
75
  ```
package/src/api-client.js CHANGED
@@ -465,6 +465,21 @@ export class AudientiClient {
465
465
  return this.requestJson(accountPath(accountId, ["prospect_imports", importId]));
466
466
  }
467
467
 
468
+ linkedinReviewReports(accountId, query = {}) {
469
+ return this.requestJson(accountPath(accountId, ["tools", "linkedin-review", "reports"], query));
470
+ }
471
+
472
+ linkedinReview(accountId, body) {
473
+ return this.requestJson(accountPath(accountId, ["tools", "linkedin-review", "reports"]), {
474
+ method: "POST",
475
+ body
476
+ });
477
+ }
478
+
479
+ linkedinReviewStatus(accountId, reportId) {
480
+ return this.requestJson(accountPath(accountId, ["tools", "linkedin-review", "reports", reportId]));
481
+ }
482
+
468
483
  operatorQueue(accountId, query = {}) {
469
484
  return this.requestJson(accountPath(accountId, ["operator"], query));
470
485
  }
package/src/cli.js CHANGED
@@ -82,6 +82,11 @@ const ANALYTICS_PROSPECTS_USAGE = "Usage: audienti analytics prospects [--window
82
82
  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>]";
83
83
  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>]";
84
84
  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>]";
85
+ const TOOLS_LIST_USAGE = "Usage: audienti tools list [--json]";
86
+ const TOOLS_LINKEDIN_REVIEW_USAGE = "Usage: audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>] [--json] [--account <acct_id>]";
87
+ const TOOLS_LINKEDIN_REVIEW_REPORTS_USAGE = "Usage: audienti tools linkedin-review reports [--limit <n>] [--json] [--account <acct_id>]";
88
+ const TOOLS_LINKEDIN_REVIEW_SHOW_USAGE = "Usage: audienti tools linkedin-review show <rprt_id> [--json] [--account <acct_id>]";
89
+ const TOOLS_LINKEDIN_REVIEW_STATUS_USAGE = "Usage: audienti tools linkedin-review status <rprt_id> [--json] [--account <acct_id>]";
85
90
  const COHORT_STAGE_ORDER = [
86
91
  "identified",
87
92
  "pre_connect",
@@ -247,7 +252,9 @@ async function dispatch(argv, context) {
247
252
  if (normalizedResource === "prospects" && action === "import-batch") return prospectsImportBatch(rest, context, { accountOverride });
248
253
  if (normalizedResource === "prospects" && action === "import-status") return prospectsImportStatus(rest, context, { accountOverride });
249
254
  if (normalizedResource === "writer" && action === "test-run") return writerTestRun(rest, context, { accountOverride });
255
+ if (normalizedResource === "tools" && action === "list") return toolsList(rest, context);
250
256
  if (normalizedResource === "tools" && action === "get") return toolsGet(rest, context, { accountOverride });
257
+ if (normalizedResource === "tools" && action === "linkedin-review") return toolsLinkedinReview(rest, context, { accountOverride });
251
258
  if (normalizedResource === "operator" && action === "queue") return operatorQueue(rest, context, { accountOverride });
252
259
  if (normalizedResource === "operator" && action === "next") return operatorNext(rest, context, { accountOverride });
253
260
  if (normalizedResource === "operator" && action === "outcome") return operatorOutcome(rest, context, { accountOverride });
@@ -2390,6 +2397,88 @@ async function toolsGet(args, context, { accountOverride } = {}) {
2390
2397
  if (response.import_id) writeLine(context.stdout, `Import: ${response.import_id}`);
2391
2398
  }
2392
2399
 
2400
+ async function toolsLinkedinReview(args, context, { accountOverride } = {}) {
2401
+ if (args[0] === "reports") return toolsLinkedinReviewReports(args.slice(1), context, { accountOverride });
2402
+ if (args[0] === "show") return toolsLinkedinReviewShow(args.slice(1), context, { accountOverride });
2403
+ if (args[0] === "status") return toolsLinkedinReviewStatus(args.slice(1), context, { accountOverride });
2404
+
2405
+ const { values, positionals } = parseCommandArgs(args, {
2406
+ ...jsonOptions(),
2407
+ url: { type: "string" },
2408
+ icp: { type: "string" }
2409
+ });
2410
+ const linkedinUrl = (values.url || positionals[0] || "").trim();
2411
+
2412
+ if (!linkedinUrl || positionals.length > (values.url ? 0 : 1)) {
2413
+ throw new CommandError(TOOLS_LINKEDIN_REVIEW_USAGE);
2414
+ }
2415
+
2416
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2417
+ const payload = await client.linkedinReview(accountId, {
2418
+ linkedin_url: linkedinUrl,
2419
+ icp_id: values.icp
2420
+ });
2421
+ if (values.json) return writeJson(context.stdout, payload);
2422
+
2423
+ renderLinkedinReviewStarted(payload, context);
2424
+ }
2425
+
2426
+ async function toolsList(args, context) {
2427
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
2428
+ if (positionals.length > 0) throw new CommandError(TOOLS_LIST_USAGE);
2429
+
2430
+ const payload = { tools: availableTools() };
2431
+ if (values.json) return writeJson(context.stdout, payload);
2432
+
2433
+ renderToolsList(payload.tools, context);
2434
+ }
2435
+
2436
+ async function toolsLinkedinReviewReports(args, context, { accountOverride } = {}) {
2437
+ const { values, positionals } = parseCommandArgs(args, {
2438
+ ...jsonOptions(),
2439
+ limit: { type: "string" }
2440
+ });
2441
+
2442
+ if (positionals.length > 0) {
2443
+ throw new CommandError(TOOLS_LINKEDIN_REVIEW_REPORTS_USAGE);
2444
+ }
2445
+
2446
+ const limit = boundedListLimit(values.limit);
2447
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2448
+ const payload = await client.linkedinReviewReports(accountId, { limit });
2449
+ if (values.json) return writeJson(context.stdout, payload);
2450
+
2451
+ renderLinkedinReviewReports(payload, context);
2452
+ }
2453
+
2454
+ async function toolsLinkedinReviewShow(args, context, { accountOverride } = {}) {
2455
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
2456
+
2457
+ if (positionals.length !== 1) {
2458
+ throw new CommandError(TOOLS_LINKEDIN_REVIEW_SHOW_USAGE);
2459
+ }
2460
+
2461
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2462
+ const payload = await client.linkedinReviewStatus(accountId, positionals[0]);
2463
+ if (values.json) return writeJson(context.stdout, payload);
2464
+
2465
+ renderLinkedinReviewReport(payload, context);
2466
+ }
2467
+
2468
+ async function toolsLinkedinReviewStatus(args, context, { accountOverride } = {}) {
2469
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
2470
+
2471
+ if (positionals.length !== 1) {
2472
+ throw new CommandError(TOOLS_LINKEDIN_REVIEW_STATUS_USAGE);
2473
+ }
2474
+
2475
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2476
+ const payload = await client.linkedinReviewStatus(accountId, positionals[0]);
2477
+ if (values.json) return writeJson(context.stdout, payload);
2478
+
2479
+ renderLinkedinReviewStatus(payload, context);
2480
+ }
2481
+
2393
2482
  async function operatorQueue(args, context, { accountOverride } = {}) {
2394
2483
  const { values, positionals } = parseCommandArgs(args, operatorFilterOptions());
2395
2484
  if (positionals.length > 0) throw new CommandError("Usage: audienti operator queue [--json] [filters] [--account <acct_id>]");
@@ -2628,6 +2717,15 @@ function jsonOptions() {
2628
2717
  };
2629
2718
  }
2630
2719
 
2720
+ function boundedListLimit(value) {
2721
+ if (value === undefined || value === null || value === "") return DEFAULT_LIST_LIMIT;
2722
+
2723
+ const parsed = Number.parseInt(String(value), 10);
2724
+ if (!Number.isFinite(parsed) || parsed < 1) throw new CommandError("--limit must be a positive integer.");
2725
+
2726
+ return Math.min(parsed, API_MAX_LIST_LIMIT);
2727
+ }
2728
+
2631
2729
  function operatorFilterOptions(extra = {}) {
2632
2730
  return {
2633
2731
  ...jsonOptions(),
@@ -4199,6 +4297,184 @@ function renderProspectImportStatus(payload, context) {
4199
4297
  writeLine(context.stdout, `Social profiles: ${socialCount}`);
4200
4298
  }
4201
4299
 
4300
+ function renderLinkedinReviewStarted(payload, context) {
4301
+ renderLinkedinReviewStatus(payload, context, { title: "LinkedIn review queued" });
4302
+ const reportId = payload?.report?.prefix_id;
4303
+ if (reportId) writeLine(context.stdout, `Run \`audienti tools linkedin-review status ${reportId}\` to check progress.`);
4304
+ }
4305
+
4306
+ function renderToolsList(tools, context) {
4307
+ writeAlignedTable(context, ["TOOL", "COMMAND", "REPORTS"], tools.map((tool) => [
4308
+ tool.id,
4309
+ tool.command,
4310
+ tool.reports_command || "-"
4311
+ ]));
4312
+ }
4313
+
4314
+ function renderLinkedinReviewReports(payload, context) {
4315
+ const rows = Array.isArray(payload?.reports) ? payload.reports : [];
4316
+ if (rows.length === 0) {
4317
+ writeLine(context.stdout, "No LinkedIn review reports found.");
4318
+ return;
4319
+ }
4320
+
4321
+ writeAlignedTable(context, ["REPORT ID", "STATUS", "STAGE", "PROFILE", "UPDATED"], rows.map(linkedinReviewReportRow));
4322
+ writeLine(context.stdout, "");
4323
+ writeLine(context.stdout, "Inspect one report with `audienti tools linkedin-review status <rprt_id>`.");
4324
+ }
4325
+
4326
+ function linkedinReviewReportRow(entry) {
4327
+ const report = entry?.report || {};
4328
+ const profile = entry?.profile || {};
4329
+
4330
+ return [
4331
+ display(report.prefix_id),
4332
+ display(report.display_status || report.status),
4333
+ display(report.stage),
4334
+ display(profile.display_name || profile.url || profile.username || report.title || report.input_url),
4335
+ display(report.updated_at)
4336
+ ];
4337
+ }
4338
+
4339
+ function renderLinkedinReviewStatus(payload, context, { title = "LinkedIn review status" } = {}) {
4340
+ const report = payload?.report || {};
4341
+ const profile = payload?.profile || {};
4342
+ const run = payload?.run || {};
4343
+ const queue = payload?.queue || {};
4344
+ const icp = payload?.icp || {};
4345
+
4346
+ writeLine(context.stdout, `${title}: ${display(report.prefix_id)}`);
4347
+ writeLine(context.stdout, `Status: ${display(report.display_status || report.status)}`);
4348
+ if (report.stage) writeLine(context.stdout, `Stage: ${report.stage}`);
4349
+ if (profile.url) writeLine(context.stdout, `Profile: ${profile.url}`);
4350
+ if (profile.display_name) writeLine(context.stdout, `Profile name: ${profile.display_name}`);
4351
+ if (icp.name || icp.id) writeLine(context.stdout, `ICP: ${display(icp.name)} (${display(icp.id)})`);
4352
+ if (run.status) writeLine(context.stdout, `Run: ${run.status}`);
4353
+ if (queue.state && queue.state !== "none") {
4354
+ writeLine(context.stdout, `Queue: ${queue.state} (${display(queue.pending_count, 0)} pending)`);
4355
+ }
4356
+ if (report.updated_at) writeLine(context.stdout, `Updated: ${report.updated_at}`);
4357
+ if (report.completed_at) writeLine(context.stdout, `Completed: ${report.completed_at}`);
4358
+ if (report.url) writeLine(context.stdout, `URL: ${report.url}`);
4359
+ }
4360
+
4361
+ function renderLinkedinReviewReport(payload, context) {
4362
+ renderLinkedinReviewStatus(payload, context, { title: "LinkedIn review report" });
4363
+
4364
+ const report = payload?.report || {};
4365
+ const content = payload?.content?.payload || {};
4366
+ if (!content || Object.keys(content).length === 0) {
4367
+ writeLine(context.stdout, "");
4368
+ writeLine(context.stdout, report.display_status === "completed" || report.status === "completed"
4369
+ ? "No report content is available yet."
4370
+ : "Report content is not available until the review completes.");
4371
+ return;
4372
+ }
4373
+
4374
+ const observed = objectValue(content.observed_profile);
4375
+ const scores = objectValue(content.scores);
4376
+ const findings = objectValue(content.findings);
4377
+ const strategy = objectValue(content.strategy);
4378
+ const rewrite = objectValue(content.rewrite);
4379
+ const leadMagnets = Array.isArray(content.lead_magnets) ? content.lead_magnets : [];
4380
+
4381
+ writeSection(context, "Summary");
4382
+ writeField(context, "Name", observed.name || report.title);
4383
+ writeField(context, "Headline", observed.headline);
4384
+ writeField(context, "Location", observed.location);
4385
+ writeField(context, "Authority score", scores.authority_score);
4386
+ writeField(context, "Score summary", scores.summary);
4387
+ writeField(context, "Bottom line", findings.bottom_line);
4388
+
4389
+ writeSection(context, "Strategy");
4390
+ writeField(context, "Buyer persona", strategy.buyer_persona);
4391
+ writeField(context, "Strategic gap", strategy.strategic_gap);
4392
+ writeField(context, "Opportunity", strategy.strategic_opportunity);
4393
+ writeField(context, "Fit", strategy.fit_assessment);
4394
+ writeBullets(context, "Next steps", strategy.next_steps);
4395
+
4396
+ writeSection(context, "Recommended Rewrite");
4397
+ writeField(context, "Headline", rewrite.recommended_headline);
4398
+ writeField(context, "Why", rewrite.recommended_reason);
4399
+ writeField(context, "Bio", rewrite.recommended_bio);
4400
+ writeBullets(context, "Improvement suggestions", rewrite.improvement_suggestions);
4401
+
4402
+ writeSection(context, "Findings");
4403
+ writeBullets(context, "What's working", Array.isArray(findings.whats_working) ? findings.whats_working.map(summaryItem) : []);
4404
+ writeBullets(context, "Revenue leaks", Array.isArray(findings.revenue_leaks) ? findings.revenue_leaks.map(summaryItem) : []);
4405
+
4406
+ writeSection(context, "Lead Magnets");
4407
+ if (leadMagnets.length === 0) {
4408
+ writeLine(context.stdout, "None");
4409
+ } else {
4410
+ leadMagnets.slice(0, 5).forEach((magnet, index) => {
4411
+ const headline = display(magnet?.headline || magnet?.title, `Idea ${index + 1}`);
4412
+ const contentType = magnet?.content_type ? ` (${magnet.content_type})` : "";
4413
+ writeLine(context.stdout, `${index + 1}. ${headline}${contentType}`);
4414
+ if (magnet?.subheadline) writeLine(context.stdout, ` ${magnet.subheadline}`);
4415
+ if (magnet?.description) writeLine(context.stdout, ` ${magnet.description}`);
4416
+ });
4417
+ }
4418
+ }
4419
+
4420
+ function objectValue(value) {
4421
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
4422
+ }
4423
+
4424
+ function writeSection(context, title) {
4425
+ writeLine(context.stdout, "");
4426
+ writeLine(context.stdout, title);
4427
+ writeLine(context.stdout, "-".repeat(title.length));
4428
+ }
4429
+
4430
+ function writeField(context, label, value) {
4431
+ const text = String(display(value)).trim();
4432
+ if (!text) return;
4433
+
4434
+ writeLine(context.stdout, `${label}: ${text}`);
4435
+ }
4436
+
4437
+ function writeBullets(context, label, values) {
4438
+ const rows = Array.isArray(values) ? values.map((value) => String(display(value)).trim()).filter(Boolean) : [];
4439
+ if (rows.length === 0) return;
4440
+
4441
+ writeLine(context.stdout, `${label}:`);
4442
+ rows.forEach((row) => writeLine(context.stdout, `- ${row}`));
4443
+ }
4444
+
4445
+ function summaryItem(item) {
4446
+ if (!item || typeof item !== "object") return item;
4447
+
4448
+ return [item.title, item.description].map((value) => String(display(value)).trim()).filter(Boolean).join(": ");
4449
+ }
4450
+
4451
+ function availableTools() {
4452
+ return [
4453
+ {
4454
+ id: "get-email",
4455
+ command: "audienti tools get email --url <linkedin_url>",
4456
+ description: "Find the first selected email for a LinkedIn person URL.",
4457
+ reports_command: null,
4458
+ status_command: null
4459
+ },
4460
+ {
4461
+ id: "get-phone",
4462
+ command: "audienti tools get phone --url <linkedin_url>",
4463
+ description: "Find the first selected phone for a LinkedIn person URL.",
4464
+ reports_command: null,
4465
+ status_command: null
4466
+ },
4467
+ {
4468
+ id: "linkedin-review",
4469
+ command: "audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>]",
4470
+ description: "Create a LinkedIn personal profile authority review and ICP-fit positioning blueprint.",
4471
+ reports_command: "audienti tools linkedin-review reports",
4472
+ status_command: "audienti tools linkedin-review status <rprt_id>",
4473
+ show_command: "audienti tools linkedin-review show <rprt_id>"
4474
+ }
4475
+ ];
4476
+ }
4477
+
4202
4478
  function writeProspectImportProspectLine(payload, context) {
4203
4479
  const prospect = payload?.prospect;
4204
4480
  if (!prospect) return;
@@ -5131,8 +5407,12 @@ const HELP_TOPICS = new Map([
5131
5407
  " audienti analytics content --window week",
5132
5408
  "",
5133
5409
  " Utilities",
5410
+ " audienti tools list",
5134
5411
  " audienti tools get email --url <linkedin_url>",
5135
5412
  " audienti tools get phone --url <linkedin_url>",
5413
+ " audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>]",
5414
+ " audienti tools linkedin-review reports",
5415
+ " audienti tools linkedin-review show <rprt_id>",
5136
5416
  "",
5137
5417
  "Common flows:",
5138
5418
  " Work the next move: audienti operator next --plan",
@@ -7189,12 +7469,36 @@ const HELP_TOPICS = new Map([
7189
7469
 
7190
7470
  ["tools", [
7191
7471
  "Usage:",
7472
+ " audienti tools list [--json]",
7192
7473
  " audienti tools get <email|phone> --url <linkedin_url> [--json]",
7474
+ " audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>] [--json]",
7475
+ " audienti tools linkedin-review reports [--limit <n>] [--json]",
7476
+ " audienti tools linkedin-review show <rprt_id> [--json]",
7477
+ " audienti tools linkedin-review status <rprt_id> [--json]",
7193
7478
  "",
7194
7479
  "Status: implemented",
7195
7480
  "",
7196
7481
  "Commands:",
7197
- " audienti tools get Run a LinkedIn URL through the existing import and contact-enrichment pipeline, then return the first selected email or phone."
7482
+ " audienti tools list Show available CLI tools and the report commands they support.",
7483
+ " audienti tools get Run a LinkedIn URL through the existing import and contact-enrichment pipeline, then return the first selected email or phone.",
7484
+ " audienti tools linkedin-review Queue a LinkedIn personal profile authority review and ICP-fit positioning blueprint.",
7485
+ " audienti tools linkedin-review reports List recent LinkedIn Review reports for the active account.",
7486
+ " audienti tools linkedin-review show View the completed report content in the terminal.",
7487
+ " audienti tools linkedin-review status Show the current report stage and run status."
7488
+ ].join("\n")],
7489
+
7490
+ ["tools list", [
7491
+ "Usage:",
7492
+ ` ${TOOLS_LIST_USAGE.slice("Usage: ".length)}`,
7493
+ "",
7494
+ "Status: implemented",
7495
+ "",
7496
+ "Purpose:",
7497
+ " Shows the available CLI-backed tools and which commands create or inspect reports.",
7498
+ "",
7499
+ "Output:",
7500
+ " Plain text: tool id, create command, and reports command",
7501
+ " JSON: { tools }"
7198
7502
  ].join("\n")],
7199
7503
 
7200
7504
  ["tools get", [
@@ -7223,6 +7527,98 @@ const HELP_TOPICS = new Map([
7223
7527
  " JSON: { kind, url, found, value, import_id, status, ready, prospect, pipeline }"
7224
7528
  ].join("\n")],
7225
7529
 
7530
+ ["tools linkedin-review", [
7531
+ "Usage:",
7532
+ " audienti tools linkedin-review --url <linkedin_url> [--icp <icp_id>] [--json] [--account <acct_id>]",
7533
+ " audienti tools linkedin-review reports [--limit <n>] [--json] [--account <acct_id>]",
7534
+ " audienti tools linkedin-review show <rprt_id> [--json] [--account <acct_id>]",
7535
+ " audienti tools linkedin-review status <rprt_id> [--json] [--account <acct_id>]",
7536
+ "",
7537
+ "Status: implemented",
7538
+ "",
7539
+ "Purpose:",
7540
+ " Queues the same LinkedIn Review / Blueprint report as the web tool for a LinkedIn person profile.",
7541
+ "",
7542
+ "Input shape:",
7543
+ " linkedin_url: url LinkedIn person profile URL, not a company URL",
7544
+ " icp_id: icpp_ id or numeric id | optional buyer context for positioning rewrites",
7545
+ "",
7546
+ "Behavior:",
7547
+ " Creates a profile-backed LinkedIn Blueprint report, starts profile enrichment when needed, and queues the authority review once the profile is ready.",
7548
+ " The command returns the report URL and status command immediately; report generation continues in Audienti.",
7549
+ "",
7550
+ "Options:",
7551
+ " --url <linkedin_url> LinkedIn person profile URL",
7552
+ " --icp <icp_id> Optional ICP to tune positioning recommendations",
7553
+ "",
7554
+ "Output:",
7555
+ " Plain text: queued report id, status, profile, ICP, queue state, and product URL",
7556
+ " JSON: { report, profile, run, queue, icp, queued }",
7557
+ "",
7558
+ "API:",
7559
+ " POST /api/v1/accounts/:account_id/tools/linkedin-review/reports.json"
7560
+ ].join("\n")],
7561
+
7562
+ ["tools linkedin-review reports", [
7563
+ "Usage:",
7564
+ ` ${TOOLS_LINKEDIN_REVIEW_REPORTS_USAGE.slice("Usage: ".length)}`,
7565
+ "",
7566
+ "Status: implemented",
7567
+ "",
7568
+ "Purpose:",
7569
+ " Lists recent LinkedIn Review reports for the active account so you can find report ids and inspect progress.",
7570
+ "",
7571
+ "Options:",
7572
+ " --limit <n> Number of recent reports to return. Default: 20, max: 100",
7573
+ "",
7574
+ "Output:",
7575
+ " Plain text: report id, status, stage, profile, and updated timestamp",
7576
+ " JSON: { reports, count, limit }",
7577
+ "",
7578
+ "API:",
7579
+ " GET /api/v1/accounts/:account_id/tools/linkedin-review/reports.json"
7580
+ ].join("\n")],
7581
+
7582
+ ["tools linkedin-review show", [
7583
+ "Usage:",
7584
+ ` ${TOOLS_LINKEDIN_REVIEW_SHOW_USAGE.slice("Usage: ".length)}`,
7585
+ "",
7586
+ "Status: implemented",
7587
+ "",
7588
+ "Purpose:",
7589
+ " Prints the completed LinkedIn Review report content in the terminal.",
7590
+ "",
7591
+ "Input shape:",
7592
+ " rprt_id: rprt_ report id from `audienti tools linkedin-review reports`",
7593
+ "",
7594
+ "Output:",
7595
+ " Plain text: summary, strategy, rewrite, findings, lead magnets, and report URL",
7596
+ " JSON: { report, profile, run, queue, icp, content }",
7597
+ "",
7598
+ "API:",
7599
+ " GET /api/v1/accounts/:account_id/tools/linkedin-review/reports/:id.json"
7600
+ ].join("\n")],
7601
+
7602
+ ["tools linkedin-review status", [
7603
+ "Usage:",
7604
+ " audienti tools linkedin-review status <rprt_id> [--json] [--account <acct_id>]",
7605
+ "",
7606
+ "Status: implemented",
7607
+ "",
7608
+ "Purpose:",
7609
+ " Shows whether a LinkedIn Review report is waiting on enrichment, running, completed, or failed.",
7610
+ "",
7611
+ "Input shape:",
7612
+ " rprt_id: rprt_ report id returned by `audienti tools linkedin-review`",
7613
+ "",
7614
+ "Output:",
7615
+ " Plain text: report status, stage, run status, queue state, timestamps, and product URL",
7616
+ " JSON: { report, profile, run, queue, icp, queued }",
7617
+ "",
7618
+ "API:",
7619
+ " GET /api/v1/accounts/:account_id/tools/linkedin-review/reports/:id.json"
7620
+ ].join("\n")],
7621
+
7226
7622
  ["operator", [
7227
7623
  "Usage:",
7228
7624
  " audienti operator next [--json|--plan|--done|--skip|--fail|--return]",