@audienti/cli 0.1.116 → 0.1.122

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,42 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.122] - 2026-10-19
8
+
9
+ ### Added
10
+
11
+ - Create child accounts with `audienti accounts create --name <name> --parent <name-or-id> [--json]` and the shared API. Parent admins receive access; ambiguous parent names and duplicate child names fail clearly (#2943).
12
+
13
+ ## [0.1.121] - 2026-10-19
14
+
15
+ ### Added
16
+
17
+ - Add `motions runs` to read account-scoped, paginated discovery history with run purposes, current saved-person outcomes, and blocked-search reasons.
18
+
19
+ ## [0.1.120] - 2026-10-19
20
+
21
+ ### Changed
22
+
23
+ - Extend the existing `social-cookies activity` command with `--repair-task-id` and `--repair-id` for exact read-only browser repair details from the account-scoped activity API.
24
+
25
+ ## [0.1.119] - 2026-10-18
26
+
27
+ ### Changed
28
+
29
+ - Extend the operator conversation-reader request and status API contract with bounded retries that retain failure evidence. This release adds no new CLI command.
30
+
31
+ ## [0.1.118] - 2026-10-16
32
+
33
+ ### Changed
34
+
35
+ - Update the operator conversation-reader request and task-status API contract. This release adds no new CLI command.
36
+
37
+ ## [0.1.117] - 2026-10-12
38
+
39
+ ### Changed
40
+
41
+ - Quick Start API `linkedin_sign_in` can now return `computer_needed` when LinkedIn requires the person to finish sign-in in their Computer. The `setup_state` read accepts an optional `computer_handoff_cookie_id`; it is used only when it matches the selected owner's current LinkedIn cookie in `approval_needed` state. The CLI does not start a Computer or perform the handoff.
42
+
7
43
  ## [0.1.116] - 2026-10-12
8
44
 
9
45
  ### Changed
package/README.md CHANGED
@@ -78,6 +78,7 @@ Authenticate through the browser, then configure the default account context:
78
78
  ```bash
79
79
  audienti auth login
80
80
  audienti accounts list --json
81
+ audienti accounts create --name Doppel --parent OMALab --json
81
82
  audienti accounts select <acct_id>
82
83
  audienti users list
83
84
  audienti users select <account_user_id|email|name|me>
@@ -232,6 +233,7 @@ audienti analytics motions --json
232
233
  audienti analytics icps --json
233
234
  audienti motions analytics <motn_id>
234
235
  audienti motions run-discovery <motn_id>
236
+ audienti motions runs <motn_id> [--cursor <id>] [--limit <1-10>] [--json]
235
237
  audienti motions quick-start --url https://example.com --wait --confirm
236
238
  audienti motions abm-companies <motn_id> add --file abm-domains.txt
237
239
  audienti motions abm-companies <motn_id> list
@@ -878,3 +880,5 @@ Copyright (c) 2026 OMALab, Inc. All rights reserved. See [LICENSE](LICENSE).
878
880
 
879
881
  Batch import accepts up to 50 rows per API request. Split larger files before importing. Row destination IDs or new names override batch defaults; failed rows stay visible in the response.
880
882
  Bulk destinations: `audienti prospects set-destination <prsp_id> --type list --destination <list_id>` adds by default. Use `--name "New list"` to create a list, `--type experiment --name "Existing relationships"` to create a transition without setup, or `--mode move` for explicit reassignment. Add preserves existing memberships; experiment Add skips people assigned elsewhere.
883
+
884
+ Create a child workspace with `audienti accounts create --name <name> --parent <name-or-id> [--json]`. The parent can be a visible name, unique name fragment, numeric ID, or prefixed ID. You must administer a root team account. All parent admins receive access to the child; ordinary members do not. Ambiguous names show matching IDs and stop. A duplicate child name under the same parent fails clearly. The response includes the new account ID. Creation keeps your selected account unchanged: use `audienti accounts select <new_acct_id>` or `--account <new_acct_id>` before creating a motion there.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.116",
3
+ "version": "0.1.122",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -111,6 +111,7 @@ context:
111
111
  ```bash
112
112
  audienti auth login
113
113
  audienti accounts list --json
114
+ audienti accounts create --name Doppel --parent OMALab --json
114
115
  audienti accounts select <acct_id>
115
116
  audienti users select me
116
117
  ```
@@ -332,3 +333,5 @@ completed report later.
332
333
  - `tools email-find`, `linkedin-enrich`, `signals-find` and `write` return a run id immediately. Pass `--wait --json` to get results in one call, or poll `tools runs show <trun_id>` and read `tools runs results <trun_id>`. Nothing is sent and no prospects or experiments are created.
333
334
  - Pass `--request-key <key>` when retrying a submission; the same key and input return the same run.
334
335
  - `audienti network list|export` reads only the requester's own connected account's saved network. A 404 means the requester is not that account's owner. Coverage `unsupported_capture` or `not_yet_observed` is not zero.
336
+
337
+ Create a child workspace with `audienti accounts create --name <name> --parent <name-or-id> [--json]`. The parent can be a visible name, unique name fragment, numeric ID, or prefixed ID. You must administer a root team account. All parent admins receive access to the child; ordinary members do not. Ambiguous names show matching IDs and stop. A duplicate child name under the same parent fails clearly. The response includes the new account ID. Creation keeps your selected account unchanged: use `audienti accounts select <new_acct_id>` or `--account <new_acct_id>` before creating a motion there.
package/src/api-client.js CHANGED
@@ -40,6 +40,10 @@ export class AudientiClient {
40
40
  return this.requestJson("/api/v1/accounts.json");
41
41
  }
42
42
 
43
+ createAccount(body) {
44
+ return this.requestJson("/api/v1/accounts.json", { method: "POST", body });
45
+ }
46
+
43
47
  account(accountId) {
44
48
  return this.requestJson(accountPath(accountId, []));
45
49
  }
@@ -813,6 +817,10 @@ export class AudientiClient {
813
817
  });
814
818
  }
815
819
 
820
+ motionRuns(accountId, motionId, params = {}) {
821
+ return this.requestJson(accountPath(accountId, ["motions", motionId, "runs"], params));
822
+ }
823
+
816
824
  motionStatus(accountId, motionId) {
817
825
  return this.requestJson(accountPath(accountId, ["motions", motionId, "status"]));
818
826
  }
package/src/cli.js CHANGED
@@ -149,6 +149,7 @@ const PAYMENT_SHOW_USAGE = "Usage: audienti payment show [--json] [--account <ac
149
149
  const PAYMENT_CODE_USAGE = "Usage: audienti payment code <signup_code> [--json] [--account <acct_id>]";
150
150
  const BRAND_PROFILE_SHOW_USAGE = "Usage: audienti brand-profile show [--json] [--account <acct_id>]";
151
151
  const BRAND_PROFILE_UPDATE_USAGE = "Usage: audienti brand-profile update [--voice <text>] [--style <text>] [--do-not-use <text>] [--json] [--account <acct_id>]";
152
+ const ACCOUNTS_CREATE_USAGE = "Usage: audienti accounts create --name <text> --parent <name-or-id> [--json]";
152
153
  const ACCOUNTS_SHOW_USAGE = "Usage: audienti accounts show [<acct_id>] [--json] [--account <acct_id>]";
153
154
  const LINKEDIN_LOOKUPS_USAGE = "Usage: audienti linkedin-lookups <company-sizes|company-types|functions|industries|job-titles|locations|seniorities> [--query <text>] [--icp <icp_id>] [--json] [--account <acct_id>]";
154
155
  const LINKEDIN_LOOKUP_KINDS = new Map([
@@ -368,6 +369,7 @@ async function dispatch(argv, context) {
368
369
  if (normalizedResource === "config" && action === "list") return configList(rest, context);
369
370
  if (normalizedResource === "update" && action === "check") return updateCheck(rest, context);
370
371
  if (normalizedResource === "accounts" && action === "list") return accountsList(rest, context, { accountOverride });
372
+ if (normalizedResource === "accounts" && action === "create") return accountsCreate(rest, context);
371
373
  if (normalizedResource === "accounts" && action === "select") return accountsSelect(rest, context);
372
374
  if (normalizedResource === "accounts" && action === "show") return accountsShow(rest, context, { accountOverride });
373
375
  if (normalizedResource === "linkedin-lookups") return linkedinLookups(action, rest, context, { accountOverride });
@@ -450,6 +452,7 @@ async function dispatch(argv, context) {
450
452
  if (normalizedResource === "motions" && action === "list") return motionsList(rest, context, { accountOverride });
451
453
  if (normalizedResource === "motions" && action === "show") return motionsShow(rest, context, { accountOverride });
452
454
  if (normalizedResource === "motions" && action === "signals") return motionsSignals(rest, context, { accountOverride });
455
+ if (normalizedResource === "motions" && action === "runs") return motionsRuns(rest, context, { accountOverride });
453
456
  if (normalizedResource === "motions" && action === "status") return motionsStatus(rest, context, { accountOverride });
454
457
  if (normalizedResource === "motions" && ["abm-companies", "company-filters"].includes(action)) return motionsAbmCompanies(rest, context, { accountOverride });
455
458
  if (normalizedResource === "motions" && action === "profile-signals") return motionsProfileSignals(rest, context, { accountOverride });
@@ -1733,6 +1736,27 @@ async function accountsList(args, context, { accountOverride } = {}) {
1733
1736
  }
1734
1737
  }
1735
1738
 
1739
+ async function accountsCreate(args, context) {
1740
+ const { values, positionals } = parseCommandArgs(args, {
1741
+ ...jsonOptions(),
1742
+ name: { type: "string" },
1743
+ parent: { type: "string" }
1744
+ });
1745
+ if (positionals.length || !values.name?.trim() || !values.parent?.trim()) {
1746
+ throw new CommandError(ACCOUNTS_CREATE_USAGE);
1747
+ }
1748
+
1749
+ const config = await requireAuthenticatedConfig(context);
1750
+ const client = clientFromConfig(config, context);
1751
+ const parent = resolveAccountSelection(await client.accounts(), values.parent);
1752
+ if (!parent) throw new CommandError(`Parent account "${values.parent}" does not exist or is not accessible.`);
1753
+ if (!parent.prefix_id) throw new CommandError("Account payload is missing prefix_id.");
1754
+
1755
+ const account = await client.createAccount({ account: { name: values.name, parent_account_id: parent.prefix_id } });
1756
+ if (values.json) return writeJson(context.stdout, account);
1757
+ writeLine(context.stdout, `Created account: ${account.name} (${account.prefix_id})`);
1758
+ }
1759
+
1736
1760
  async function accountsShow(args, context, { accountOverride } = {}) {
1737
1761
  const { values, positionals } = parseCommandArgs(args, jsonOptions());
1738
1762
  if (positionals.length > 1) throw new CommandError(ACCOUNTS_SHOW_USAGE);
@@ -1822,12 +1846,14 @@ function resolveAccountSelection(accounts, term) {
1822
1846
 
1823
1847
  const exactPrefix = accounts.find((candidate) => candidate.prefix_id === requested);
1824
1848
  if (exactPrefix) return exactPrefix;
1849
+ const exactId = accounts.find((candidate) => String(candidate.id) === requested);
1850
+ if (exactId) return exactId;
1825
1851
 
1826
1852
  const normalizedRequested = requested.toLowerCase();
1827
- const exactName = accounts.find((candidate) => String(candidate.name || "").toLowerCase() === normalizedRequested);
1828
- if (exactName) return exactName;
1853
+ const exactNames = accounts.filter((candidate) => String(candidate.name || "").toLowerCase() === normalizedRequested);
1854
+ if (exactNames.length === 1) return exactNames[0];
1829
1855
 
1830
- const matches = accounts.filter((candidate) => {
1856
+ const matches = exactNames.length > 1 ? exactNames : accounts.filter((candidate) => {
1831
1857
  const prefixId = String(candidate.prefix_id || "").toLowerCase();
1832
1858
  const name = String(candidate.name || "").toLowerCase();
1833
1859
  return prefixId.includes(normalizedRequested) || name.includes(normalizedRequested);
@@ -3602,6 +3628,25 @@ async function motionsSignals(args, context, { accountOverride } = {}) {
3602
3628
  renderMotionDiscoverySignals(payload, context);
3603
3629
  }
3604
3630
 
3631
+ async function motionsRuns(args, context, { accountOverride } = {}) {
3632
+ const { values, positionals } = parseCommandArgs(args, {
3633
+ ...jsonOptions(), cursor: { type: "string" }, limit: { type: "string" }
3634
+ });
3635
+ if (positionals.length !== 1) throw new CommandError("Usage: audienti motions runs <motn_id> [--cursor <id>] [--limit <1-10>] [--json] [--account <acct_id>]");
3636
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
3637
+ const payload = await client.motionRuns(accountId, positionals[0], compactObject({
3638
+ cursor: normalizeOptionalPositiveInteger(values.cursor, "--cursor"),
3639
+ limit: normalizeOptionalPositiveInteger(values.limit, "--limit")
3640
+ }));
3641
+ if (values.json) return writeJson(context.stdout, payload);
3642
+ for (const row of payload.runs || []) {
3643
+ context.stdout.write(`#${row.id} ${row.purpose}: ${row.status} · ${row.outcome || "outcome unknown"} · seen ${row.seen_count} · submitted ${row.submitted_count} · saved ${row.promoted_count}\n`);
3644
+ if (row.error_message) context.stdout.write(` ${row.error_message}\n`);
3645
+ }
3646
+ if (!payload.runs?.length) context.stdout.write("No discovery runs on this page.\n");
3647
+ if (payload.has_more) context.stdout.write(`More runs: --cursor ${payload.next_cursor}\n`);
3648
+ }
3649
+
3605
3650
  async function motionsStatus(args, context, { accountOverride } = {}) {
3606
3651
  const { values, positionals } = parseCommandArgs(args, jsonOptions());
3607
3652
  if (positionals.length !== 1) throw new CommandError("Usage: audienti motions status <motn_id> [--json] [--account <acct_id>]");
@@ -10621,6 +10666,7 @@ const HELP_TOPICS = new Map([
10621
10666
  ["skills list", "Usage:\n audienti skills list [--json]\n\nList bundled skills and marketplace discovery metadata without network or login."],
10622
10667
  ["skills show", "Usage:\n audienti skills show <name> [--json]\n\nPrint bundled skill instructions, or upstream source links and host-specific install commands. Read each upstream README for its dependencies. Installation is a separate action."],
10623
10668
  ["tools gift-research", "Usage:\n audienti tools gift-research --url <website> [--json]\n\nGive the agent the website-gift-research skill and the supplied HTTP(S) URL. The agent browses using its own tools. The CLI does not fetch the website, call Audienti, require login, create gifts or return research results.\n\nRead the skill without a website:\n audienti skills show audienti-gift-research"],
10669
+ ["motions runs", "Usage:\n audienti motions runs <motn_id> [--cursor <id>] [--limit <1-10>] [--json] [--account <acct_id>]\n\nList account-scoped discovery runs with read-only pagination."],
10624
10670
  ["", [
10625
10671
  "Usage:",
10626
10672
  " audienti <command> [options]",
@@ -10657,6 +10703,7 @@ const HELP_TOPICS = new Map([
10657
10703
  " audienti motions list",
10658
10704
  " audienti motions show <motn_id>",
10659
10705
  " audienti motions analytics <motn_id>",
10706
+ " audienti motions runs <motn_id> [--cursor <id>] [--limit <1-10>] [--json]",
10660
10707
  " audienti motions run-discovery <motn_id>",
10661
10708
  " audienti motions quick-start --url <company_url> --confirm --wait",
10662
10709
  " audienti motions prospects <motn_id>",
@@ -10982,6 +11029,7 @@ const HELP_TOPICS = new Map([
10982
11029
  ["accounts", [
10983
11030
  "Usage:",
10984
11031
  " audienti accounts list [--json]",
11032
+ ` ${ACCOUNTS_CREATE_USAGE.slice("Usage: ".length)}`,
10985
11033
  " audienti accounts show [<acct_id>] [--json]",
10986
11034
  " audienti accounts select <acct_id>",
10987
11035
  "",
@@ -11026,6 +11074,21 @@ const HELP_TOPICS = new Map([
11026
11074
  " The CLI only requests work; provider traversal remains owned by the server worker."
11027
11075
  ].join("\n")],
11028
11076
 
11077
+ ["accounts create", [
11078
+ "Usage:",
11079
+ ` ${ACCOUNTS_CREATE_USAGE.slice("Usage: ".length)}`,
11080
+ "",
11081
+ "Creates a child under a root team account you administer and copies its admins.",
11082
+ "--parent accepts an accessible account name, unique fragment, numeric ID or prefixed ID.",
11083
+ "Ambiguous names list matching IDs; use an ID to choose. Duplicate child names fail clearly.",
11084
+ "Returns the new account ID. Your selected account does not change.",
11085
+ "Use audienti accounts select <new_acct_id> or --account <new_acct_id> for subsequent commands.",
11086
+ "",
11087
+ "API: POST /api/v1/accounts.json",
11088
+ "",
11089
+ "Example:",
11090
+ " audienti accounts create --name Doppel --parent OMALab --json"
11091
+ ].join("\n")],
11029
11092
  ["accounts list", [
11030
11093
  "Usage:",
11031
11094
  " audienti accounts list [--json] [--account <acct_id>]",
@@ -13019,6 +13082,7 @@ const HELP_TOPICS = new Map([
13019
13082
  " audienti motions show <motn_id> [--json]",
13020
13083
  " audienti motions signals <motn_id> [--json]",
13021
13084
  " audienti motions status <motn_id> [--json]",
13085
+ " audienti motions runs <motn_id> [--cursor <id>] [--limit <1-10>] [--json]",
13022
13086
  " audienti motions run-discovery <motn_id> [--target-count <n>] [--json]",
13023
13087
  " audienti motions quick-start --url <company_url> [--confirm] [--wait] [--json]",
13024
13088
  " audienti motions setup-state [--json]",
@@ -15936,20 +16000,21 @@ const PARITY_ACTION_COMMANDS = new Map([
15936
16000
  done: (_positionals, payload) => describeSocialCookie(payload?.social_cookie)
15937
16001
  }],
15938
16002
  ["social-cookies activity", {
15939
- usage: "audienti social-cookies activity <scok_id> [--section <actions|status|sync|browser>] [--window <1h|24h|7d|30d>] [--task-type <type>] [--page <n>]",
16003
+ usage: "audienti social-cookies activity <scok_id> [--section <actions|status|sync|browser>] [--window <1h|24h|7d|30d>] [--task-type <type>] [--task-id <id>] [--repair-id <id>] [--page <n>]",
15940
16004
  purpose: "Read a social account's action, sync, and browser activity without changing work.",
15941
16005
  api: "GET /api/v1/accounts/:account_id/social_cookies/:id/activity.json",
15942
16006
  json: true,
15943
16007
  options: {
15944
16008
  section: { type: "string" }, window: { type: "string" }, "task-type": { type: "string" },
15945
16009
  page: { type: "string" }, "per-page": { type: "string" }, "event-id": { type: "string" },
15946
- "task-id": { type: "string" }, "session-id": { type: "string" }, status: { type: "string" },
16010
+ "task-id": { type: "string" }, "repair-task-id": { type: "string" }, "repair-id": { type: "string" }, "session-id": { type: "string" }, status: { type: "string" },
15947
16011
  "action-type": { type: "string" }, "automation-filter": { type: "string" }, query: { type: "string" },
15948
16012
  "created-from": { type: "string" }, "created-to": { type: "string" }
15949
16013
  },
15950
16014
  run: (client, accountId, [id], values) => client.socialCookieActivity(accountId, id, compactObject({
15951
16015
  section: values.section, window: values.window, task_type: values["task-type"], page: values.page,
15952
16016
  per_page: values["per-page"], event_id: values["event-id"], task_id: values["task-id"],
16017
+ repair_task_id: values["repair-task-id"], repair_id: values["repair-id"],
15953
16018
  session_id: values["session-id"], status: values.status, action_type: values["action-type"],
15954
16019
  automation_filter: values["automation-filter"], query: values.query,
15955
16020
  created_from: values["created-from"], created_to: values["created-to"]