@erdoai/cli 0.65.0 → 0.66.0

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.
Files changed (2) hide show
  1. package/dist/index.js +88 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -396,6 +396,22 @@ var ErdoClient = class {
396
396
  `/v1/received-emails${qs ? `?${qs}` : ""}`
397
397
  );
398
398
  }
399
+ // The audited outbound side of email. Listing omits bodies; get reads the
400
+ // exact stored message. The scalar filters use the GET mirror of the same
401
+ // service that backs MCP's erdo_list_emails.
402
+ listSentEmails(params) {
403
+ const q = new URLSearchParams();
404
+ if (params?.to) q.set("to", params.to);
405
+ if (params?.since) q.set("since", params.since);
406
+ if (params?.search) q.set("search", params.search);
407
+ if (params?.limit) q.set("limit", String(params.limit));
408
+ if (params?.offset) q.set("offset", String(params.offset));
409
+ const qs = q.toString();
410
+ return this.request("GET", `/v1/emails${qs ? `?${qs}` : ""}`);
411
+ }
412
+ getSentEmail(emailID) {
413
+ return this.request("GET", `/v1/emails/${encodeURIComponent(emailID)}`);
414
+ }
399
415
  // Run a read-only HogQL query against the org's page-analytics events. Rows are
400
416
  // positional per columns; enabled:false means page analytics is off for the org
401
417
  // (not zero traffic). A rejected query surfaces PostHog's message as the error.
@@ -514,6 +530,14 @@ var ErdoClient = class {
514
530
  `/v1/pages/restore/${encodeURIComponent(id)}`
515
531
  );
516
532
  }
533
+ // Copy a page: the deploy endpoint's clone mode. clone_from_page_id makes
534
+ // POST /v1/pages copy an existing page server-side instead of taking content.
535
+ clonePage(id, input) {
536
+ return this.request("POST", "/v1/pages", {
537
+ clone_from_page_id: id,
538
+ title: input?.title
539
+ });
540
+ }
517
541
  // --- workstreams ---
518
542
  listWorkstreams(status) {
519
543
  const q = new URLSearchParams();
@@ -3807,6 +3831,24 @@ pagesCmd.command("restore <id>").description("Restore a previously deleted page
3807
3831
  fail(e);
3808
3832
  }
3809
3833
  });
3834
+ pagesCmd.command("clone <id>").description(
3835
+ "Copy a page. The copy is byte-identical and starts private (publish state is never inherited); the source's lead-form pipelines are duplicated onto it and the ids in its content rewritten, so it captures its own leads"
3836
+ ).option("--title <title>", 'title for the copy (default: "Copy of <source title>")').option("--json", "print the full JSON, including the cloned pipelines and id rewrites").action(async (id, opts) => {
3837
+ try {
3838
+ const res = await new ErdoClient().clonePage(id, { title: opts.title });
3839
+ if (opts.json) {
3840
+ print(res);
3841
+ return;
3842
+ }
3843
+ console.log(`${res.id} ${res.url}`);
3844
+ for (const p of res.cloned_pipelines || []) {
3845
+ console.error(`cloned pipeline: ${p.source_id} -> ${p.id}${p.slug ? ` (${p.slug})` : ""}`);
3846
+ }
3847
+ for (const note of res.notes || []) console.error(`note: ${note}`);
3848
+ } catch (e) {
3849
+ fail(e);
3850
+ }
3851
+ });
3810
3852
  pagesCmd.command("get <id>").description("Show an artifact").action(async (id) => {
3811
3853
  try {
3812
3854
  print(await new ErdoClient().getArtifact(id));
@@ -4079,6 +4121,52 @@ emailCmd.command("received").description(
4079
4121
  fail(e);
4080
4122
  }
4081
4123
  });
4124
+ var sentEmailsCmd = emailCmd.command("sent").description("Read the audited outbound email log and provider delivery evidence");
4125
+ sentEmailsCmd.command("list").description("List sent email, newest first, including immutable delivered_at evidence").option("--to <email>", "only mail sent to this address").option("--since <timestamp>", "only mail created at or after this RFC 3339 timestamp").option("--search <text>", "case-insensitive subject substring").option("--limit <n>", "page size (default 25, max 200)").option("--offset <n>", "rows to skip").option("--json", "print the raw JSON result instead of a table").action(
4126
+ async (opts) => {
4127
+ try {
4128
+ const res = await new ErdoClient().listSentEmails({
4129
+ to: opts.to,
4130
+ since: opts.since,
4131
+ search: opts.search,
4132
+ limit: opts.limit ? Number(opts.limit) : void 0,
4133
+ offset: opts.offset ? Number(opts.offset) : void 0
4134
+ });
4135
+ if (opts.json) {
4136
+ print(res);
4137
+ return;
4138
+ }
4139
+ const emails = res.emails ?? [];
4140
+ if (emails.length === 0) {
4141
+ console.log("No sent email matches those filters.");
4142
+ return;
4143
+ }
4144
+ printAlignedTable(
4145
+ ["id", "to", "subject", "status", "delivered at", "latest event", "sent at"],
4146
+ emails.map((email) => [
4147
+ email.id,
4148
+ email.to,
4149
+ email.subject,
4150
+ email.status_reason ? `${email.status}: ${email.status_reason}` : email.status,
4151
+ email.delivered_at ?? "",
4152
+ email.last_delivery_event_at ?? "",
4153
+ email.sent_at ?? ""
4154
+ ])
4155
+ );
4156
+ process.stderr.write(`showing ${emails.length} of ${res.total} matching message(s)
4157
+ `);
4158
+ } catch (e) {
4159
+ fail(e);
4160
+ }
4161
+ }
4162
+ );
4163
+ sentEmailsCmd.command("get <emailID>").description("Read one sent email, including exact bodies and delivery evidence").action(async (emailID) => {
4164
+ try {
4165
+ print(await new ErdoClient().getSentEmail(emailID));
4166
+ } catch (e) {
4167
+ fail(e);
4168
+ }
4169
+ });
4082
4170
  var datasetsCmd = program.command("datasets").description("Datasets");
4083
4171
  datasetsCmd.command("list").description("List datasets").option(
4084
4172
  "--class <class>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.65.0",
3
+ "version": "0.66.0",
4
4
  "description": "Erdo CLI — drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {