@audienti/cli 0.1.88 → 0.1.89

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,15 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.89] - 2026-10-01
8
+
9
+ ### Added
10
+
11
+ - `offers show` lists the offer's gifts and insights. A gift is a free, useful thing the offer already has; it is ready once it has a send link or a file.
12
+ - `offers add-gift`, `offers update-gift`, `offers turn-off-gift`, and `offers turn-on-gift` manage an offer's gifts. `offers update-gift --remove-file` takes the attached file off a gift.
13
+ - `offers update-insight`, `offers turn-off-insight`, and `offers turn-on-insight` edit an offer's insights.
14
+ - `motions create` and `motions update` accept `--gift <gift_id|none>` to choose a ready gift from the motion's own offer. Motion output shows the gift.
15
+
7
16
  ## [0.1.88] - 2026-10-01
8
17
 
9
18
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -188,6 +188,27 @@ export class AudientiClient {
188
188
  });
189
189
  }
190
190
 
191
+ createOfferGift(accountId, offerId, body) {
192
+ return this.requestJson(accountPath(accountId, ["offers", offerId, "gifts"]), {
193
+ method: "POST",
194
+ body
195
+ });
196
+ }
197
+
198
+ updateOfferGift(accountId, offerId, giftId, body) {
199
+ return this.requestJson(accountPath(accountId, ["offers", offerId, "gifts", giftId]), {
200
+ method: "PATCH",
201
+ body
202
+ });
203
+ }
204
+
205
+ updateOfferInsight(accountId, offerId, insightId, body) {
206
+ return this.requestJson(accountPath(accountId, ["offers", offerId, "insights", insightId]), {
207
+ method: "PATCH",
208
+ body
209
+ });
210
+ }
211
+
191
212
  icps(accountId, query = {}) {
192
213
  return this.requestJson(accountPath(accountId, ["icps"], query));
193
214
  }
package/src/cli.js CHANGED
@@ -162,7 +162,7 @@ const OFFERS_DELETE_USAGE = "Usage: audienti offers delete <offr_id> --confirm <
162
162
  const WRITER_TEST_RUN_USAGE = "Usage: audienti writer test-run <prsp_id> [--json] [--mode <plan|report|step>] [--branch <both|no-accept|accepted>] [--step <step_key|row_number>] [--report <rprt_id>] [--no-wait] [--timeout-seconds <n>] [--poll-interval-seconds <n>] [--account <acct_id>]";
163
163
  const WRITER_TEST_RUN_SHOW_USAGE = "Usage: audienti writer test-run show <prsp_id> <rprt_id> [--json] [--account <acct_id>]";
164
164
  const MOTIONS_ANALYTICS_USAGE = "Usage: audienti motions analytics <motn_id> [--window 30d] [--json] [--account <acct_id>]";
165
- 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>] | --payload <file.json>) [--json] [--account <acct_id>]";
165
+ 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>]";
166
166
  const CONTENT_PROGRAMS_USAGE = "Usage: audienti content programs [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
167
167
  const CONTENT_PLAN_USAGE = "Usage: audienti content plan <cprg_id> [--week <n>] [--due] [--json] [--account <acct_id>]";
168
168
  const CONTENT_SHOW_USAGE = "Usage: audienti content show <cpwi_id> [--json] [--account <acct_id>]";
@@ -238,6 +238,14 @@ const OFFERS_REGENERATE_RESEARCH_USAGE = "Usage: audienti offers regenerate-rese
238
238
  const OFFERS_UPDATE_WRITEUP_USAGE = "Usage: audienti offers update-writeup <offr_id> --description <text> [--json] [--account <acct_id>]";
239
239
  const OFFERS_ADD_ARTIFACTS_USAGE = "Usage: audienti offers add-artifacts <offr_id> <file> [file...] [--json] [--account <acct_id>]";
240
240
  const OFFERS_REMOVE_ARTIFACT_USAGE = "Usage: audienti offers remove-artifact <offr_id> <artifact_id> [--json] [--account <acct_id>]";
