@audienti/cli 0.1.106 → 0.1.108
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 +13 -0
- package/README.md +12 -2
- package/package.json +1 -1
- package/src/api-client.js +7 -0
- package/src/cli.js +61 -48
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.108] - 2026-10-08
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Import receipts resolve to the surviving person after compatible LinkedIn duplicate reconciliation. Account and list records are preserved; conflicting records remain available for identity review.
|
|
12
|
+
|
|
13
|
+
## [0.1.107] - 2026-10-08
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `prospects import`, `prospects intake` and `prospects import-batch` can request a new list or system transition.
|
|
18
|
+
- Batch imports submit parsed rows and defaults to the account API in one request; the CLI renders the server response. Explicit invalid names are forwarded for API validation.
|
|
19
|
+
|
|
7
20
|
## [0.1.106] - 2026-10-08
|
|
8
21
|
|
|
9
22
|
### Added
|
package/README.md
CHANGED
|
@@ -839,14 +839,22 @@ audienti company-rules create --domain example.com --disposition not_fit --user
|
|
|
839
839
|
audienti company-rules apply --all
|
|
840
840
|
```
|
|
841
841
|
|
|
842
|
+
The direct intake action supports the same destination names and optional experiment:
|
|
843
|
+
|
|
844
|
+
```bash
|
|
845
|
+
audienti prospects intake --url https://www.linkedin.com/in/example --new-list "Target list" --new-transition "Fit transition" --json
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
Use `--motion <motn_id>` for an existing experiment. Explicit new names, including blank names, are sent to the API for validation.
|
|
849
|
+
|
|
842
850
|
To import multiple LinkedIn people through the same per-prospect import path:
|
|
843
851
|
|
|
844
852
|
```bash
|
|
845
|
-
audienti prospects import-batch --file prospects.csv --
|
|
853
|
+
audienti prospects import-batch --file prospects.csv --new-list "Target list" --new-transition "Fit transition" --assigned-user me
|
|
846
854
|
```
|
|
847
855
|
|
|
848
856
|
CSV files should include a `linkedin_url` or `url` header. Optional row columns
|
|
849
|
-
`list_id`, `motion_id`, and `assigned_user_id` override command defaults.
|
|
857
|
+
`list_id`, `motion_id`, `new_list_name`, `new_transition_name`, and `assigned_user_id` override command defaults. The command parses the file and sends one batch request; the API owns validation, destination creation, row outcomes, and queueing.
|
|
850
858
|
|
|
851
859
|
## Compatibility
|
|
852
860
|
|
|
@@ -867,3 +875,5 @@ credentials or silently authenticate an agent.
|
|
|
867
875
|
## License
|
|
868
876
|
|
|
869
877
|
Copyright (c) 2026 OMALab, Inc. All rights reserved. See [LICENSE](LICENSE).
|
|
878
|
+
|
|
879
|
+
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.
|
package/package.json
CHANGED
package/src/api-client.js
CHANGED
|
@@ -1210,6 +1210,13 @@ export class AudientiClient {
|
|
|
1210
1210
|
});
|
|
1211
1211
|
}
|
|
1212
1212
|
|
|
1213
|
+
prospectImportBatch(accountId, body) {
|
|
1214
|
+
return this.requestJson(accountPath(accountId, ["prospect_imports", "batch"]), {
|
|
1215
|
+
method: "POST",
|
|
1216
|
+
body
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1213
1220
|
prospectImportStatus(accountId, importId) {
|
|
1214
1221
|
return this.requestJson(accountPath(accountId, ["prospect_imports", importId]));
|
|
1215
1222
|
}
|
package/src/cli.js
CHANGED
|
@@ -77,7 +77,7 @@ const PROSPECTS_RESTORE_USAGE = "Usage: audienti prospects restore <prsp_id> [--
|
|
|
77
77
|
const PROSPECTS_LOCK_USAGE = "Usage: audienti prospects lock <prsp_id> [--note <text>] [--kind <protected_relationship|company_policy>] [--json] [--account <acct_id>]";
|
|
78
78
|
const PROSPECTS_UNLOCK_USAGE = "Usage: audienti prospects unlock <prsp_id> [--json] [--account <acct_id>]";
|
|
79
79
|
const PROSPECTS_CHECK_USAGE = "Usage: audienti prospects check [--json|--csv] [filters] [--account <acct_id>]";
|
|
80
|
-
const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
|
|
80
|
+
const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--new-list <name>] [--new-transition <name>] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
|
|
81
81
|
const OPERATOR_FAILED_DRAFTS_USAGE = "Usage: audienti operator failed-drafts [--json] [filters] [--account <acct_id>]";
|
|
82
82
|
const OPERATOR_FAILED_DRAFTS_REQUEUE_USAGE = "Usage: audienti operator failed-drafts requeue (--all | <row_id> [row_id...]) [--limit <n>] [--json] [filters] [--account <acct_id>]";
|
|
83
83
|
const INBOX_OPS_QUEUE_USAGE = "Usage: audienti inbox-ops queue [--page <n>] [--offset <n>|--cursor <token>] [--group-by domain] [--json] [--account <acct_id>]";
|
|
@@ -5077,19 +5077,23 @@ async function prospectsImport(args, context, { accountOverride } = {}) {
|
|
|
5077
5077
|
...jsonOptions(),
|
|
5078
5078
|
list: { type: "string" },
|
|
5079
5079
|
motion: { type: "string" },
|
|
5080
|
+
"new-list": { type: "string" },
|
|
5081
|
+
"new-transition": { type: "string" },
|
|
5080
5082
|
"assigned-user": { type: "string" }
|
|
5081
5083
|
});
|
|
5082
5084
|
if (positionals.length !== 1) {
|
|
5083
|
-
throw new CommandError("Usage: audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]");
|
|
5085
|
+
throw new CommandError("Usage: audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--new-list <name>] [--new-transition <name>] [--assigned-user <id|me>] [--json] [--account <acct_id>]");
|
|
5084
5086
|
}
|
|
5085
5087
|
|
|
5086
5088
|
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
5087
|
-
const payload = await client.prospectImport(accountId,
|
|
5089
|
+
const payload = await client.prospectImport(accountId, compactObjectPreservingFields({
|
|
5088
5090
|
linkedin_url: positionals[0],
|
|
5089
5091
|
list_id: values.list,
|
|
5090
5092
|
motion_id: values.motion,
|
|
5093
|
+
new_list_name: values["new-list"],
|
|
5094
|
+
new_transition_name: values["new-transition"],
|
|
5091
5095
|
assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
|
|
5092
|
-
}));
|
|
5096
|
+
}, ["new_list_name", "new_transition_name"]));
|
|
5093
5097
|
if (values.json) return writeJson(context.stdout, payload);
|
|
5094
5098
|
|
|
5095
5099
|
renderProspectImportStarted(payload, context);
|
|
@@ -5101,7 +5105,9 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
|
|
|
5101
5105
|
file: { type: "string" },
|
|
5102
5106
|
list: { type: "string" },
|
|
5103
5107
|
motion: { type: "string" },
|
|
5104
|
-
"assigned-user": { type: "string" }
|
|
5108
|
+
"assigned-user": { type: "string" },
|
|
5109
|
+
"new-list": { type: "string" },
|
|
5110
|
+
"new-transition": { type: "string" }
|
|
5105
5111
|
});
|
|
5106
5112
|
if (positionals.length > 0 || !values.file) {
|
|
5107
5113
|
throw new CommandError(PROSPECTS_IMPORT_BATCH_USAGE);
|
|
@@ -5111,40 +5117,16 @@ async function prospectsImportBatch(args, context, { accountOverride } = {}) {
|
|
|
5111
5117
|
if (rows.length === 0) throw new CommandError("Import batch file did not contain any prospects.");
|
|
5112
5118
|
|
|
5113
5119
|
const { client, accountId, config } = await requireAccountContext(context, { accountOverride });
|
|
5114
|
-
const result = {
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
for (const row of rows) {
|
|
5125
|
-
const body = compactObject({
|
|
5126
|
-
linkedin_url: row.linkedin_url,
|
|
5127
|
-
list_id: row.list_id || values.list,
|
|
5128
|
-
motion_id: row.motion_id || values.motion,
|
|
5129
|
-
assigned_user_id: resolveAccountUserId(row.assigned_user_id || values["assigned-user"], config, { accountOverride })
|
|
5130
|
-
});
|
|
5131
|
-
|
|
5132
|
-
try {
|
|
5133
|
-
const payload = await client.prospectImport(accountId, body);
|
|
5134
|
-
result.imports.push(payload);
|
|
5135
|
-
result.summary.started += 1;
|
|
5136
|
-
} catch (error) {
|
|
5137
|
-
if (!(error instanceof ApiError)) throw error;
|
|
5138
|
-
|
|
5139
|
-
result.failed.push({
|
|
5140
|
-
row: row.row,
|
|
5141
|
-
linkedin_url: row.linkedin_url,
|
|
5142
|
-
status: error.status,
|
|
5143
|
-
error: error.body?.error || error.message
|
|
5144
|
-
});
|
|
5145
|
-
result.summary.failed += 1;
|
|
5146
|
-
}
|
|
5147
|
-
}
|
|
5120
|
+
const result = await client.prospectImportBatch(accountId, {
|
|
5121
|
+
rows,
|
|
5122
|
+
defaults: compactObjectPreservingFields({
|
|
5123
|
+
list_id: values.list,
|
|
5124
|
+
motion_id: values.motion,
|
|
5125
|
+
new_list_name: values["new-list"],
|
|
5126
|
+
new_transition_name: values["new-transition"],
|
|
5127
|
+
assigned_user_id: resolveAccountUserId(values["assigned-user"], config, { accountOverride })
|
|
5128
|
+
}, ["new_list_name", "new_transition_name"])
|
|
5129
|
+
});
|
|
5148
5130
|
|
|
5149
5131
|
if (values.json) {
|
|
5150
5132
|
writeJson(context.stdout, result);
|
|
@@ -6714,6 +6696,16 @@ function compactObject(object) {
|
|
|
6714
6696
|
);
|
|
6715
6697
|
}
|
|
6716
6698
|
|
|
6699
|
+
function compactObjectPreservingFields(object, fields) {
|
|
6700
|
+
const compacted = compactObject(object);
|
|
6701
|
+
for (const field of fields) {
|
|
6702
|
+
if (Object.prototype.hasOwnProperty.call(object, field) && object[field] !== undefined) {
|
|
6703
|
+
compacted[field] = object[field];
|
|
6704
|
+
}
|
|
6705
|
+
}
|
|
6706
|
+
return compacted;
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6717
6709
|
async function readLocalPackageMetadata() {
|
|
6718
6710
|
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
6719
6711
|
return {
|
|
@@ -7256,13 +7248,21 @@ function normalizeImportBatchRows(rows, filePath) {
|
|
|
7256
7248
|
const linkedinUrl = normalized?.linkedin_url || normalized?.url;
|
|
7257
7249
|
if (!linkedinUrl) throw new CommandError(`Missing linkedin_url on row ${rowNumber} in ${filePath}.`);
|
|
7258
7250
|
|
|
7259
|
-
|
|
7251
|
+
const result = compactObject({
|
|
7260
7252
|
row: rowNumber,
|
|
7261
7253
|
linkedin_url: linkedinUrl,
|
|
7262
7254
|
list_id: normalized.list_id,
|
|
7263
7255
|
motion_id: normalized.motion_id,
|
|
7256
|
+
new_list_name: normalized.new_list_name,
|
|
7257
|
+
new_transition_name: normalized.new_transition_name,
|
|
7264
7258
|
assigned_user_id: normalized.assigned_user_id || normalized.assigned_user
|
|
7265
7259
|
});
|
|
7260
|
+
|
|
7261
|
+
for (const field of ["new_list_name", "new_transition_name"]) {
|
|
7262
|
+
if (Object.prototype.hasOwnProperty.call(normalized, field)) result[field] = normalized[field];
|
|
7263
|
+
}
|
|
7264
|
+
|
|
7265
|
+
return result;
|
|
7266
7266
|
});
|
|
7267
7267
|
}
|
|
7268
7268
|
|
|
@@ -13637,8 +13637,8 @@ const HELP_TOPICS = new Map([
|
|
|
13637
13637
|
" audienti prospects report-bad-profile <prsp_id> <prof_id|citation_id> [--json]",
|
|
13638
13638
|
" audienti prospects sequence-preview <prsp_id> [--json]",
|
|
13639
13639
|
" audienti prospects sequence-export <prsp_id> [--csv]",
|
|
13640
|
-
" audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--json]",
|
|
13641
|
-
" audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--json]",
|
|
13640
|
+
" audienti prospects import <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--new-list <name>] [--new-transition <name>] [--json]",
|
|
13641
|
+
" audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--new-list <name>] [--new-transition <name>] [--json]",
|
|
13642
13642
|
" audienti prospects import-status <primp_id> [--json]",
|
|
13643
13643
|
"",
|
|
13644
13644
|
"Status: read commands, assignment, disposition, lock/unlock, per-prospect draft preview, sequence preview, and import implemented",
|
|
@@ -14324,13 +14324,15 @@ const HELP_TOPICS = new Map([
|
|
|
14324
14324
|
" file: CSV with linkedin_url/url header, JSON array, JSONL objects, or newline-delimited LinkedIn URLs",
|
|
14325
14325
|
" list_id: list_ prefix id | optional default for every row",
|
|
14326
14326
|
" motn_id: motn_ prefix id | optional default for every row",
|
|
14327
|
+
" new_list_name: list name | a row value creates that row's list; command default applies to rows without one",
|
|
14328
|
+
" new_transition_name: system transition name | a row value creates that row's transition; command default applies to rows without one",
|
|
14327
14329
|
" assigned_user_id: account user id or me | optional default for every row",
|
|
14328
14330
|
"",
|
|
14329
14331
|
"CSV columns:",
|
|
14330
|
-
" linkedin_url or url, list_id, motion_id, assigned_user_id",
|
|
14332
|
+
" linkedin_url or url, list_id, motion_id, new_list_name, new_transition_name, assigned_user_id",
|
|
14331
14333
|
"",
|
|
14332
14334
|
"Behavior:",
|
|
14333
|
-
" Starts one normal prospect import per row. Row-level
|
|
14335
|
+
" Starts one normal prospect import per row. Row-level destination names or IDs and assigned_user_id override command defaults.",
|
|
14334
14336
|
"",
|
|
14335
14337
|
"API:",
|
|
14336
14338
|
" POST /api/v1/accounts/:account_id/prospect_imports.json"
|
|
@@ -15650,19 +15652,30 @@ const PARITY_ACTION_COMMANDS = new Map([
|
|
|
15650
15652
|
done: (_positionals, payload) => `Rejected ${payload?.rejected?.length ?? 0}; failed ${payload?.failed?.length ?? 0}.`
|
|
15651
15653
|
}],
|
|
15652
15654
|
["prospects intake", {
|
|
15653
|
-
usage: "audienti prospects intake --url <linkedin_url> [--list <list_id>] [--assign <account_user_id>] [--signal <custom_signal_id>]",
|
|
15655
|
+
usage: "audienti prospects intake --url <linkedin_url> [--list <list_id>] [--motion <motn_id>] [--new-list <name>] [--new-transition <name>] [--assign <account_user_id>] [--signal <custom_signal_id>]",
|
|
15654
15656
|
minPositionals: 0,
|
|
15655
15657
|
maxPositionals: 0,
|
|
15656
15658
|
purpose: "Add one LinkedIn person by URL, like Add prospect on the web.",
|
|
15657
15659
|
api: "POST /api/v1/accounts/:account_id/prospects/intake.json",
|
|
15658
|
-
options: {
|
|
15660
|
+
options: {
|
|
15661
|
+
url: { type: "string" },
|
|
15662
|
+
list: { type: "string" },
|
|
15663
|
+
motion: { type: "string" },
|
|
15664
|
+
"new-list": { type: "string" },
|
|
15665
|
+
"new-transition": { type: "string" },
|
|
15666
|
+
assign: { type: "string" },
|
|
15667
|
+
signal: { type: "string" }
|
|
15668
|
+
},
|
|
15659
15669
|
required: ["url"],
|
|
15660
|
-
run: (client, accountId, _positionals, values) => client.intakeProspect(accountId,
|
|
15670
|
+
run: (client, accountId, _positionals, values) => client.intakeProspect(accountId, compactObjectPreservingFields({
|
|
15661
15671
|
url: values.url,
|
|
15662
15672
|
list_id: values.list,
|
|
15673
|
+
motion_id: values.motion,
|
|
15674
|
+
new_list_name: values["new-list"],
|
|
15675
|
+
new_transition_name: values["new-transition"],
|
|
15663
15676
|
assigned_to_account_user_id: values.assign,
|
|
15664
15677
|
custom_signal_id: values.signal
|
|
15665
|
-
})),
|
|
15678
|
+
}, ["new_list_name", "new_transition_name"])),
|
|
15666
15679
|
done: () => "Prospect intake queued."
|
|
15667
15680
|
}],
|
|
15668
15681
|
["events retry", {
|