@audienti/cli 0.1.98 → 0.1.100

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,19 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.100] - 2026-10-05
8
+
9
+ ### Changed
10
+
11
+ - The setup state returned by the API now includes `linkedin_sign_in` (not_started, signing_in, code_needed, approval_needed, connected, failed or needs_attention) and `linkedin_account_id`.
12
+ - A LinkedIn social account can be created with only its sign-in email and password; the profile handle is read after sign-in.
13
+
14
+ ## [0.1.99] - 2026-10-05
15
+
16
+ - List user-owned content plans and read scripts with `content plans` and `content plan --report`.
17
+ - Edit, approve, research, draft and generate visuals for a plan piece through the existing production services.
18
+ - Approve an explicit comment reply through the tracked post endpoint with `content post-reply`.
19
+
7
20
  ## [0.1.98] - 2026-10-04
8
21
 
9
22
  ### Added
package/README.md CHANGED
@@ -189,6 +189,14 @@ audienti content track <linkedin_post_url>
189
189
  audienti content posts
190
190
  audienti content engagement <cpwi_id> --json
191
191
  audienti content plan <cprg_id>
192
+ audienti content plans --user me
193
+ audienti content plan <rprt_id> --report --user me
194
+ audienti content plan-update <rprt_id> --day 1 --payload edits.json
195
+ audienti content plan-approve <rprt_id> --day 1
196
+ audienti content plan-research <rprt_id> --day 1
197
+ audienti content plan-draft <rprt_id> --day 1 --feedback "Revise the opening"
198
+ audienti content plan-visuals <rprt_id> --day 1 --style <id>
199
+ audienti content post-reply <cpwi_id> --comment <task_id> --body "Approved reply"
192
200
  audienti content approve <cpwi_id>
193
201
  audienti content comments
194
202
  audienti social-cookies sync-messages <scok_id> [--folder <folder>] [--retry] --json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.98",
3
+ "version": "0.1.100",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -695,6 +695,38 @@ export class AudientiClient {
695
695
  return this.requestJson(accountPath(accountId, ["content_ops", "programs", programId, "plan"], query));
696
696
  }
697
697
 
698
+ contentPlans(accountId, query = {}) {
699
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans"], query));
700
+ }
701
+
702
+ contentPlanReport(accountId, reportId, query = {}) {
703
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId], query));
704
+ }
705
+
706
+ contentPlanUpdate(accountId, reportId, day, body = {}) {
707
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId, "items", day]), { method: "PATCH", body });
708
+ }
709
+
710
+ contentPlanApprove(accountId, reportId, day, body = {}) {
711
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId, "items", day, "approve"]), { method: "POST", body });
712
+ }
713
+
714
+ contentPlanResearch(accountId, reportId, day, body = {}) {
715
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId, "items", day, "research"]), { method: "POST", body });
716
+ }
717
+
718
+ contentPlanDraft(accountId, reportId, day, body = {}) {
719
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId, "items", day, "draft"]), { method: "POST", body });
720
+ }
721
+
722
+ contentPlanVisuals(accountId, reportId, day, body = {}) {
723
+ return this.requestJson(accountPath(accountId, ["content_ops", "plans", reportId, "items", day, "visuals"]), { method: "POST", body });
724
+ }
725
+
726
+ contentPostReply(accountId, workItemId, taskId, body = {}) {
727
+ return this.requestJson(accountPath(accountId, ["content_ops", "tracked_posts", workItemId, "comments", taskId, "reply"]), { method: "POST", body });
728
+ }
729
+
698
730
  contentWorkItem(accountId, workItemId) {
699
731
  return this.requestJson(accountPath(accountId, ["content_ops", "work_items", workItemId]));
700
732
  }
package/src/cli.js CHANGED
@@ -166,7 +166,9 @@ const WRITER_TEST_RUN_SHOW_USAGE = "Usage: audienti writer test-run show <prsp_i
166
166
  const MOTIONS_ANALYTICS_USAGE = "Usage: audienti motions analytics <motn_id> [--window 30d] [--json] [--account <acct_id>]";
167
167
  const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> ([--status <draft|preparing|active|closing|paused|archived>] [--tags <tag[,tag...]>] [--own-post-engagement <true|false>] [--start-date <YYYY-MM-DD|none>] [--end-date <YYYY-MM-DD|none>] [--maximum-company-count <n|none>] [--approach <text>] [--gift <gift_id|none>] | --payload <file.json>) [--json] [--account <acct_id>]";
168
168
  const CONTENT_PROGRAMS_USAGE = "Usage: audienti content programs [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
