@audienti/cli 0.1.36 → 0.1.37
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 +10 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/skills/audienti/SKILL.md +9 -0
- package/src/cli.js +76 -12
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ All notable changes to the Audienti CLI are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.1.37] - 2026-08-23
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Add motion start/end scheduling and maximum-company discovery-cap configuration to motion API readback and CLI create/update/show workflows.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Show conversion totals, stage SLA, and oldest stage age in the default `audienti analytics stages` output so it matches the dashboard read model without requiring `--json`.
|
|
16
|
+
|
|
7
17
|
## [0.1.36] - 2026-08-22
|
|
8
18
|
|
|
9
19
|
### Added
|
package/README.md
CHANGED
|
@@ -143,6 +143,7 @@ audienti motions quick-start --url https://example.com --wait --confirm
|
|
|
143
143
|
audienti motions abm-companies <motn_id> add --file abm-domains.txt
|
|
144
144
|
audienti motions abm-companies <motn_id> list
|
|
145
145
|
audienti motions update <motn_id> --status paused
|
|
146
|
+
audienti motions update <motn_id> --start-date 2026-09-01 --end-date 2026-09-30 --maximum-company-count 25
|
|
146
147
|
audienti motions update <motn_id> --own-post-engagement true
|
|
147
148
|
audienti motions update <motn_id> --payload motion-signals.json
|
|
148
149
|
audienti motions activate <motn_id>
|
package/package.json
CHANGED
package/skills/audienti/SKILL.md
CHANGED
|
@@ -110,11 +110,13 @@ audienti motions quick-start --url https://example.com --wait --confirm --json
|
|
|
110
110
|
audienti motions abm-companies <motn_id> add --file abm-domains.txt --json
|
|
111
111
|
audienti motions abm-companies <motn_id> list --json
|
|
112
112
|
audienti motions update <motn_id> --status paused --json
|
|
113
|
+
audienti motions update <motn_id> --start-date 2026-09-01 --end-date 2026-09-30 --maximum-company-count 25 --json
|
|
113
114
|
audienti motions activate <motn_id> --json
|
|
114
115
|
audienti motions delete <motn_id> --confirm yes --json
|
|
115
116
|
audienti operator next --json
|
|
116
117
|
audienti operator next --plan
|
|
117
118
|
audienti analytics prospects --window 24h --json
|
|
119
|
+
audienti analytics stages --window 30d
|
|
118
120
|
audienti analytics visibility --window 24h --user me --json
|
|
119
121
|
audienti analytics content --window week --json
|
|
120
122
|
audienti tools list --json
|
|
@@ -135,6 +137,13 @@ condition and action data as the list UI. Inspect the ordered rules first, use
|
|
|
135
137
|
as an asynchronous relaunch: it queues the existing routing job and does not
|
|
136
138
|
mean every list member has finished routing.
|
|
137
139
|
|
|
140
|
+
Motion start and end dates are optional lifecycle controls. A due start can
|
|
141
|
+
activate a configured preparing or paused motion; an end date is the final
|
|
142
|
+
active day and pauses the motion afterward. `--maximum-company-count` caps
|
|
143
|
+
durable company admissions only: research and people discovery for admitted
|
|
144
|
+
companies, prospect intake, and automation continue. Use `none` to clear any
|
|
145
|
+
of these settings.
|
|
146
|
+
|
|
138
147
|
`audienti writer test-run <prsp_id>` starts a report-backed writing session and
|
|
139
148
|
builds the campaign timeline without drafting every message. The printed
|
|
140
149
|
`Report: rprt_...` id is the session handle. Pass `--report <rprt_id>` when
|
package/src/cli.js
CHANGED
|
@@ -72,7 +72,7 @@ const OFFERS_DELETE_USAGE = "Usage: audienti offers delete <offr_id> --confirm <
|
|
|
72
72
|
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>]";
|
|
73
73
|
const WRITER_TEST_RUN_SHOW_USAGE = "Usage: audienti writer test-run show <prsp_id> <rprt_id> [--json] [--account <acct_id>]";
|
|
74
74
|
const MOTIONS_ANALYTICS_USAGE = "Usage: audienti motions analytics <motn_id> [--window 30d] [--json] [--account <acct_id>]";
|
|
75
|
-
const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> ([--status <draft|preparing|active|paused|archived>] [--tags <tag[,tag...]>] [--own-post-engagement <true|false>] | --payload <file.json>) [--json] [--account <acct_id>]";
|
|
75
|
+
const MOTIONS_UPDATE_USAGE = "Usage: audienti motions update <motn_id> ([--status <draft|preparing|active|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>] | --payload <file.json>) [--json] [--account <acct_id>]";
|
|
76
76
|
const CONTENT_PROGRAMS_USAGE = "Usage: audienti content programs [--user <account_user_id|email|name|me>] [--json] [--account <acct_id>]";
|
|
77
77
|
const CONTENT_PLAN_USAGE = "Usage: audienti content plan <cprg_id> [--week <n>] [--due] [--json] [--account <acct_id>]";
|
|
78
78
|
const CONTENT_SHOW_USAGE = "Usage: audienti content show <cpwi_id> [--json] [--account <acct_id>]";
|
|
@@ -1881,7 +1881,10 @@ async function motionsUpdate(args, context, { accountOverride } = {}) {
|
|
|
1881
1881
|
payload: { type: "string" },
|
|
1882
1882
|
status: { type: "string" },
|
|
1883
1883
|
tags: { type: "string" },
|
|
1884
|
-
"own-post-engagement": { type: "string" }
|
|
1884
|
+
"own-post-engagement": { type: "string" },
|
|
1885
|
+
"start-date": { type: "string" },
|
|
1886
|
+
"end-date": { type: "string" },
|
|
1887
|
+
"maximum-company-count": { type: "string" }
|
|
1885
1888
|
});
|
|
1886
1889
|
const hasUpdateField = values.payload || motionSimpleFieldsPresent(values);
|
|
1887
1890
|
if (positionals.length !== 1 || !hasUpdateField) {
|
|
@@ -1899,7 +1902,7 @@ async function motionsUpdate(args, context, { accountOverride } = {}) {
|
|
|
1899
1902
|
async function motionUpdatePayload(values) {
|
|
1900
1903
|
if (values.payload) {
|
|
1901
1904
|
if (motionSimpleFieldsPresent(values)) {
|
|
1902
|
-
throw new CommandError("Choose one motion input mode: either --payload <file.json> or the simple
|
|
1905
|
+
throw new CommandError("Choose one motion input mode: either --payload <file.json> or the simple motion update flags.");
|
|
1903
1906
|
}
|
|
1904
1907
|
|
|
1905
1908
|
const payload = await readJsonPayload(values.payload);
|
|
@@ -1907,15 +1910,54 @@ async function motionUpdatePayload(values) {
|
|
|
1907
1910
|
return payload;
|
|
1908
1911
|
}
|
|
1909
1912
|
|
|
1910
|
-
|
|
1913
|
+
const payload = compactObject({
|
|
1911
1914
|
status: normalizeMotionStatus(values.status),
|
|
1912
1915
|
play_tags: values.tags !== undefined ? tagList(values.tags) : undefined,
|
|
1913
1916
|
own_post_engagement: values["own-post-engagement"] !== undefined ? parseBooleanString(values["own-post-engagement"], "--own-post-engagement") : undefined
|
|
1914
1917
|
});
|
|
1918
|
+
const nullableSettings = {
|
|
1919
|
+
starts_on: normalizeMotionDate(values["start-date"], "--start-date"),
|
|
1920
|
+
ends_on: normalizeMotionDate(values["end-date"], "--end-date"),
|
|
1921
|
+
maximum_company_count: normalizeMotionMaximumCompanyCount(values["maximum-company-count"])
|
|
1922
|
+
};
|
|
1923
|
+
for (const [key, value] of Object.entries(nullableSettings)) {
|
|
1924
|
+
if (value !== undefined) payload[key] = value;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
return payload;
|
|
1915
1928
|
}
|
|
1916
1929
|
|
|
1917
1930
|
function motionSimpleFieldsPresent(values) {
|
|
1918
|
-
return Boolean(values.status) ||
|
|
1931
|
+
return Boolean(values.status) ||
|
|
1932
|
+
values.tags !== undefined ||
|
|
1933
|
+
values["own-post-engagement"] !== undefined ||
|
|
1934
|
+
values["start-date"] !== undefined ||
|
|
1935
|
+
values["end-date"] !== undefined ||
|
|
1936
|
+
values["maximum-company-count"] !== undefined;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
function normalizeMotionDate(value, flagName) {
|
|
1940
|
+
if (value === undefined) return undefined;
|
|
1941
|
+
|
|
1942
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
1943
|
+
if (normalized === "none") return null;
|
|
1944
|
+
const match = normalized.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
1945
|
+
if (!match) throw new CommandError(`${flagName} must be YYYY-MM-DD or none.`);
|
|
1946
|
+
|
|
1947
|
+
const [, year, month, day] = match.map(Number);
|
|
1948
|
+
const parsed = new Date(Date.UTC(year, month - 1, day));
|
|
1949
|
+
if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
|
|
1950
|
+
throw new CommandError(`${flagName} must be YYYY-MM-DD or none.`);
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
return normalized;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
function normalizeMotionMaximumCompanyCount(value) {
|
|
1957
|
+
if (value === undefined) return undefined;
|
|
1958
|
+
if (String(value || "").trim().toLowerCase() === "none") return null;
|
|
1959
|
+
|
|
1960
|
+
return normalizeOptionalPositiveInteger(value, "--maximum-company-count");
|
|
1919
1961
|
}
|
|
1920
1962
|
|
|
1921
1963
|
function validateMotionSignalRows(payload) {
|
|
@@ -4588,6 +4630,9 @@ function renderMotion(motion, context) {
|
|
|
4588
4630
|
writeLine(context.stdout, `Motion: ${display(motion?.name)} (${display(motion?.prefix_id)})`);
|
|
4589
4631
|
writeLine(context.stdout, `Status: ${display(motion?.status)}`);
|
|
4590
4632
|
writeLine(context.stdout, `Kind: ${display(motion?.kind)}`);
|
|
4633
|
+
writeLine(context.stdout, `Start date: ${display(motion?.starts_on, "not set")}`);
|
|
4634
|
+
writeLine(context.stdout, `End date: ${display(motion?.ends_on, "not set")}`);
|
|
4635
|
+
writeLine(context.stdout, `Maximum companies: ${display(motion?.maximum_company_count, "not set")}`);
|
|
4591
4636
|
renderExecutableConfiguration(motion?.executable_configuration, context);
|
|
4592
4637
|
if (motion?.offer?.name) writeLine(context.stdout, `Offer: ${motion.offer.name} (${display(motion.offer.prefix_id)})`);
|
|
4593
4638
|
if (motion?.icp?.name) writeLine(context.stdout, `ICP: ${motion.icp.name} (${display(motion.icp.prefix_id)})`);
|
|
@@ -5780,6 +5825,7 @@ function writeStageConversionTable(conversionGrid, context) {
|
|
|
5780
5825
|
const rows = Array.isArray(conversionGrid?.rows) ? conversionGrid.rows : [];
|
|
5781
5826
|
const definitions = Array.isArray(conversionGrid?.stage_definitions) ? conversionGrid.stage_definitions : [];
|
|
5782
5827
|
const columns = definitions.filter((definition) => definition?.key);
|
|
5828
|
+
const totalValues = conversionGrid?.total_values || {};
|
|
5783
5829
|
|
|
5784
5830
|
writeLine(context.stdout, "");
|
|
5785
5831
|
writeLine(context.stdout, display(conversionGrid?.window_description, "Conversion cohorts"));
|
|
@@ -5790,6 +5836,12 @@ function writeStageConversionTable(conversionGrid, context) {
|
|
|
5790
5836
|
display(row?.label),
|
|
5791
5837
|
...columns.map((column) => stageMetricValueLabel(row?.values?.[column.key]))
|
|
5792
5838
|
]);
|
|
5839
|
+
if (Object.keys(totalValues).length > 0) {
|
|
5840
|
+
tableRows.push([
|
|
5841
|
+
"TOTAL",
|
|
5842
|
+
...columns.map((column) => stageMetricValueLabel(totalValues[column.key]))
|
|
5843
|
+
]);
|
|
5844
|
+
}
|
|
5793
5845
|
|
|
5794
5846
|
writeAlignedTable(context, headers, tableRows);
|
|
5795
5847
|
}
|
|
@@ -5807,20 +5859,22 @@ function writeStageAgingTable(stageAging, context) {
|
|
|
5807
5859
|
);
|
|
5808
5860
|
writeAlignedTable(
|
|
5809
5861
|
context,
|
|
5810
|
-
["STAGE", "CURRENT", "DUE SOON", "OVERDUE", "OVERDUE %", "MED AGE", "OLDEST IDLE"],
|
|
5862
|
+
["STAGE", "SLA", "CURRENT", "DUE SOON", "OVERDUE", "OVERDUE %", "MED AGE", "OLDEST AGE", "OLDEST IDLE"],
|
|
5811
5863
|
rows.map(stageAgingRow),
|
|
5812
|
-
{ numericColumns: [false, true, true, true, true, true, true] }
|
|
5864
|
+
{ numericColumns: [false, true, true, true, true, true, true, true, true] }
|
|
5813
5865
|
);
|
|
5814
5866
|
}
|
|
5815
5867
|
|
|
5816
5868
|
function stageAgingRow(row) {
|
|
5817
5869
|
return [
|
|
5818
5870
|
display(row?.label || row?.key),
|
|
5871
|
+
dayCountLabel(row?.due_after_days),
|
|
5819
5872
|
display(row?.current_count, 0),
|
|
5820
5873
|
display(row?.due_soon_count, 0),
|
|
5821
5874
|
display(row?.overdue_count, 0),
|
|
5822
5875
|
percentageLabel(row?.overdue_rate),
|
|
5823
5876
|
dayCountLabel(row?.median_stage_age_days),
|
|
5877
|
+
dayCountLabel(row?.oldest_stage_age_days),
|
|
5824
5878
|
dayCountLabel(row?.oldest_idle_days)
|
|
5825
5879
|
];
|
|
5826
5880
|
}
|
|
@@ -6576,7 +6630,7 @@ const HELP_TOPICS = new Map([
|
|
|
6576
6630
|
" audienti motions abm-companies <motn_id> list",
|
|
6577
6631
|
" audienti motions abm-companies <motn_id> add <domain_or_linkedin_url>...",
|
|
6578
6632
|
" audienti motions create --payload <file.json>",
|
|
6579
|
-
" audienti motions update <motn_id> [--status <state>] [--tags <tag[,tag...]>] [--own-post-engagement <true|false>]",
|
|
6633
|
+
" audienti motions update <motn_id> [--status <state>] [--tags <tag[,tag...]>] [--own-post-engagement <true|false>] [--start-date <date|none>] [--end-date <date|none>] [--maximum-company-count <n|none>]",
|
|
6580
6634
|
" audienti motions update <motn_id> --payload <file.json>",
|
|
6581
6635
|
" audienti motions add-tag <motn_id> <tag>",
|
|
6582
6636
|
" audienti motions remove-tag <motn_id> <tag>",
|
|
@@ -7899,7 +7953,7 @@ const HELP_TOPICS = new Map([
|
|
|
7899
7953
|
" audienti motions abm-companies <motn_id> add (<domain_or_linkedin_url>... | --file <txt|json>) [--json]",
|
|
7900
7954
|
" audienti motions abm-companies <motn_id> remove <row_id> [--json]",
|
|
7901
7955
|
" audienti motions create --payload <file.json> [--json]",
|
|
7902
|
-
"
|
|
7956
|
+
` ${MOTIONS_UPDATE_USAGE.slice("Usage: ".length).replace(" [--account <acct_id>]", "")}`,
|
|
7903
7957
|
" audienti motions add-tag <motn_id> <tag> [--json]",
|
|
7904
7958
|
" audienti motions remove-tag <motn_id> <tag> [--json]",
|
|
7905
7959
|
" audienti motions activate <motn_id> [--json]",
|
|
@@ -8177,6 +8231,9 @@ const HELP_TOPICS = new Map([
|
|
|
8177
8231
|
" icp_id: icpp_ prefix id | optional",
|
|
8178
8232
|
" list_id: list_ prefix id | optional",
|
|
8179
8233
|
" play_tags: [string] | optional",
|
|
8234
|
+
" starts_on: YYYY-MM-DD | null | optional scheduled activation date",
|
|
8235
|
+
" ends_on: YYYY-MM-DD | null | optional final active date",
|
|
8236
|
+
" maximum_company_count: positive integer | null | optional new-company discovery cap",
|
|
8180
8237
|
" signal_rows: [{ scope: company | person | both, question: string, company_signal_category: string | optional, role_terms: string | optional, posting_language: hiring-only string | optional, topics: string | optional }] | optional for outbound motions",
|
|
8181
8238
|
" signal_questions: newline-delimited company::, person::, or both:: legacy question text | optional for outbound motions",
|
|
8182
8239
|
" inbound_channels: [linkedin | reddit] | optional; defaults to [linkedin] for inbound motions",
|
|
@@ -8191,6 +8248,9 @@ const HELP_TOPICS = new Map([
|
|
|
8191
8248
|
" \"offer_id\": \"offr_abc123\",",
|
|
8192
8249
|
" \"principal_account_user_id\": 42,",
|
|
8193
8250
|
" \"list_id\": \"list_abc123\",",
|
|
8251
|
+
" \"starts_on\": \"2026-09-01\",",
|
|
8252
|
+
" \"ends_on\": \"2026-09-30\",",
|
|
8253
|
+
" \"maximum_company_count\": 25,",
|
|
8194
8254
|
" \"play_tags\": [\"sarit\", \"pj\"]",
|
|
8195
8255
|
" }",
|
|
8196
8256
|
"",
|
|
@@ -8214,8 +8274,8 @@ const HELP_TOPICS = new Map([
|
|
|
8214
8274
|
" name: new motion name",
|
|
8215
8275
|
"",
|
|
8216
8276
|
"Behavior:",
|
|
8217
|
-
" Copies the motion kind, offer, ICP, principal, premise, approach, targeting profile, suppression policy, secondary roles, and active signal rows.",
|
|
8218
|
-
" The clone starts as draft with a new empty backing list.",
|
|
8277
|
+
" Copies the motion kind, offer, ICP, principal, premise, approach, maximum company count, targeting profile, suppression policy, secondary roles, and active signal rows.",
|
|
8278
|
+
" The clone starts as draft with a new empty backing list and no inherited schedule dates.",
|
|
8219
8279
|
"",
|
|
8220
8280
|
"API:",
|
|
8221
8281
|
" POST /api/v1/accounts/:account_id/motions/:id/clone.json",
|
|
@@ -8241,10 +8301,14 @@ const HELP_TOPICS = new Map([
|
|
|
8241
8301
|
" motn_id: motn_ prefix id",
|
|
8242
8302
|
" status: draft | preparing | active | paused | archived | optional",
|
|
8243
8303
|
" tags: comma-separated tag list | optional",
|
|
8304
|
+
" start-date: YYYY-MM-DD | none | optional",
|
|
8305
|
+
" end-date: YYYY-MM-DD | none | optional",
|
|
8306
|
+
" maximum-company-count: positive integer | none | optional",
|
|
8244
8307
|
" payload: file.json | optional full or partial motion object using the account API shape",
|
|
8245
8308
|
"",
|
|
8246
8309
|
"Behavior:",
|
|
8247
|
-
" Choose either --payload or simple flags. Updates only the provided fields. Sending --tags replaces the motion's full tag set.",
|
|
8310
|
+
" Choose either --payload or simple flags. Updates only the provided fields. Use none to clear a schedule date or company cap. Sending --tags replaces the motion's full tag set.",
|
|
8311
|
+
" The company cap stops only new company discovery; existing company research, people discovery, prospect intake, and automation continue.",
|
|
8248
8312
|
" Payload mode supports outbound signal_rows or legacy signal_questions; supplied rows replace the motion's active ready signals.",
|
|
8249
8313
|
" posting_language is only supported on company-scope hiring signal rows; use topics for person discussion evidence.",
|
|
8250
8314
|
"",
|