241
+ const OFFERS_ADD_GIFT_USAGE = "Usage: audienti offers add-gift <offr_id> --title <text> [--summary <text>] [--send-url <url>] [--file <path>] [--json] [--account <acct_id>]";
242
+ const OFFERS_UPDATE_GIFT_USAGE = "Usage: audienti offers update-gift <offr_id> <gift_id> [--title <text>] [--summary <text>] [--send-url <url>] [--file <path>] [--remove-file] [--status <on|off>] [--json] [--account <acct_id>]";
243
+ const OFFERS_TURN_OFF_GIFT_USAGE = "Usage: audienti offers turn-off-gift <offr_id> <gift_id> [--json] [--account <acct_id>]";
244
+ const OFFERS_TURN_ON_GIFT_USAGE = "Usage: audienti offers turn-on-gift <offr_id> <gift_id> [--json] [--account <acct_id>]";
245
+ const OFFERS_UPDATE_INSIGHT_USAGE = "Usage: audienti offers update-insight <offr_id> <insight_id> [--content <text>] [--source-url <url>] [--status <on|off>] [--json] [--account <acct_id>]";
246
+ const OFFERS_TURN_OFF_INSIGHT_USAGE = "Usage: audienti offers turn-off-insight <offr_id> <insight_id> [--json] [--account <acct_id>]";
247
+ const OFFERS_TURN_ON_INSIGHT_USAGE = "Usage: audienti offers turn-on-insight <offr_id> <insight_id> [--json] [--account <acct_id>]";
248
+ const MOTIONS_CREATE_USAGE = "Usage: audienti motions create --payload <file.json> [--gift <gift_id|none>] [--json] [--account <acct_id>]";
241
249
  const TASKS_UPDATE_USAGE = "Usage: audienti tasks update <ptsk_id> [--title <text>] [--due <time>] [--notes <text>] [--prospect <prsp_id|\"\">] [--list <list_id|\"\">] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
242
250
  const TASKS_BULK_UPDATE_USAGE = "Usage: audienti tasks bulk-update --action <complete|reassign> [--assigned-user <id|me>] <ptsk_id> [ptsk_id...] [--json] [--account <acct_id>]";
243
251
  const SOCIAL_COOKIES_SYNC_MESSAGES_USAGE = "Usage: audienti social-cookies sync-messages <scok_id> [--folder <folder>] [--retry] [--json] [--account <acct_id>]";