169
- const CONTENT_PLAN_USAGE = "Usage: audienti content plan <cprg_id> [--week <n>] [--due] [--json] [--account <acct_id>]";
169
+ const CONTENT_PLAN_USAGE = "Usage: audienti content plan <cprg_id|rprt_id> [--report] [--user <id|me>] [--week <n>] [--due] [--json] [--account <acct_id>]";
170
+ const CONTENT_PLANS_USAGE = "Usage: audienti content plans [--user <id|me>] [--page <n>] [--json] [--account <acct_id>]";
171
+ const CONTENT_POST_REPLY_USAGE = "Usage: audienti content post-reply <cpwi_id> --comment <cctk_id> --body <text> [--user <id|me>] [--json] [--account <acct_id>]";
170
172
  const CONTENT_SHOW_USAGE = "Usage: audienti content show <cpwi_id> [--json] [--account <acct_id>]";
171
173
  const CONTENT_POSTS_USAGE = "Usage: audienti content posts [--user <account_user_id|email|name|me>] [--page <n>] [--json] [--account <acct_id>]";
172
174
  const CONTENT_TRACK_USAGE = "Usage: audienti content track <linkedin_post_url> [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
@@ -451,6 +453,9 @@ async function dispatch(argv, context) {
451
453
  if (normalizedResource === "motions" && action === "quick-start") return motionsQuickStart(rest, context, { accountOverride });
452
454
  if (normalizedResource === "motions" && action === "setup-state") return motionsSetupState(rest, context, { accountOverride });
453
455
  if (normalizedResource === "content" && action === "programs") return contentPrograms(rest, context, { accountOverride });
456
+ if (normalizedResource === "content" && action === "plans") return contentPlans(rest, context, { accountOverride });
457
+ if (normalizedResource === "content" && ["plan-update", "plan-approve", "plan-research", "plan-draft", "plan-visuals"].includes(action)) return contentPlanAction(action, rest, context, { accountOverride });
458
+ if (normalizedResource === "content" && action === "post-reply") return contentPostReply(rest, context, { accountOverride });
454
459
  if (normalizedResource === "content" && action === "plan") return contentPlan(rest, context, { accountOverride });
455
460
  if (normalizedResource === "content" && action === "show") return contentShow(rest, context, { accountOverride });
456
461
  if (normalizedResource === "content" && action === "posts") return contentPosts(rest, context, { accountOverride });
@@ -3853,18 +3858,71 @@ async function contentPrograms(args, context, { accountOverride } = {}) {
3853
3858
  renderContentPrograms(programs, context);
3854
3859
  }
3855
3860
 
3861
+ async function contentPlans(args, context, { accountOverride } = {}) {
3862
+ const { values, positionals } = parseCommandArgs(args, { ...jsonOptions(), user: { type: "string" }, page: { type: "string" } });
3863
+ if (positionals.length) throw new CommandError(CONTENT_PLANS_USAGE);
3864
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3865
+ const payload = await client.contentPlans(accountId, compactObject({ user: values.user, page: values.page }));
3866
+ if (values.json) return writeJson(context.stdout, payload);
3867
+ for (const plan of payload.plans || []) context.stdout.write(`${plan.prefix_id} ${plan.channel} ${plan.status} ${plan.title}\n`);
3868
+ context.stdout.write("Open a plan: content plan <rprt_id> --report\n");
3869
+ if (payload.next_page) context.stdout.write(`More plans: content plans --page ${payload.next_page}\n`);
3870
+ }
3871
+
3872
+ async function contentPlanAction(action, args, context, { accountOverride } = {}) {
3873
+ const usage = `Usage: audienti content ${action} <rprt_id> --day <n> [--user <id|me>] [--payload <file.json>] [--feedback <text>] [--style <id>] [--aspect-ratio <w:h>] [--json] [--account <acct_id>]`;
3874
+ const { values, positionals } = parseCommandArgs(args, { ...jsonOptions(), day: { type: "string" }, user: { type: "string" }, payload: { type: "string" }, feedback: { type: "string" }, style: { type: "string" }, "aspect-ratio": { type: "string" } });
3875
+ const day = Number(values.day);
3876
+ if (positionals.length !== 1 || !Number.isInteger(day) || day < 1 || (action === "plan-update" && !values.payload)) throw new CommandError(usage);
3877
+ if (values["aspect-ratio"] && !/^\d+:\d+$/.test(values["aspect-ratio"])) throw new CommandError("Aspect ratio must be w:h.");
3878
+ const body = compactObject({ user: values.user });
3879
+ if (action === "plan-update") {
3880
+ body.item = await readJsonPayload(values.payload);
3881
+ if (!body.item || typeof body.item !== "object" || Array.isArray(body.item)) throw new CommandError("Plan update payload must be a JSON object.");
3882
+ }
3883
+ if (action === "plan-draft") body.draft_feedback = values.feedback || "";
3884
+ if (action === "plan-visuals") body.visual_generation = compactObject({ ad_style_id: values.style, aspect_ratio_option: values["aspect-ratio"] });
3885
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3886
+ let result;
3887
+ if (action === "plan-update") result = await client.contentPlanUpdate(accountId, positionals[0], day, body);
3888
+ else if (action === "plan-approve") result = await client.contentPlanApprove(accountId, positionals[0], day, body);
3889
+ else if (action === "plan-research") result = await client.contentPlanResearch(accountId, positionals[0], day, body);
3890
+ else if (action === "plan-draft") result = await client.contentPlanDraft(accountId, positionals[0], day, body);
3891
+ else result = await client.contentPlanVisuals(accountId, positionals[0], day, body);
3892
+ if (values.json) return writeJson(context.stdout, result);
3893
+ context.stdout.write(`${result.title || "Content plan"}: ${result.status}\n`);
3894
+ }
3895
+
3896
+ async function contentPostReply(args, context, { accountOverride } = {}) {
3897
+ const { values, positionals } = parseCommandArgs(args, { ...jsonOptions(), comment: { type: "string" }, body: { type: "string" }, user: { type: "string" } });
3898
+ if (positionals.length !== 1 || !values.comment || !values.body?.trim()) throw new CommandError(CONTENT_POST_REPLY_USAGE);
3899
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3900
+ const result = await client.contentPostReply(accountId, positionals[0], values.comment, compactObject({ reply_body: values.body, user: values.user }));
3901
+ if (values.json) return writeJson(context.stdout, result);
3902
+ context.stdout.write(`Reply approved for post ${result.prefix_id}; check engagement for delivery status.\n`);
3903
+ }
3904
+
3856
3905
  async function contentPlan(args, context, { accountOverride } = {}) {
3857
3906
  const { values, positionals } = parseCommandArgs(args, {
3858
3907
  ...jsonOptions(),
3859
3908
  week: { type: "string" },
3860
- due: { type: "boolean" }
3909
+ due: { type: "boolean" },
3910
+ report: { type: "boolean" },
3911
+ user: { type: "string" }
3861
3912
  });
3862
3913
  if (positionals.length !== 1) throw new CommandError(CONTENT_PLAN_USAGE);
3863
3914
 
3864
3915
  const { client, accountId } = await requireAccountContext(context, { accountOverride });
3865
- const payload = await client.contentPlan(accountId, positionals[0]);
3916
+ const payload = values.report
3917
+ ? await client.contentPlanReport(accountId, positionals[0], compactObject({ user: values.user }))
3918
+ : await client.contentPlan(accountId, positionals[0]);
3866
3919
  if (values.json) return writeJson(context.stdout, payload);
3867
3920
 
3921
+ if (values.report) {
3922
+ context.stdout.write(`${payload.title || "Content plan"}: ${payload.status}\n`);
3923
+ for (const row of payload.content_plan || []) context.stdout.write(`Day ${row.day_number} ${row.channel} ${row.title} ${row.execution?.workflow_phase || "Not started"}\n${row.finalized_content || ""}\n`);
3924
+ return;
3925
+ }
3868
3926
  const week = values.week ? Number.parseInt(values.week, 10) : null;
3869
3927
  let rows = Array.isArray(payload?.rows) ? payload.rows : [];
3870
3928
  if (week) rows = rows.filter((row) => Number(row.week_number) === week);
@@ -12625,6 +12683,9 @@ const HELP_TOPICS = new Map([
12625
12683
 
12626
12684
  ["content programs", [CONTENT_PROGRAMS_USAGE].join("\n")],
12627
12685
  ["content plan", [CONTENT_PLAN_USAGE].join("\n")],
12686
+ ["content plans", CONTENT_PLANS_USAGE],
12687
+ ["content post-reply", CONTENT_POST_REPLY_USAGE],
12688
+ ...["plan-update", "plan-approve", "plan-research", "plan-draft", "plan-visuals"].map((action) => [`content ${action}`, `Usage: audienti content ${action} <rprt_id> --day <n> [--user <id|me>] [--payload <file.json>] [--feedback <text>] [--style <id>] [--aspect-ratio <w:h>] [--json] [--account <acct_id>]`]),
12628
12689
  ["content show", [CONTENT_SHOW_USAGE].join("\n")],
12629
12690
  ["content posts", [CONTENT_POSTS_USAGE].join("\n")],
12630
12691
  ["content track", [CONTENT_TRACK_USAGE].join("\n")],