@audienti/cli 0.1.59 → 0.1.61

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.61] - 2026-09-08
8
+
9
+ ### Added
10
+
11
+ - Add owner-scoped `network-ops queue`, `accept`, and `decline` commands for pending inbound LinkedIn connection requests, with `reject` as a decline alias and explicit queued-versus-provider-confirmed output.
12
+
13
+ ### Fixed
14
+
15
+ - Preserve exact invitation-to-message binding in Network Ops output instead of assigning unrelated neighboring payload text.
16
+
17
+ ## [0.1.60] - 2026-09-08
18
+
19
+ ### Changed
20
+
21
+ - Motion responses no longer include `post_accept_actions_enabled`; a Motion with an Approach always plans and executes post-accept outreach, so the per-Motion enabled/disabled line is gone from `motions show`.
22
+
7
23
  ## [0.1.59] - 2026-09-06
8
24
 
9
25
  ### Changed
package/README.md CHANGED
@@ -218,7 +218,8 @@ audienti operator next --plan
218
218
  audienti operator next --done --note "Connection request sent."
219
219
  ```
220
220
 
221
- `operator queue`, `operator failed-drafts`, and `inbox-ops queue` print a
221
+ `operator queue`, `operator failed-drafts`, `network-ops queue`, and
222
+ `inbox-ops queue` print a
222
223
  continuation command when more rows remain. Read-only `operator next` (including
223
224
  `--plan`) also prints one when its page has no focal move but more rows remain;
224
225
  when a move is present, inspect or act on it and rerun `operator next`.
@@ -229,6 +230,21 @@ with an offset. If the scan limit is reached, narrow the filters; an incomplete
229
230
  scan does not mean the queue is empty. JSON output preserves the API response.
230
231
  Pagination flags are not accepted when recording outcomes or requeueing drafts.
231
232
 
233
+ Network Ops has its own owner-scoped CLI surface for pending inbound LinkedIn
234
+ connection requests. It shows the exact invitation-bound message when one was
235
+ captured and queues the same canonical provider actions as the product UI:
236
+
237
+ ```bash
238
+ audienti network-ops queue [--page <n>] [--offset <n>|--cursor <token>]
239
+ audienti network-ops accept <row_id>
240
+ audienti network-ops decline <row_id>
241
+ ```
242
+
243
+ `reject` is accepted as an alias for `decline`. An accepted API response means
244
+ the provider action was queued; it is not confirmation that LinkedIn completed
245
+ the action. The same queue can be read with
246
+ `audienti operator queue --opportunity-kind network`.
247
+
232
248
  Inbox Ops has its own owner-scoped CLI surface. Queue rows expose the stable row
233
249
  id used by the row-based rule command. Rules can also be set or removed directly
234
250
  by sender or domain; the server normalizes and validates every supplied key:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: audienti
3
- description: Use when the user wants to operate Audienti through the production CLI or app-hosted MCP endpoint, including account selection, plays, prospect imports, lists and routing rules, message previews, analytics, or supported operator outcomes.
3
+ description: Use when the user wants to operate Audienti through the production CLI or app-hosted MCP endpoint, including account selection, plays, prospect imports, lists and routing rules, message previews, analytics, Inbox Ops, Network Ops, or supported operator outcomes.
4
4
  ---
5
5
 
6
6
  # Audienti CLI and MCP
@@ -136,6 +136,9 @@ audienti motions activate <motn_id> --json
136
136
  audienti motions delete <motn_id> --confirm yes --json
137
137
  audienti operator next --json
138
138
  audienti operator next --plan
139
+ audienti network-ops queue --json
140
+ audienti network-ops accept <row_id> --account <acct_id> --json
141
+ audienti network-ops decline <row_id> --account <acct_id> --json
139
142
  audienti inbox-ops queue --json
140
143
  audienti inbox-ops filters --json
141
144
  audienti inbox-ops rule <row_id> --scope <sender|domain> --disposition <allow|filter> --json
package/src/api-client.js CHANGED
@@ -657,6 +657,12 @@ export class AudientiClient {
657
657
  return this.requestJson(accountPath(accountId, ["operator"], query));
658
658
  }
659
659
 
660
+ networkOpsAction(accountId, rowId, action) {
661
+ return this.requestJson(accountPath(accountId, ["network_ops", rowId, action]), {
662
+ method: "POST"
663
+ });
664
+ }
665
+
660
666
  inboxOpsFilters(accountId) {
661
667
  return this.requestJson(accountPath(accountId, ["inbox_ops", "filters"]));
662
668
  }
package/src/cli.js CHANGED
@@ -66,6 +66,9 @@ const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --f
66
66
  const OPERATOR_FAILED_DRAFTS_USAGE = "Usage: audienti operator failed-drafts [--json] [filters] [--account <acct_id>]";
67
67
  const OPERATOR_FAILED_DRAFTS_REQUEUE_USAGE = "Usage: audienti operator failed-drafts requeue (--all | <row_id> [row_id...]) [--limit <n>] [--json] [filters] [--account <acct_id>]";
68
68
  const INBOX_OPS_QUEUE_USAGE = "Usage: audienti inbox-ops queue [--page <n>] [--offset <n>|--cursor <token>] [--json] [--account <acct_id>]";
69
+ const NETWORK_OPS_QUEUE_USAGE = "Usage: audienti network-ops queue [--page <n>] [--offset <n>|--cursor <token>] [--json] [--account <acct_id>]";
70
+ const NETWORK_OPS_ACCEPT_USAGE = "Usage: audienti network-ops accept <row_id> [--json] [--account <acct_id>]";
71
+ const NETWORK_OPS_DECLINE_USAGE = "Usage: audienti network-ops decline <row_id> [--json] [--account <acct_id>]";
69
72
  const OPERATOR_PAGINATION_HELP = [
70
73
  "Read pagination:",
71
74
  " --page <n> Positive page number",
@@ -80,6 +83,7 @@ const INBOX_OPS_RULE_USAGE = "Usage: audienti inbox-ops rule <row_id> --scope <s
80
83
  const INBOX_OPS_RULE_SET_USAGE = "Usage: audienti inbox-ops rule set --scope <sender|domain> --key <email|domain> --disposition <allow|filter> [--json] [--account <acct_id>]";
81
84
  const INBOX_OPS_RULE_REMOVE_USAGE = "Usage: audienti inbox-ops rule remove --scope <sender|domain> --key <email|domain> [--json] [--account <acct_id>]";
82
85
  const INBOX_OPS_ROW_ID_PATTERN = /^inbox_ops_message_[1-9]\d*$/;
86
+ const NETWORK_OPS_ROW_ID_PATTERN = /^network_ops_event_[1-9]\d*$/;
83
87
  const DNC_ADD_USAGE = "Usage: audienti dnc add <email|citation_id|profile_url> [--json] [--account <acct_id>]";
84
88
  const DNC_IMPORT_USAGE = "Usage: audienti dnc import --file <txt|csv> [--json] [--account <acct_id>]";
85
89
  const DNC_REMOVE_USAGE = "Usage: audienti dnc remove <dnc_entry_id> [--json] [--account <acct_id>]";
@@ -346,6 +350,10 @@ async function dispatch(argv, context) {
346
350
  if (normalizedResource === "operator" && action === "next") return operatorNext(rest, context, { accountOverride });
347
351
  if (normalizedResource === "operator" && action === "outcome") return operatorOutcome(rest, context, { accountOverride });
348
352
  if (normalizedResource === "operator" && action === "answer") return operatorAnswer(rest, context, { accountOverride });
353
+ if (normalizedResource === "network-ops" && action === "queue") return networkOpsQueue(rest, context, { accountOverride });
354
+ if (normalizedResource === "network-ops" && ["accept", "decline", "reject"].includes(action)) {
355
+ return networkOpsAction(action, rest, context, { accountOverride });
356
+ }
349
357
  if (normalizedResource === "inbox-ops" && action === "queue") return inboxOpsQueue(rest, context, { accountOverride });
350
358
  if (normalizedResource === "inbox-ops" && action === "filters") return inboxOpsFilters(rest, context, { accountOverride });
351
359
  if (normalizedResource === "inbox-ops" && action === "rule") return inboxOpsRule(rest, context, { accountOverride });
@@ -3275,6 +3283,39 @@ async function inboxOpsQueue(args, context, { accountOverride } = {}) {
3275
3283
  renderOperatorRead(payload, context, { command: "inbox-ops queue", accountId, query }, () => renderInboxOpsQueue(payload, context));
3276
3284
  }
3277
3285
 
3286
+ async function networkOpsQueue(args, context, { accountOverride } = {}) {
3287
+ const { values, positionals } = parseCommandArgs(args, {
3288
+ ...jsonOptions(),
3289
+ ...operatorPaginationOptions()
3290
+ });
3291
+ if (positionals.length > 0) throw new CommandError(NETWORK_OPS_QUEUE_USAGE);
3292
+
3293
+ const query = { opportunity_kind: "network", ...operatorPaginationQuery(values) };
3294
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3295
+ const payload = await client.operatorQueue(accountId, query);
3296
+ if (values.json) return writeJson(context.stdout, payload);
3297
+
3298
+ renderOperatorRead(payload, context, { command: "network-ops queue", accountId, query }, () => renderNetworkOpsQueue(payload, context, { accountId }));
3299
+ }
3300
+
3301
+ async function networkOpsAction(action, args, context, { accountOverride } = {}) {
3302
+ const { values, positionals } = parseCommandArgs(args, jsonOptions());
3303
+ const canonicalAction = action === "reject" ? "decline" : action;
3304
+ const usage = canonicalAction === "accept" ? NETWORK_OPS_ACCEPT_USAGE : NETWORK_OPS_DECLINE_USAGE;
3305
+ if (positionals.length !== 1) throw new CommandError(usage);
3306
+
3307
+ const rowId = positionals[0];
3308
+ if (!NETWORK_OPS_ROW_ID_PATTERN.test(rowId)) {
3309
+ throw new CommandError("<row_id> must match network_ops_event_<positive integer>.");
3310
+ }
3311
+
3312
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3313
+ const payload = await client.networkOpsAction(accountId, rowId, canonicalAction);
3314
+ if (values.json) return writeJson(context.stdout, payload);
3315
+
3316
+ renderNetworkOpsAction(payload, context);
3317
+ }
3318
+
3278
3319
  async function inboxOpsFilters(args, context, { accountOverride } = {}) {
3279
3320
  const { values, positionals } = parseCommandArgs(args, jsonOptions());
3280
3321
  if (positionals.length > 0) throw new CommandError(INBOX_OPS_FILTERS_USAGE);
@@ -5414,9 +5455,6 @@ function renderMotion(motion, context) {
5414
5455
  writeLine(context.stdout, `Status: ${display(motion?.status)}`);
5415
5456
  writeLine(context.stdout, `Kind: ${display(motion?.kind)}`);
5416
5457
  writeLine(context.stdout, `Approach: ${display(motion?.approach, "not set")}`);
5417
- if (typeof motion?.post_accept_actions_enabled === "boolean") {
5418
- writeLine(context.stdout, `Post-accept actions: ${motion.post_accept_actions_enabled ? "enabled" : "disabled"}`);
5419
- }
5420
5458
  writeLine(context.stdout, `Start date: ${display(motion?.starts_on, "not set")}`);
5421
5459
  writeLine(context.stdout, `End date: ${display(motion?.ends_on, "not set")}`);
5422
5460
  writeLine(context.stdout, `Maximum companies: ${display(motion?.maximum_company_count, "not set")}`);
@@ -6408,7 +6446,7 @@ function operatorContinuationCommand(payload, { command, accountId, query, plan
6408
6446
  }
6409
6447
 
6410
6448
  function operatorContinuationFilters(command, query, resolvedFilters = {}) {
6411
- if (command === "inbox-ops queue") return [];
6449
+ if (["inbox-ops queue", "network-ops queue"].includes(command)) return [];
6412
6450
 
6413
6451
  const filters = { ...resolvedFilters, ...query };
6414
6452
  const flags = {
@@ -6451,6 +6489,37 @@ function renderInboxOpsQueue(payload, context) {
6451
6489
  ]));
6452
6490
  }
6453
6491
 
6492
+ function renderNetworkOpsQueue(payload, context, { accountId }) {
6493
+ const decisionQueue = Array.isArray(payload?.decision_queue) ? payload.decision_queue : [];
6494
+ const rows = decisionQueue.length > 0 ? decisionQueue : [payload?.next_move].filter(Boolean);
6495
+ if (rows.length === 0) return writeLine(context.stdout, "No Network Ops rows found.");
6496
+
6497
+ writeAlignedTable(context, ["ROW ID", "PERSON", "MESSAGE", "STATE"], rows.map((row) => [
6498
+ display(row?.id),
6499
+ operatorSubjectLabel(row),
6500
+ row?.network_ops?.note || "-",
6501
+ display(row?.network_ops?.state)
6502
+ ]));
6503
+
6504
+ for (const row of rows) {
6505
+ const accountOption = ` --account ${operatorCommandArgument(accountId)}`;
6506
+ writeLine(context.stdout, "");
6507
+ writeLine(context.stdout, `Accept: audienti network-ops accept ${row.id}${accountOption}`);
6508
+ writeLine(context.stdout, `Decline: audienti network-ops decline ${row.id}${accountOption}`);
6509
+ }
6510
+ }
6511
+
6512
+ function renderNetworkOpsAction(payload, context) {
6513
+ const actionKey = String(payload?.action?.key || "");
6514
+ const label = actionKey.endsWith("_decline") ? "Decline" : "Acceptance";
6515
+ const person = payload?.request?.display_name || payload?.request?.id || payload?.row_id;
6516
+ writeLine(context.stdout, `${label} queued for ${display(person)} (${display(payload?.row_id)}).`);
6517
+ if (payload?.action?.prefix_id) {
6518
+ writeLine(context.stdout, `Action: ${payload.action.prefix_id} (${display(payload.action.state)})`);
6519
+ }
6520
+ writeLine(context.stdout, "Queued means provider execution was requested; it is not confirmation that LinkedIn completed the action.");
6521
+ }
6522
+
6454
6523
  function renderInboxOpsFilters(payload, context) {
6455
6524
  const owner = payload?.owner || {};
6456
6525
  const filters = payload?.email_filters || {};
@@ -7906,6 +7975,11 @@ const HELP_TOPICS = new Map([
7906
7975
  " audienti inbox-ops queue",
7907
7976
  " audienti inbox-ops filters",
7908
7977
  " audienti inbox-ops rule <row_id> --scope <sender|domain> --disposition <allow|filter>",
7978
+ "",
7979
+ " Network Ops",
7980
+ " audienti network-ops queue",
7981
+ " audienti network-ops accept <row_id>",
7982
+ " audienti network-ops decline <row_id>",
7909
7983
  "",
7910
7984
  " Analytics",
7911
7985
  " audienti analytics motions",
@@ -10809,6 +10883,66 @@ const HELP_TOPICS = new Map([
10809
10883
  " key: PATCH|DELETE /api/v1/accounts/:account_id/inbox_ops/rules.json"
10810
10884
  ].join("\n")],
10811
10885
 
10886
+ ["network-ops", [
10887
+ "Usage:",
10888
+ ` ${NETWORK_OPS_QUEUE_USAGE.slice("Usage: ".length)}`,
10889
+ ` ${NETWORK_OPS_ACCEPT_USAGE.slice("Usage: ".length)}`,
10890
+ ` ${NETWORK_OPS_DECLINE_USAGE.slice("Usage: ".length)}`,
10891
+ " audienti network-ops reject <row_id> [--json] [--account <acct_id>]",
10892
+ "",
10893
+ "Status: implemented",
10894
+ "",
10895
+ "Purpose:",
10896
+ " Inspect the authenticated owner's private inbound LinkedIn connection requests and queue accept or decline provider actions.",
10897
+ " `reject` is accepted as an alias for `decline`.",
10898
+ "",
10899
+ "Safety:",
10900
+ " Rows always resolve through the current owner-private Network Ops scope. Arbitrary event ids and another user's requests fail closed.",
10901
+ " A successful response means the provider action was queued, not that LinkedIn has confirmed it.",
10902
+ "",
10903
+ "API:",
10904
+ " queue: GET /api/v1/accounts/:account_id/operator.json?opportunity_kind=network",
10905
+ " action: POST /api/v1/accounts/:account_id/network_ops/:row_id/:accept_or_decline.json"
10906
+ ].join("\n")],
10907
+
10908
+ ["network-ops queue", [
10909
+ NETWORK_OPS_QUEUE_USAGE,
10910
+ "",
10911
+ "Status: implemented",
10912
+ "",
10913
+ ...OPERATOR_PAGINATION_HELP,
10914
+ "Purpose:",
10915
+ " List one page of the authenticated owner's pending inbound LinkedIn connection requests, including the exact invitation-bound message when available.",
10916
+ " The general equivalent is `audienti operator queue --opportunity-kind network`.",
10917
+ "",
10918
+ "API:",
10919
+ " GET /api/v1/accounts/:account_id/operator.json?opportunity_kind=network"
10920
+ ].join("\n")],
10921
+
10922
+ ["network-ops accept", [
10923
+ NETWORK_OPS_ACCEPT_USAGE,
10924
+ "",
10925
+ "Status: implemented",
10926
+ "",
10927
+ "Purpose:",
10928
+ " Queue the canonical LinkedIn accept action for one authorized pending Network Ops row.",
10929
+ "",
10930
+ "API:",
10931
+ " POST /api/v1/accounts/:account_id/network_ops/:row_id/accept.json"
10932
+ ].join("\n")],
10933
+
10934
+ ["network-ops decline", [
10935
+ NETWORK_OPS_DECLINE_USAGE,
10936
+ "",
10937
+ "Status: implemented",
10938
+ "",
10939
+ "Purpose:",
10940
+ " Queue the canonical LinkedIn decline action for one authorized pending Network Ops row. `reject` is an alias.",
10941
+ "",
10942
+ "API:",
10943
+ " POST /api/v1/accounts/:account_id/network_ops/:row_id/decline.json"
10944
+ ].join("\n")],
10945
+
10812
10946
  ["operator", [
10813
10947
  "Usage:",
10814
10948
  " audienti operator next [--json|--plan|--done|--skip|--fail|--return]",
@@ -10825,7 +10959,7 @@ const HELP_TOPICS = new Map([
10825
10959
  " --motion <motn_id>",
10826
10960
  " --list <list_id>",
10827
10961
  " --stage <stage>",
10828
- " --opportunity-kind prospect|visibility|inbox",
10962
+ " --opportunity-kind prospect|visibility|inbox|network|content",
10829
10963
  " --writing-status ready|drafting|draft_failed"
10830
10964
  ].join("\n")],
10831
10965
 
@@ -11360,6 +11494,9 @@ const HELP_TOPICS = new Map([
11360
11494
  " audienti operator failed-drafts",
11361
11495
  " audienti operator failed-drafts requeue <row_id>",
11362
11496
  " audienti operator outcome <row_id> --payload <file.json>",
11497
+ " audienti network-ops queue",
11498
+ " audienti network-ops accept <row_id>",
11499
+ " audienti network-ops decline <row_id>",
11363
11500
  " audienti inbox-ops queue",
11364
11501
  " audienti inbox-ops filters",
11365
11502
  " audienti inbox-ops rule <row_id> --scope sender --disposition filter",