@@ -351,6 +359,13 @@ async function dispatch(argv, context) {
351
359
  if (normalizedResource === "offers" && action === "update-writeup") return offersUpdateWriteup(rest, context, { accountOverride });
352
360
  if (normalizedResource === "offers" && action === "add-artifacts") return offersAddArtifacts(rest, context, { accountOverride });
353
361
  if (normalizedResource === "offers" && action === "remove-artifact") return offersRemoveArtifact(rest, context, { accountOverride });
362
+ if (normalizedResource === "offers" && action === "add-gift") return offersAddGift(rest, context, { accountOverride });
363
+ if (normalizedResource === "offers" && action === "update-gift") return offersUpdateGift(rest, context, { accountOverride });
364
+ if (normalizedResource === "offers" && action === "turn-off-gift") return offersSetGiftStatus(rest, context, { accountOverride, status: "inactive" });
365
+ if (normalizedResource === "offers" && action === "turn-on-gift") return offersSetGiftStatus(rest, context, { accountOverride, status: "active" });
366
+ if (normalizedResource === "offers" && action === "update-insight") return offersUpdateInsight(rest, context, { accountOverride });
367
+ if (normalizedResource === "offers" && action === "turn-off-insight") return offersSetInsightStatus(rest, context, { accountOverride, status: "inactive" });
368
+ if (normalizedResource === "offers" && action === "turn-on-insight") return offersSetInsightStatus(rest, context, { accountOverride, status: "active" });
354
369
  if (normalizedResource === "icps" && action === "list") return icpsList(rest, context, { accountOverride });
355
370
  if (normalizedResource === "icps" && action === "show") return icpsShow(rest, context, { accountOverride });
356
371
  if (normalizedResource === "icps" && action === "analytics") return analyticsIcps(rest, context, { accountOverride });
@@ -1841,6 +1856,128 @@ async function offersRemoveArtifact(args, context, { accountOverride } = {}) {
1841
1856
  writeLine(context.stdout, `Removed artifact ${display(artifactId)} from offer ${display(payload?.offer_id || offerId)}.`);
1842
1857
  }
1843
1858
 
1859
+ const OFFER_SHELF_STATUSES = { on: "active", off: "inactive", active: "active", inactive: "inactive" };
1860
+
1861
+ function offerShelfStatus(value, usage) {
1862
+ if (value === undefined) return undefined;
1863
+
1864
+ const status = OFFER_SHELF_STATUSES[String(value).trim().toLowerCase()];
1865
+ if (!status) throw new CommandError(`--status must be on or off.\n${usage}`);
1866
+ return status;
1867
+ }
1868
+
1869
+ async function offerGiftFile(path) {
1870
+ if (path === undefined) return undefined;
1871
+
1872
+ try {
1873
+ return { filename: basename(path), data: (await readFile(path)).toString("base64") };
1874
+ } catch (error) {
1875
+ throw new CommandError(`Cannot read ${path}: ${error.message}`);
1876
+ }
1877
+ }
1878
+
1879
+ async function offersAddGift(args, context, { accountOverride } = {}) {
1880
+ const { values, positionals } = parseCommandArgs(args, {
1881
+ ...jsonOptions(),
1882
+ title: { type: "string" },
1883
+ summary: { type: "string" },
1884
+ "send-url": { type: "string" },
1885
+ file: { type: "string" }
1886
+ });
1887
+ if (positionals.length !== 1 || !String(values.title || "").trim()) throw new CommandError(OFFERS_ADD_GIFT_USAGE);
1888
+
1889
+ const gift = compactObject({
1890
+ title: values.title,
1891
+ summary: values.summary,
1892
+ send_url: values["send-url"],
1893
+ file: await offerGiftFile(values.file)
1894
+ });
1895
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1896
+ const payload = await client.createOfferGift(accountId, positionals[0], { gift });
1897
+ if (values.json) return writeJson(context.stdout, payload);
1898
+
1899
+ writeLine(context.stdout, `Added gift ${display(payload?.gift?.title)} (${display(payload?.gift?.prefix_id)}) to offer ${display(payload?.offer_id || positionals[0])}.`);
1900
+ renderOfferGifts([payload?.gift], context);
1901
+ }
1902
+
1903
+ async function offersUpdateGift(args, context, { accountOverride } = {}) {
1904
+ const { values, positionals } = parseCommandArgs(args, {
1905
+ ...jsonOptions(),
1906
+ title: { type: "string" },
1907
+ summary: { type: "string" },
1908
+ "send-url": { type: "string" },
1909
+ file: { type: "string" },
1910
+ "remove-file": { type: "boolean" },
1911
+ status: { type: "string" }
1912
+ });
1913
+ if (values.file !== undefined && values["remove-file"]) throw new CommandError("Use --file or --remove-file, not both.");
1914
+ const gift = compactObject({
1915
+ title: values.title,
1916
+ summary: values.summary,
1917
+ send_url: values["send-url"],
1918
+ remove_file: values["remove-file"] ? true : undefined,
1919
+ status: offerShelfStatus(values.status, OFFERS_UPDATE_GIFT_USAGE)
1920
+ });
1921
+ if (positionals.length !== 2 || (Object.keys(gift).length === 0 && values.file === undefined)) throw new CommandError(OFFERS_UPDATE_GIFT_USAGE);
1922
+
1923
+ const file = await offerGiftFile(values.file);
1924
+ if (file) gift.file = file;
1925
+ const [offerId, giftId] = positionals;
1926
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1927
+ const payload = await client.updateOfferGift(accountId, offerId, giftId, { gift });
1928
+ if (values.json) return writeJson(context.stdout, payload);
1929
+
1930
+ writeLine(context.stdout, `Updated gift ${display(payload?.gift?.title)} (${display(payload?.gift?.prefix_id || giftId)}).`);
1931
+ renderOfferGifts([payload?.gift], context);
1932
+ }
1933
+
1934
+ async function offersSetGiftStatus(args, context, { accountOverride, status } = {}) {
1935
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
1936
+ if (positionals.length !== 2) throw new CommandError(status === "active" ? OFFERS_TURN_ON_GIFT_USAGE : OFFERS_TURN_OFF_GIFT_USAGE);
1937
+
1938
+ const [offerId, giftId] = positionals;
1939
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1940
+ const payload = await client.updateOfferGift(accountId, offerId, giftId, { gift: { status } });
1941
+ if (values.json) return writeJson(context.stdout, payload);
1942
+
1943
+ writeLine(context.stdout, `Turned ${status === "active" ? "on" : "off"} gift ${display(payload?.gift?.title)} (${display(payload?.gift?.prefix_id || giftId)}).`);
1944
+ }
1945
+
1946
+ async function offersUpdateInsight(args, context, { accountOverride } = {}) {
1947
+ const { values, positionals } = parseCommandArgs(args, {
1948
+ ...jsonOptions(),
1949
+ content: { type: "string" },
1950
+ "source-url": { type: "string" },
1951
+ status: { type: "string" }
1952
+ });
1953
+ const insight = compactObject({
1954
+ content: values.content,
1955
+ source_url: values["source-url"],
1956
+ status: offerShelfStatus(values.status, OFFERS_UPDATE_INSIGHT_USAGE)
1957
+ });
1958
+ if (positionals.length !== 2 || Object.keys(insight).length === 0) throw new CommandError(OFFERS_UPDATE_INSIGHT_USAGE);
1959
+
1960
+ const [offerId, insightId] = positionals;
1961
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1962
+ const payload = await client.updateOfferInsight(accountId, offerId, insightId, { insight });
1963
+ if (values.json) return writeJson(context.stdout, payload);
1964
+
1965
+ writeLine(context.stdout, `Updated insight ${display(payload?.insight?.id || insightId)}.`);
1966
+ renderOfferInsights([payload?.insight], context);
1967
+ }
1968
+
1969
+ async function offersSetInsightStatus(args, context, { accountOverride, status } = {}) {
1970
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
1971
+ if (positionals.length !== 2) throw new CommandError(status === "active" ? OFFERS_TURN_ON_INSIGHT_USAGE : OFFERS_TURN_OFF_INSIGHT_USAGE);
1972
+
1973
+ const [offerId, insightId] = positionals;
1974
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1975
+ const payload = await client.updateOfferInsight(accountId, offerId, insightId, { insight: { status } });
1976
+ if (values.json) return writeJson(context.stdout, payload);
1977
+
1978
+ writeLine(context.stdout, `Turned ${status === "active" ? "on" : "off"} insight ${display(payload?.insight?.id || insightId)}.`);
1979
+ }
1980
+
1844
1981
  async function icpsList(args, context, { accountOverride } = {}) {
1845
1982
  const { values, positionals } = parseCommandArgs(args, {
1846
1983
  ...jsonOptions(),
@@ -3234,14 +3371,15 @@ async function motionsAddProspects(args, context, { accountOverride } = {}) {
3234
3371
  async function motionsCreate(args, context, { accountOverride } = {}) {
3235
3372
  const { values, positionals } = parseCommandArgs(args, {
3236
3373
  ...jsonOptions(),
3237
- payload: { type: "string" }
3374
+ payload: { type: "string" },
3375
+ gift: { type: "string" }
3238
3376
  });
3239
3377
  if (positionals.length > 0 || !values.payload) {
3240
- throw new CommandError("Usage: audienti motions create --payload <file.json> [--json] [--account <acct_id>]");
3378
+ throw new CommandError(MOTIONS_CREATE_USAGE);
3241
3379
  }
3242
3380
 
3243
3381
  const { client, accountId } = await requireAccountContext(context, { accountOverride });
3244
- const payload = normalizeMotionCreatePayload(await readJsonPayload(values.payload));
3382
+ const payload = withMotionGift(normalizeMotionCreatePayload(await readJsonPayload(values.payload)), values.gift);
3245
3383
  const created = await client.createMotion(accountId, { motion: payload });
3246
3384
  if (values.json) return writeJson(context.stdout, created);
3247
3385
 
@@ -3249,6 +3387,22 @@ async function motionsCreate(args, context, { accountOverride } = {}) {
3249
3387
  renderMotion(created, context);
3250
3388
  }
3251
3389
 
3390
+ // --gift names a ready gift on the motion's offer. "none" clears the gift.
3391
+ function normalizeMotionGift(value) {
3392
+ if (value === undefined) return undefined;
3393
+
3394
+ const gift = String(value).trim();
3395
+ if (!gift) throw new CommandError("--gift needs a gift id or none.");
3396
+ return gift.toLowerCase() === "none" ? null : gift;
3397
+ }
3398
+
3399
+ function withMotionGift(payload, value) {
3400
+ const gift = normalizeMotionGift(value);
3401
+ if (gift === undefined || !payload || typeof payload !== "object" || Array.isArray(payload)) return payload;
3402
+
3403
+ return { ...payload, offer_gift_id: gift };
3404
+ }
3405
+
3252
3406
  function normalizeMotionCreatePayload(payload) {
3253
3407
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) return payload;
3254
3408
  rejectMotionPlanningMode(payload);
@@ -3408,7 +3562,8 @@ async function motionsUpdate(args, context, { accountOverride } = {}) {
3408
3562
  "own-post-engagement": { type: "string" },
3409
3563
  "start-date": { type: "string" },
3410
3564
  "end-date": { type: "string" },
3411
- "maximum-company-count": { type: "string" }
3565
+ "maximum-company-count": { type: "string" },
3566
+ gift: { type: "string" }
3412
3567
  });
3413
3568
  const hasUpdateField = values.payload || motionSimpleFieldsPresent(values);
3414
3569
  if (positionals.length !== 1 || !hasUpdateField) {
@@ -3455,7 +3610,8 @@ async function motionUpdatePayload(values) {
3455
3610
  approach: values.approach,
3456
3611
  starts_on: normalizeMotionDate(values["start-date"], "--start-date"),
3457
3612
  ends_on: normalizeMotionDate(values["end-date"], "--end-date"),
3458
- maximum_company_count: normalizeMotionMaximumCompanyCount(values["maximum-company-count"])
3613
+ maximum_company_count: normalizeMotionMaximumCompanyCount(values["maximum-company-count"]),
3614
+ offer_gift_id: normalizeMotionGift(values.gift)
3459
3615
  };
3460
3616
  for (const [key, value] of Object.entries(nullableSettings)) {
3461
3617
  if (value !== undefined) payload[key] = value;
@@ -3471,7 +3627,8 @@ function motionSimpleFieldsPresent(values) {
3471
3627
  values["own-post-engagement"] !== undefined ||
3472
3628
  values["start-date"] !== undefined ||
3473
3629
  values["end-date"] !== undefined ||
3474
- values["maximum-company-count"] !== undefined;
3630
+ values["maximum-company-count"] !== undefined ||
3631
+ values.gift !== undefined;
3475
3632
  }
3476
3633
 
3477
3634
  function rejectMotionPlanningMode(payload) {
@@ -7039,6 +7196,47 @@ function renderOffer(offer, context) {
7039
7196
  if (offer?.description) writeLine(context.stdout, `Description: ${offer.description}`);
7040
7197
  if (offer?.url) writeLine(context.stdout, `URL: ${offer.url}`);
7041
7198
  if (Array.isArray(offer?.artifacts) && offer.artifacts.length > 0) renderOfferArtifacts(offer.artifacts, context);
7199
+ if (Array.isArray(offer?.gifts)) renderOfferGifts(offer.gifts, context);
7200
+ if (Array.isArray(offer?.insights)) renderOfferInsights(offer.insights, context);
7201
+ }
7202
+
7203
+ const OFFER_GIFT_STATE_LABELS = { ready: "ready", needs_link: "needs a link", off: "off" };
7204
+
7205
+ function renderOfferGifts(gifts, context) {
7206
+ const rows = (Array.isArray(gifts) ? gifts : []).filter(Boolean);
7207
+ if (rows.length === 0) return writeLine(context.stdout, "No gifts.");
7208
+
7209
+ writeLine(context.stdout, "GIFT ID\tSTATE\tTITLE\tSEND LINK\tWHO IT HELPS");
7210
+ for (const gift of rows) {
7211
+ writeLine(
7212
+ context.stdout,
7213
+ [
7214
+ display(gift.prefix_id || gift.id),
7215
+ display(OFFER_GIFT_STATE_LABELS[gift.state] || gift.state),
7216
+ display(gift.title),
7217
+ display(gift.send_url || gift.file?.filename, "-"),
7218
+ display(gift.summary, "-")
7219
+ ].join("\t")
7220
+ );
7221
+ }
7222
+ }
7223
+
7224
+ function renderOfferInsights(insights, context) {
7225
+ const rows = (Array.isArray(insights) ? insights : []).filter(Boolean);
7226
+ if (rows.length === 0) return writeLine(context.stdout, "No insights.");
7227
+
7228
+ writeLine(context.stdout, "INSIGHT ID\tSTATUS\tINSIGHT\tSOURCE");
7229
+ for (const insight of rows) {
7230
+ writeLine(
7231
+ context.stdout,
7232
+ [
7233
+ display(insight.id),
7234
+ insight.status === "active" ? "on" : insight.status === "inactive" ? "off" : display(insight.status),
7235
+ display(insight.content),
7236
+ display(insight.source_url || insight.source_label, "-")
7237
+ ].join("\t")
7238
+ );
7239
+ }
7042
7240
  }
7043
7241
 
7044
7242
  function renderOfferArtifacts(artifacts, context) {
@@ -7295,6 +7493,7 @@ function renderMotion(motion, context) {
7295
7493
  writeLine(context.stdout, `Maximum companies: ${display(motion?.maximum_company_count, "not set")}`);
7296
7494
  renderExecutableConfiguration(motion?.executable_configuration, context);
7297
7495
  if (motion?.offer?.name) writeLine(context.stdout, `Offer: ${motion.offer.name} (${display(motion.offer.prefix_id)})`);
7496
+ if (motion?.offer_gift?.title) writeLine(context.stdout, `Gift: ${motion.offer_gift.title} (${display(motion.offer_gift.prefix_id)})`);
7298
7497
  if (motion?.icp?.name) writeLine(context.stdout, `ICP: ${motion.icp.name} (${display(motion.icp.prefix_id)})`);
7299
7498
  if (motion?.list?.name) writeLine(context.stdout, `List: ${motion.list.name} (${display(motion.list.prefix_id)})`);
7300
7499
  writeLine(context.stdout, `Own-post engagement: ${motion?.own_post_engagement ? "enabled" : "disabled"}`);
@@ -9921,6 +10120,7 @@ const HELP_TOPICS = new Map([
9921
10120
  " audienti offers regenerate-research <offr_id> [--guidance <text>]",
9922
10121
  " audienti offers update-writeup <offr_id> --description <text>",
9923
10122
  " audienti offers add-artifacts <offr_id> <file> [file...]",
10123
+ " audienti offers add-gift <offr_id> --title <text> [--send-url <url>]",
9924
10124
  " audienti icps list [--status <active|archived|all>] [--tag <tag>]",
9925
10125
  " audienti icps show <icp_id>",
9926
10126
  " audienti icps update <icp_id> [--tags <tag[,tag...]> | --payload <file.json>]",
@@ -10508,6 +10708,13 @@ const HELP_TOPICS = new Map([
10508
10708
  " audienti offers update-writeup <offr_id> --description <text> [--json]",
10509
10709
  " audienti offers add-artifacts <offr_id> <file> [file...] [--json]",
10510
10710
  " audienti offers remove-artifact <offr_id> <artifact_id> [--json]",
10711
+ " audienti offers add-gift <offr_id> --title <text> [--send-url <url> | --file <path>] [--json]",
10712
+ " audienti offers update-gift <offr_id> <gift_id> [--title <text>] [--send-url <url>] [--json]",
10713
+ " audienti offers turn-off-gift <offr_id> <gift_id> [--json]",
10714
+ " audienti offers turn-on-gift <offr_id> <gift_id> [--json]",
10715
+ " audienti offers update-insight <offr_id> <insight_id> [--content <text>] [--json]",
10716
+ " audienti offers turn-off-insight <offr_id> <insight_id> [--json]",
10717
+ " audienti offers turn-on-insight <offr_id> <insight_id> [--json]",
10511
10718
  "",
10512
10719
  "Status: implemented",
10513
10720
  "",
@@ -10568,6 +10775,11 @@ const HELP_TOPICS = new Map([
10568
10775
  "",
10569
10776
  "Status: implemented",
10570
10777
  "",
10778
+ "Purpose:",
10779
+ " Show one offer with its artifacts, gifts, and insights.",
10780
+ " A gift is a free, useful thing the offer already has. It is ready once it has a send link or a file; otherwise it needs a link.",
10781
+ " An insight is an exact fact or quote with its source.",
10782
+ "",
10571
10783
  "Input shape:",
10572
10784
  " offr_id: offr_ prefixed id or integer id",
10573
10785
  "",
@@ -11768,6 +11980,129 @@ const HELP_TOPICS = new Map([
11768
11980
  " DELETE /api/v1/accounts/:account_id/offers/:offer_id/artifacts/:id.json"
11769
11981
  ].join("\n")],
11770
11982
 
11983
+ ["offers add-gift", [
11984
+ "Usage:",
11985
+ ` ${OFFERS_ADD_GIFT_USAGE.slice("Usage: ".length)}`,
11986
+ "",
11987
+ "Status: implemented",
11988
+ "",
11989
+ "Purpose:",
11990
+ " Add a gift to an offer by hand. A gift is a free, useful thing you already have, such as a guide, a report, or a tool.",
11991
+ " The gift is ready once it has a send link or a file. Do not use a page that asks for an email as the send link.",
11992
+ "",
11993
+ "Input shape:",
11994
+ " offr_id: offr_ prefixed id or integer id",
11995
+ " title: string",
11996
+ " summary: who the gift helps | optional",
11997
+ " send-url: the file or page a prospect opens | optional",
11998
+ " file: local file path; sent as base64 | optional",
11999
+ "",
12000
+ "API:",
12001
+ " POST /api/v1/accounts/:account_id/offers/:offer_id/gifts.json"
12002
+ ].join("\n")],
12003
+
12004
+ ["offers update-gift", [
12005
+ "Usage:",
12006
+ ` ${OFFERS_UPDATE_GIFT_USAGE.slice("Usage: ".length)}`,
12007
+ "",
12008
+ "Status: implemented",
12009
+ "",
12010
+ "Purpose:",
12011
+ " Edit a gift, give it a send link or a file, or turn it off or on. Only the given fields change.",
12012
+ " A gift that is turned off or loses its send link is removed from any motion that carried it.",
12013
+ "",
12014
+ "Input shape:",
12015
+ " gift_id: ogft_ prefixed id or integer id from `audienti offers show <offr_id>`",
12016
+ " status: on | off | optional",
12017
+ " --remove-file: take the attached file off the gift; without a send link the gift then needs a link",
12018
+ "",
12019
+ "API:",
12020
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/gifts/:id.json"
12021
+ ].join("\n")],
12022
+
12023
+ ["offers turn-off-gift", [
12024
+ "Usage:",
12025
+ ` ${OFFERS_TURN_OFF_GIFT_USAGE.slice("Usage: ".length)}`,
12026
+ "",
12027
+ "Status: implemented",
12028
+ "",
12029
+ "Purpose:",
12030
+ " Turn off a gift. It stays on the offer, motions stop carrying it, and later site scans do not turn it back on.",
12031
+ "",
12032
+ "Input shape:",
12033
+ " gift_id: ogft_ prefixed id or integer id from `audienti offers show <offr_id>`",
12034
+ "",
12035
+ "API:",
12036
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/gifts/:id.json"
12037
+ ].join("\n")],
12038
+
12039
+ ["offers turn-on-gift", [
12040
+ "Usage:",
12041
+ ` ${OFFERS_TURN_ON_GIFT_USAGE.slice("Usage: ".length)}`,
12042
+ "",
12043
+ "Status: implemented",
12044
+ "",
12045
+ "Purpose:",
12046
+ " Turn a gift back on.",
12047
+ "",
12048
+ "Input shape:",
12049
+ " gift_id: ogft_ prefixed id or integer id from `audienti offers show <offr_id>`",
12050
+ "",
12051
+ "API:",
12052
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/gifts/:id.json"
12053
+ ].join("\n")],
12054
+
12055
+ ["offers update-insight", [
12056
+ "Usage:",
12057
+ ` ${OFFERS_UPDATE_INSIGHT_USAGE.slice("Usage: ".length)}`,
12058
+ "",
12059
+ "Status: implemented",
12060
+ "",
12061
+ "Purpose:",
12062
+ " Edit an insight or turn it off or on. An insight is an exact fact or quote with its source. Only the given fields change.",
12063
+ "",
12064
+ "Input shape:",
12065
+ " insight_id: integer id from `audienti offers show <offr_id>`",
12066
+ " content: string | optional",
12067
+ " source-url: URL | optional",
12068
+ " status: on | off | optional",
12069
+ "",
12070
+ "API:",
12071
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/insights/:id.json"
12072
+ ].join("\n")],
12073
+
12074
+ ["offers turn-off-insight", [
12075
+ "Usage:",
12076
+ ` ${OFFERS_TURN_OFF_INSIGHT_USAGE.slice("Usage: ".length)}`,
12077
+ "",
12078
+ "Status: implemented",
12079
+ "",
12080
+ "Purpose:",
12081
+ " Turn off an insight. It stays on the offer and later site scans do not turn it back on.",
12082
+ "",
12083
+ "Input shape:",
12084
+ " insight_id: integer id from `audienti offers show <offr_id>`",
12085
+ "",
12086
+ "API:",
12087
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/insights/:id.json"
12088
+ ].join("\n")],
12089
+
12090
+ ["offers turn-on-insight", [
12091
+ "Usage:",
12092
+ ` ${OFFERS_TURN_ON_INSIGHT_USAGE.slice("Usage: ".length)}`,
12093
+ "",
12094
+ "Status: implemented",
12095
+ "",
12096
+ "Purpose:",
12097
+ " Turn an insight back on.",
12098
+ "",
12099
+ "Input shape:",
12100
+ " insight_id: integer id from `audienti offers show <offr_id>`",
12101
+ "",
12102
+ "API:",
12103
+ " PATCH /api/v1/accounts/:account_id/offers/:offer_id/insights/:id.json"
12104
+ ].join("\n")],
12105
+
11771
12106
  ["tasks update", [
11772
12107
  "Usage:",
11773
12108
  ` ${TASKS_UPDATE_USAGE.slice("Usage: ".length)}`,
@@ -12325,7 +12660,7 @@ const HELP_TOPICS = new Map([
12325
12660
 
12326
12661
  ["motions create", [
12327
12662
  "Usage:",
12328
- " audienti motions create --payload <file.json> [--json] [--account <acct_id>]",
12663
+ ` ${MOTIONS_CREATE_USAGE.slice("Usage: ".length)}`,
12329
12664
  "",
12330
12665
  "Status: implemented",
12331
12666
  "",
@@ -12339,6 +12674,7 @@ const HELP_TOPICS = new Map([
12339
12674
  " kind: outbound | inbound | lopa | transition",
12340
12675
  " status: draft | active | paused | archived",
12341
12676
  " offer_id: offr_ prefix id",
12677
+ " offer_gift_id: ogft_ prefix id | null | optional; a ready gift on this offer. --gift <gift_id|none> sets the same field",
12342
12678
  " principal_account_user_id: integer | me | optional",
12343
12679
  " icp_id: icpp_ prefix id | optional",
12344
12680
  " list_id: list_ prefix id | optional",
@@ -12419,6 +12755,7 @@ const HELP_TOPICS = new Map([
12419
12755
  " start-date: YYYY-MM-DD | none | optional",
12420
12756
  " end-date: YYYY-MM-DD | none | optional",
12421
12757
  " maximum-company-count: positive integer | none | optional",
12758
+ " gift: ogft_ prefix id | none | optional; a ready gift on the motion's own offer (offer_gift_id in payload mode)",
12422
12759
  " payload: file.json | optional full or partial motion object using the account API shape",
12423
12760
  "",
12424
12761
  "Behavior:",