@dench.com/cli 3.5.5 → 3.5.6-staging.344

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/README.md CHANGED
@@ -334,8 +334,9 @@ dench campaign pause|resume|archive <campaign>
334
334
  dench campaign stop <campaign> --person <enrollmentId>
335
335
  ```
336
336
 
337
- Steps lock at launch (`steps set` works on drafts only); the schedule, daily
338
- cap and stop-on-reply stay editable with `dench campaign set`. A campaign
337
+ `steps set` works on drafts only; after launch, edit a step's text or wait
338
+ time in the Dench app. The schedule, daily cap and stop-on-reply stay
339
+ editable with `dench campaign set`. A campaign
339
340
  holds at most 300 people. Every command takes `--json`. The full guide,
340
341
  including the `steps.json` shape and the `--window` spec, is
341
342
  `references/CAMPAIGNS.md` (`dench campaign help` for the flag list).
@@ -355,7 +356,7 @@ returned. LinkedIn summaries expose `linkedinAccountId`, display/owner labels,
355
356
  availability, `remainingToday` (invites/messages/profiles) and
356
357
  `remainingInvitesThisWeek`. Capacity is an account-local usage snapshot before
357
358
  queued work and campaign limits; today's invites also respect the weekly cap.
358
- The API equivalent is `GET /v1/campaigns/accounts/linkedin`.
359
+ The API equivalent is `GET $DENCH_API_BASE/campaigns/accounts/linkedin`.
359
360
 
360
361
  Outreach needs a workspace member's credentials (a `dench signin` session, a
361
362
  member-bound `DENCH_API_KEY`, or an agent session); an organization-only key
package/app-sdk.d.ts CHANGED
@@ -1824,9 +1824,20 @@ export interface ApiRequests {
1824
1824
  campaignId: string;
1825
1825
  };
1826
1826
  /** List managed email campaigns (paginated, optional status filter). — `dench email campaign list` — GET /api/v1/email/campaigns */
1827
- "email.campaign.list": Record<string, unknown>;
1827
+ "email.campaign.list": {
1828
+ limit?: number;
1829
+ cursor?: string;
1830
+ status?: string;
1831
+ };
1828
1832
  /** List a campaign's recipients (paginated, optional status filter). — `dench email campaign recipients list` — GET /api/v1/email/campaigns/{campaignId}/recipients */
1829
- "email.campaign.recipients.list": Record<string, unknown>;
1833
+ "email.campaign.recipients.list": {
1834
+ campaignId: string;
1835
+ limit?: number;
1836
+ cursor?: string;
1837
+ status?: string;
1838
+ /** Default true: attach each recipient's CRM record. */
1839
+ includePeople?: boolean;
1840
+ };
1830
1841
  /** Add campaign recipients from a CRM object: pick the object, the email field, and the entry ids. — `dench email campaign recipients add-from-object` — POST /api/v1/email/campaigns/{campaignId}/recipients/from-object */
1831
1842
  "email.campaign.recipients.addFromObject": Record<string, unknown>;
1832
1843
  /** Create a follow-up sequence from a connected inbox or verified sender. — `dench email sequence create` — POST /api/v1/email/sequences */
@@ -1856,7 +1867,12 @@ export interface ApiRequests {
1856
1867
  /** Enroll people from a CRM object: pick the object, the email field, and the entry ids. — `dench email sequence enroll-from-object` — POST /api/v1/email/sequences/{sequenceId}/enroll/from-object */
1857
1868
  "email.sequence.enrollFromObject": Record<string, unknown>;
1858
1869
  /** List a sequence's enrollments (paginated, optional status filter). — `dench email sequence enrollments list` — GET /api/v1/email/sequences/{sequenceId}/enrollments */
1859
- "email.sequence.enrollments.list": Record<string, unknown>;
1870
+ "email.sequence.enrollments.list": {
1871
+ sequenceId: string;
1872
+ limit?: number;
1873
+ cursor?: string;
1874
+ status?: string;
1875
+ };
1860
1876
  /** Pause one enrollment. — `dench email sequence enrollment pause` — POST /api/v1/email/sequences/enrollments/{enrollmentId}/pause */
1861
1877
  "email.sequence.enrollment.pause": Record<string, unknown>;
1862
1878
  /** Resume one paused enrollment. — `dench email sequence enrollment resume` — POST /api/v1/email/sequences/enrollments/{enrollmentId}/resume */
@@ -1918,6 +1934,14 @@ export interface ApiRequests {
1918
1934
  /** Days sends may go out: 0 = Sunday ... 6 = Saturday. */
1919
1935
  weekdays: number[];
1920
1936
  }[];
1937
+ /** Legacy single-window timezone. Prefer sendSchedules. */
1938
+ timezone?: string;
1939
+ /** Legacy single-window start hour. Prefer sendSchedules. */
1940
+ sendWindowStartHour?: number;
1941
+ /** Legacy single-window end hour. Prefer sendSchedules. */
1942
+ sendWindowEndHour?: number;
1943
+ /** Legacy single-window weekdays, 0 = Sunday. Prefer sendSchedules. */
1944
+ sendWeekdays?: number[];
1921
1945
  /** Cold emails per day, 1-100. */
1922
1946
  dailySendCap?: number;
1923
1947
  };
@@ -1976,6 +2000,11 @@ export interface ApiRequests {
1976
2000
  entryId?: string;
1977
2001
  sourceEntryId?: string;
1978
2002
  sourceObjectName?: string;
2003
+ emailIdentityId?: string;
2004
+ linkedinIdentityId?: string;
2005
+ linkedinProviderUserId?: string;
2006
+ /** CRM object a new record is created in when none matches. */
2007
+ newRecordsObject?: "lead" | "people";
1979
2008
  personalization?: Record<string, unknown>;
1980
2009
  checkDuplicatesAcrossWorkspace?: boolean;
1981
2010
  };
package/campaign.ts CHANGED
@@ -249,7 +249,7 @@ function shift(args: string[], expected: string): string {
249
249
  if (error instanceof CliArgError) throw new CampaignCliError(error.message);
250
250
  throw error;
251
251
  }
252
- if (value.startsWith("--")) {
252
+ if (isFlagToken(value)) {
253
253
  throw new CampaignCliError(
254
254
  `Missing ${expected}: it is positional, so write it before or after the flags, e.g. dench campaign get "Founder outreach" --json`,
255
255
  );
@@ -257,7 +257,17 @@ function shift(args: string[], expected: string): string {
257
257
  return value;
258
258
  }
259
259
 
260
+ function isFlagToken(value: string): boolean {
261
+ return value.startsWith("--") || /^-[A-Za-z]/.test(value);
262
+ }
263
+
260
264
  function unknownFlags(args: readonly string[], command: string): void {
265
+ const short = args.find((token) => /^-[A-Za-z]/.test(token));
266
+ if (short) {
267
+ throw new CampaignCliError(
268
+ `Unknown flag for ${command}: ${short}. Run \`dench campaign help\` for the full flag list.`,
269
+ );
270
+ }
261
271
  try {
262
272
  assertNoUnknownFlags(args, command);
263
273
  } catch (error) {
@@ -1298,11 +1308,17 @@ async function runGet(ctx: CampaignCliContext): Promise<void> {
1298
1308
  unknownFlags(ctx.args, "campaign get");
1299
1309
  const row = await resolveCampaign(ctx, reference);
1300
1310
  const sequenceId = String(row._id);
1311
+ let analyticsError: string | undefined;
1301
1312
  const [detail, analytics, live] = await Promise.all([
1302
1313
  loadDetail(ctx, sequenceId),
1303
- callAction(ctx, `${OUTREACH}:computeSequenceAnalytics`, {
1304
- sequenceId,
1305
- }) as Promise<CampaignAnalytics>,
1314
+ (
1315
+ callAction(ctx, `${OUTREACH}:computeSequenceAnalytics`, {
1316
+ sequenceId,
1317
+ }) as Promise<CampaignAnalytics>
1318
+ ).catch((error: unknown) => {
1319
+ analyticsError = error instanceof Error ? error.message : String(error);
1320
+ return null;
1321
+ }),
1306
1322
  callQuery(ctx, `${OUTREACH}:getSequenceLive`, {
1307
1323
  sequenceId,
1308
1324
  }) as Promise<CampaignLive>,
@@ -1324,6 +1340,11 @@ async function runGet(ctx: CampaignCliContext): Promise<void> {
1324
1340
  if (sequence.lastError) lines.push(`Last error: ${sequence.lastError}`);
1325
1341
 
1326
1342
  lines.push("", "Funnel");
1343
+ if (analyticsError) {
1344
+ lines.push(
1345
+ ` Funnel numbers are unavailable right now (${analyticsError}). Run dench campaign get again in a minute.`,
1346
+ );
1347
+ }
1327
1348
  const a = analytics ?? {};
1328
1349
  const audience = a.audience ?? detail.enrollments.length;
1329
1350
  lines.push(` Enrolled ${audience}`);
@@ -1418,7 +1439,11 @@ async function runGet(ctx: CampaignCliContext): Promise<void> {
1418
1439
  ` … ${enrollments.length - shown.length} more: dench campaign people <campaign>`,
1419
1440
  );
1420
1441
  }
1421
- out(ctx, { detail, analytics, live }, lines);
1442
+ out(
1443
+ ctx,
1444
+ { detail, analytics, live, ...(analyticsError ? { analyticsError } : {}) },
1445
+ lines,
1446
+ );
1422
1447
  }
1423
1448
 
1424
1449
  async function runSet(ctx: CampaignCliContext): Promise<void> {
@@ -1513,7 +1538,7 @@ async function runSteps(ctx: CampaignCliContext): Promise<void> {
1513
1538
  }
1514
1539
  if (row.status !== "draft") {
1515
1540
  throw new CampaignCliError(
1516
- "Steps can only change while a campaign is a draft. Duplicate it to edit steps.",
1541
+ "steps set only works while a campaign is a draft. After launch, edit a step's text or wait time in the Dench app (the step types and order stay fixed).",
1517
1542
  );
1518
1543
  }
1519
1544
  const raw = await readFile(file, "utf8").catch(() => {
@@ -1729,7 +1754,7 @@ async function runAdd(ctx: CampaignCliContext): Promise<void> {
1729
1754
  unknownFlags(ctx.args, "campaign add");
1730
1755
 
1731
1756
  const usage =
1732
- 'Usage: dench campaign add <campaign> --object <name> --view "<view>" | --object <name> --entries id1,id2 | --name "Ada" [--email ada@x.com] [--linkedin-url https://linkedin.com/in/ada]';
1757
+ 'Usage: dench campaign add <campaign> --object <name> --view "<view>" | --object <name> --entries id1,id2 | [--name "Ada"] --email ada@x.com and/or --linkedin-url https://linkedin.com/in/ada';
1733
1758
  const row = await resolveCampaign(ctx, reference);
1734
1759
  if (row.status === "archived") {
1735
1760
  throw new CampaignCliError(
@@ -1738,6 +1763,11 @@ async function runAdd(ctx: CampaignCliContext): Promise<void> {
1738
1763
  }
1739
1764
 
1740
1765
  if (objectName) {
1766
+ if (displayName) {
1767
+ throw new CampaignCliError(
1768
+ `--name adds one person and can't be combined with --object. Use --name-field <column> to pick the name column. ${usage}`,
1769
+ );
1770
+ }
1741
1771
  if (viewName && entriesRaw) {
1742
1772
  throw new CampaignCliError(
1743
1773
  `Pass either --view or --entries, not both. ${usage}`,
@@ -1782,7 +1812,7 @@ async function runAdd(ctx: CampaignCliContext): Promise<void> {
1782
1812
  if (collected.truncated) {
1783
1813
  warn(
1784
1814
  ctx,
1785
- `the view "${viewName}" has more rows than one read can list; only the first ${entryIds.length} were considered.`,
1815
+ `the view "${viewName}" could not be read in full; ${entryIds.length} of ${collected.totalCount} rows were considered. Split it into smaller views to add the rest.`,
1786
1816
  );
1787
1817
  }
1788
1818
  } else {
@@ -1979,14 +2009,32 @@ async function runLifecycle(
1979
2009
  ]);
1980
2010
  }
1981
2011
 
2012
+ const ENROLLMENT_STATUSES = [
2013
+ "draft",
2014
+ "active",
2015
+ "paused",
2016
+ "finished",
2017
+ "replied",
2018
+ "stopped",
2019
+ "bounced",
2020
+ "complained",
2021
+ "unsubscribed",
2022
+ "failed",
2023
+ ];
2024
+
1982
2025
  async function runPeople(ctx: CampaignCliContext): Promise<void> {
1983
- const status = valueFlag(ctx.args, "--status");
2026
+ const status = valueFlag(ctx.args, "--status")?.trim().toLowerCase();
1984
2027
  const reference = shift(ctx.args, "campaign id or name");
1985
2028
  unknownFlags(ctx.args, "campaign people");
2029
+ if (status !== undefined && !ENROLLMENT_STATUSES.includes(status)) {
2030
+ throw new CampaignCliError(
2031
+ `Unknown --status "${status}". Use one of: ${ENROLLMENT_STATUSES.join(", ")}.`,
2032
+ );
2033
+ }
1986
2034
  const row = await resolveCampaign(ctx, reference);
1987
2035
  const detail = await loadDetail(ctx, String(row._id));
1988
2036
  const enrollments = status
1989
- ? detail.enrollments.filter((e) => e.status === status.trim().toLowerCase())
2037
+ ? detail.enrollments.filter((e) => e.status === status)
1990
2038
  : detail.enrollments;
1991
2039
  const people = enrollments.map((enrollment) =>
1992
2040
  describePerson(enrollment, detail),
@@ -2307,8 +2355,45 @@ async function runAccounts(ctx: CampaignCliContext): Promise<void> {
2307
2355
 
2308
2356
  // ─── Help ─────────────────────────────────────────────────────────────────
2309
2357
 
2310
- export function campaignHelp(): void {
2311
- console.log(`Usage: dench campaign <subcommand> [--json]
2358
+ const SUBCOMMAND_ALIASES: Record<string, string> = {
2359
+ ls: "list",
2360
+ new: "create",
2361
+ status: "get",
2362
+ show: "get",
2363
+ update: "set",
2364
+ configure: "set",
2365
+ enroll: "add",
2366
+ start: "launch",
2367
+ activity: "events",
2368
+ senders: "accounts",
2369
+ };
2370
+
2371
+ export function campaignHelp(subcommand?: string): void {
2372
+ const text = campaignHelpText();
2373
+ const name = subcommand
2374
+ ? (SUBCOMMAND_ALIASES[subcommand] ?? subcommand)
2375
+ : undefined;
2376
+ const lines = text.split("\n");
2377
+ const usage: string[] = [];
2378
+ lines.forEach((line, index) => {
2379
+ if (!name || !line.startsWith(` dench campaign ${name} `)) return;
2380
+ usage.push(line);
2381
+ for (const next of lines.slice(index + 1)) {
2382
+ if (!next.startsWith(" ")) break;
2383
+ usage.push(next);
2384
+ }
2385
+ });
2386
+ if (!usage.length) {
2387
+ console.log(text);
2388
+ return;
2389
+ }
2390
+ console.log(
2391
+ `Usage:\n${usage.join("\n")}\n\n<campaign> is an id or an exact (case-insensitive) name. Run 'dench campaign help' for everything.`,
2392
+ );
2393
+ }
2394
+
2395
+ function campaignHelpText(): string {
2396
+ return `Usage: dench campaign <subcommand> [--json]
2312
2397
 
2313
2398
  Outreach campaigns send email and LinkedIn steps to a list of people on one
2314
2399
  schedule. <campaign> is an id or an exact (case-insensitive) name.
@@ -2316,7 +2401,7 @@ schedule. <campaign> is an id or an exact (case-insensitive) name.
2316
2401
  Browse:
2317
2402
  dench campaign list [--all] # live campaigns; --all includes archived
2318
2403
  dench campaign get <campaign> # status, schedule, funnel, Now/Next, holds, people
2319
- dench campaign people <campaign> [--status active|paused|finished|replied|stopped|bounced|failed]
2404
+ dench campaign people <campaign> [--status active|paused|finished|replied|stopped|bounced|failed|draft|complained|unsubscribed]
2320
2405
  dench campaign events <campaign> [--limit 50] [--max-pages 1] # activity log, newest first
2321
2406
  dench campaign accounts # email + LinkedIn sender ids, availability and capacity
2322
2407
 
@@ -2332,9 +2417,10 @@ Create and configure:
2332
2417
  dench campaign steps set <campaign> --file steps.json # replaces every step; drafts only
2333
2418
 
2334
2419
  Fill it:
2335
- dench campaign add <campaign> --object lead --view "Q3 targets" [--email-field Email] [--linkedin-field "POC LinkedIn URL"] [--allow-duplicates]
2420
+ dench campaign add <campaign> --object lead --view "Q3 targets" [--email-field Email] [--linkedin-field "POC LinkedIn URL"] \\
2421
+ [--name-field Name] [--allow-duplicates]
2336
2422
  dench campaign add <campaign> --object people --entries id1,id2 [--relation-field Contact] [--reverse]
2337
- dench campaign add <campaign> --name "Ada Lovelace" [--email ada@x.com] [--linkedin-url https://linkedin.com/in/ada]
2423
+ dench campaign add <campaign> [--name "Ada Lovelace"] --email ada@x.com and/or --linkedin-url https://linkedin.com/in/ada
2338
2424
 
2339
2425
  Run it:
2340
2426
  dench campaign launch <campaign> [--ack-linkedin-risk] # checks readiness first; prints blockers
@@ -2360,13 +2446,14 @@ leave that channel unchanged. Only your accounts and accounts shared with you
2360
2446
  can be selected. Launch checks availability. A person's sender stays fixed for
2361
2447
  their conversation. Legacy step senders are preserved until a pool is configured.
2362
2448
 
2363
- A campaign holds at most ${MAX_CAMPAIGN_PEOPLE} people. Steps lock at launch; the schedule,
2364
- daily cap and stop-on-reply stay editable. Leads move New → Contacted → Replied
2449
+ A campaign holds at most ${MAX_CAMPAIGN_PEOPLE} people. steps set only works on drafts. After
2450
+ launch, edit a step's text or wait time in the Dench app; the schedule,
2451
+ daily cap and stop-on-reply stay editable here. Leads move New → Contacted → Replied
2365
2452
  on their own as steps go out.
2366
2453
 
2367
2454
  Auth: a workspace member's credentials (dench signin, a member DENCH_API_KEY, or
2368
2455
  an agent session). An organization-only key cannot run outreach.
2369
- `);
2456
+ `;
2370
2457
  }
2371
2458
 
2372
2459
  // ─── Entry point ──────────────────────────────────────────────────────────
@@ -2395,6 +2482,10 @@ export async function runCampaignCommand(opts: {
2395
2482
  campaignHelp();
2396
2483
  return;
2397
2484
  }
2485
+ if (args.some((token) => token === "--help" || token === "-h")) {
2486
+ campaignHelp(subcommand);
2487
+ return;
2488
+ }
2398
2489
  switch (subcommand) {
2399
2490
  case "list":
2400
2491
  case "ls":
package/dench.ts CHANGED
@@ -373,7 +373,7 @@ function normalizeCliError(error: unknown): CliError {
373
373
  ],
374
374
  });
375
375
  }
376
- if (message.includes("Sign in as a workspace member to run outreach")) {
376
+ if (message.includes("Sign in as a workspace member to")) {
377
377
  return new CliError(
378
378
  "Outreach needs a workspace member's credentials — sending accounts belong to a person, not the workspace",
379
379
  {
@@ -4905,6 +4905,11 @@ async function main() {
4905
4905
  await runToolCommand({ args: filteredSubArgs, jsonOutput: json });
4906
4906
  return;
4907
4907
  }
4908
+ if (sub === "run") {
4909
+ const { parseJson } = await import("./lib/cli-args");
4910
+ const argsIndex = filteredSubArgs.indexOf("--args");
4911
+ if (argsIndex !== -1) parseJson(filteredSubArgs[argsIndex + 1]);
4912
+ }
4908
4913
  const runtime = await getRuntime();
4909
4914
  const isSlackConnect =
4910
4915
  sub === "connect" &&
@@ -5105,7 +5110,11 @@ async function main() {
5105
5110
  if (command === "campaign" || command === "campaigns") {
5106
5111
  const subArgs = stripRuntimeFlags(args.slice(args.indexOf(command) + 1));
5107
5112
  const sub = subArgs[0];
5108
- if (!sub || sub === "help" || sub === "--help" || sub === "-h") {
5113
+ if (
5114
+ !sub ||
5115
+ sub === "help" ||
5116
+ subArgs.some((token) => token === "--help" || token === "-h")
5117
+ ) {
5109
5118
  const { runCampaignCommand } = await import("./campaign");
5110
5119
  // biome-ignore lint/suspicious/noExplicitAny: help-only stub, never queries
5111
5120
  await runCampaignCommand({ convex: {} as any, args: subArgs });
@@ -2382,6 +2382,31 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
2382
2382
  .optional()
2383
2383
  .describe("Epoch ms; null clears the end."),
2384
2384
  sendSchedules: z.array(campaignSendSchedule).min(1).max(8).optional(),
2385
+ timezone: z
2386
+ .string()
2387
+ .optional()
2388
+ .describe("Legacy single-window timezone. Prefer sendSchedules."),
2389
+ sendWindowStartHour: z
2390
+ .number()
2391
+ .int()
2392
+ .min(0)
2393
+ .max(23)
2394
+ .optional()
2395
+ .describe("Legacy single-window start hour. Prefer sendSchedules."),
2396
+ sendWindowEndHour: z
2397
+ .number()
2398
+ .int()
2399
+ .min(1)
2400
+ .max(24)
2401
+ .optional()
2402
+ .describe("Legacy single-window end hour. Prefer sendSchedules."),
2403
+ sendWeekdays: z
2404
+ .array(z.number().int().min(0).max(6))
2405
+ .min(1)
2406
+ .optional()
2407
+ .describe(
2408
+ "Legacy single-window weekdays, 0 = Sunday. Prefer sendSchedules.",
2409
+ ),
2385
2410
  dailySendCap: z
2386
2411
  .number()
2387
2412
  .int()
@@ -2430,6 +2455,13 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
2430
2455
  .describe("Existing CRM people entry to link."),
2431
2456
  sourceEntryId: z.string().optional(),
2432
2457
  sourceObjectName: z.string().optional(),
2458
+ emailIdentityId: z.string().optional(),
2459
+ linkedinIdentityId: z.string().optional(),
2460
+ linkedinProviderUserId: z.string().optional(),
2461
+ newRecordsObject: z
2462
+ .enum(["lead", "people"])
2463
+ .optional()
2464
+ .describe("CRM object a new record is created in when none matches."),
2433
2465
  personalization: z.record(z.string(), z.unknown()).optional(),
2434
2466
  checkDuplicatesAcrossWorkspace: z.boolean().optional(),
2435
2467
  }),
@@ -3591,6 +3623,27 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
3591
3623
  "email.campaign.pause": z.object({ campaignId: z.string() }),
3592
3624
  "email.campaign.resume": z.object({ campaignId: z.string() }),
3593
3625
  "email.campaign.cancel": z.object({ campaignId: z.string() }),
3626
+ "email.campaign.list": z.object({
3627
+ limit: z.coerce.number().int().min(1).max(100).optional(),
3628
+ cursor: z.coerce.string().optional(),
3629
+ status: z.string().optional(),
3630
+ }),
3631
+ "email.campaign.recipients.list": z.object({
3632
+ campaignId: z.string(),
3633
+ limit: z.coerce.number().int().min(1).max(100).optional(),
3634
+ cursor: z.coerce.string().optional(),
3635
+ status: z.string().optional(),
3636
+ includePeople: z
3637
+ .boolean()
3638
+ .optional()
3639
+ .describe("Default true: attach each recipient's CRM record."),
3640
+ }),
3641
+ "email.sequence.enrollments.list": z.object({
3642
+ sequenceId: z.string(),
3643
+ limit: z.coerce.number().int().min(1).max(100).optional(),
3644
+ cursor: z.coerce.string().optional(),
3645
+ status: z.string().optional(),
3646
+ }),
3594
3647
 
3595
3648
  // Routines
3596
3649
  "cron.list": z.object({ enabledOnly: z.coerce.boolean().optional() }),
@@ -5174,6 +5227,12 @@ export const requestExamples: Record<string, unknown> = {
5174
5227
  objectName: "lead",
5175
5228
  entryIds: ["<entryId1>", "<entryId2>"],
5176
5229
  },
5230
+ "campaigns.people.add": {
5231
+ sequenceId: "<sequenceId>",
5232
+ displayName: "Ada Lovelace",
5233
+ email: "ada@example.com",
5234
+ linkedinProfileUrl: "https://linkedin.com/in/ada",
5235
+ },
5177
5236
  "campaigns.launch": {
5178
5237
  sequenceId: "<sequenceId>",
5179
5238
  fingerprint: "<fingerprint from the launch preview>",
@@ -3254,7 +3254,13 @@ const rawApiOperations = [
3254
3254
  path: "/email/campaigns",
3255
3255
  requestSchema: anyObject,
3256
3256
  responseSchema: anyResponse,
3257
- backend: convex("query", "functions/emailCampaigns:listCampaigns"),
3257
+ backend: {
3258
+ ...convex("query", "functions/emailCampaigns:listCampaigns"),
3259
+ transformArgs: (input) => ({
3260
+ status: input.status,
3261
+ paginationOpts: paginationOptsFrom(input, 25),
3262
+ }),
3263
+ },
3258
3264
  }),
3259
3265
  op({
3260
3266
  id: "email.campaign.recipients.list",
@@ -3266,7 +3272,15 @@ const rawApiOperations = [
3266
3272
  path: "/email/campaigns/{campaignId}/recipients",
3267
3273
  requestSchema: anyObject,
3268
3274
  responseSchema: anyResponse,
3269
- backend: convex("query", "functions/emailCampaigns:listRecipients"),
3275
+ backend: {
3276
+ ...convex("query", "functions/emailCampaigns:listRecipients"),
3277
+ transformArgs: (input) => ({
3278
+ campaignId: input.campaignId,
3279
+ status: input.status,
3280
+ includePeople: input.includePeople,
3281
+ paginationOpts: paginationOptsFrom(input, 50),
3282
+ }),
3283
+ },
3270
3284
  }),
3271
3285
  op({
3272
3286
  id: "email.campaign.recipients.addFromObject",
@@ -3446,7 +3460,14 @@ const rawApiOperations = [
3446
3460
  path: "/email/sequences/{sequenceId}/enrollments",
3447
3461
  requestSchema: anyObject,
3448
3462
  responseSchema: anyResponse,
3449
- backend: convex("query", "functions/emailSequences:listEnrollments"),
3463
+ backend: {
3464
+ ...convex("query", "functions/emailSequences:listEnrollments"),
3465
+ transformArgs: (input) => ({
3466
+ sequenceId: input.sequenceId,
3467
+ status: input.status,
3468
+ paginationOpts: paginationOptsFrom(input, 50),
3469
+ }),
3470
+ },
3450
3471
  }),
3451
3472
  op({
3452
3473
  id: "email.sequence.enrollment.pause",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dench.com/cli",
3
- "version": "3.5.5",
3
+ "version": "3.5.6-staging.344",
4
4
  "description": "Dench agent workspace CLI.",
5
5
  "type": "module",
6
6
  "bin": {