posthorn 0.2.3 → 0.2.4

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 (3) hide show
  1. package/README.md +10 -0
  2. package/dist/index.js +79 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -152,6 +152,16 @@ Anonymous tier can do setup (accounts, domains). To send/warmup, verify:
152
152
  - `posthorn warmup list` → all campaigns
153
153
  - Warmup never fully stops on its own — pause with `posthorn warmup pause <id>`.
154
154
 
155
+ ## Feedback (bugs, feature requests)
156
+
157
+ `posthorn feedback --type bug|feature|question|other "<message>"`
158
+
159
+ If you hit a bug, missing capability, or rough edge while driving this CLI,
160
+ report it — it goes straight to the Posthorn team. Agents: you are encouraged
161
+ to file feedback yourself when something doesn't work the way you expected
162
+ (include the command you ran and what you expected). Works on any tier, no
163
+ verification needed.
164
+
155
165
  ## Tips for agents
156
166
 
157
167
  - Read commands auto-detect output: when stdout isn't a TTY (i.e. you're an agent
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk6 from "chalk";
5
+ import chalk7 from "chalk";
6
6
 
7
7
  // src/commands/auth.ts
8
8
  import chalk from "chalk";
@@ -158,6 +158,21 @@ async function api(path, options = {}) {
158
158
  }
159
159
 
160
160
  // src/commands/accounts.ts
161
+ var SERVICE_ACCOUNT_CLIENT_ID = "110137377718772968374";
162
+ var DELEGATION_SCOPES = "https://mail.google.com/,https://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.domain,https://www.googleapis.com/auth/siteverification";
163
+ function printDelegationHelp(adminEmail) {
164
+ const domain = adminEmail.includes("@") ? adminEmail.split("@")[1] : "your-domain.com";
165
+ console.log();
166
+ console.log(chalk2.bold(" Set up domain-wide delegation first (one-time per Workspace org):"));
167
+ console.log(` 1. Go to ${chalk2.cyan("admin.google.com")} signed in as a ${chalk2.bold("super-admin")} of ${chalk2.bold(domain)}`);
168
+ console.log(" 2. Security \u2192 Access and data control \u2192 API controls \u2192 Domain-wide delegation \u2192 Add new");
169
+ console.log(` 3. Client ID: ${chalk2.bold(SERVICE_ACCOUNT_CLIENT_ID)}`);
170
+ console.log(" 4. OAuth scopes (paste all, comma-separated):");
171
+ console.log(` ${chalk2.green(DELEGATION_SCOPES)}`);
172
+ console.log(" 5. Authorize, then re-run this command.");
173
+ console.log(chalk2.dim(` The admin email you pass must be a super-admin of ${domain}'s own org.`));
174
+ console.log();
175
+ }
161
176
  async function connectCloudflare(token, options) {
162
177
  const spinner = ora2("Connecting Cloudflare...").start();
163
178
  const data = await api("/api/accounts", {
@@ -183,10 +198,21 @@ async function connectCloudflare(token, options) {
183
198
  }
184
199
  async function connectWorkspace(adminEmail) {
185
200
  const spinner = ora2("Connecting Google Workspace...").start();
186
- const data = await api("/api/accounts/workspace", {
187
- method: "POST",
188
- body: { adminEmail }
189
- });
201
+ let data;
202
+ try {
203
+ data = await api("/api/accounts/workspace", {
204
+ method: "POST",
205
+ body: { adminEmail }
206
+ });
207
+ } catch (err) {
208
+ spinner.fail("Could not connect Google Workspace.");
209
+ if (err instanceof ApiError) {
210
+ console.log(chalk2.red(` ${err.message}`));
211
+ }
212
+ printDelegationHelp(adminEmail);
213
+ process.exitCode = 1;
214
+ return;
215
+ }
190
216
  setConfig({
191
217
  workspaceConnected: true,
192
218
  workspaceAccountId: data.account.id
@@ -493,14 +519,53 @@ async function listCampaigns() {
493
519
  }
494
520
  }
495
521
 
496
- // src/commands/guide.ts
522
+ // src/commands/feedback.ts
497
523
  import { readFileSync } from "fs";
498
524
  import { fileURLToPath } from "url";
499
525
  import { dirname, join } from "path";
500
- function guide() {
526
+ import chalk6 from "chalk";
527
+ function cliVersion() {
501
528
  try {
502
529
  const here = dirname(fileURLToPath(import.meta.url));
503
- const readme = readFileSync(join(here, "..", "README.md"), "utf8");
530
+ return JSON.parse(readFileSync(join(here, "..", "package.json"), "utf8")).version;
531
+ } catch {
532
+ return "unknown";
533
+ }
534
+ }
535
+ async function sendFeedback(messageWords, options) {
536
+ const message = messageWords.join(" ").trim();
537
+ if (!message) {
538
+ console.error(chalk6.red("Feedback message is required."));
539
+ console.error(chalk6.dim(' Example: posthorn feedback --type feature "bulk domain checks would save me round trips"'));
540
+ process.exitCode = 1;
541
+ return;
542
+ }
543
+ const data = await api("/api/feedback", {
544
+ method: "POST",
545
+ body: {
546
+ message,
547
+ type: options.type ?? "other",
548
+ metadata: {
549
+ cliVersion: cliVersion(),
550
+ platform: process.platform,
551
+ agent: !process.stdout.isTTY
552
+ // non-TTY usually means an agent is driving
553
+ }
554
+ }
555
+ });
556
+ console.log(chalk6.green("Feedback recorded \u2014 thank you!"));
557
+ console.log(` id: ${chalk6.dim(data.feedback.id)}`);
558
+ console.log(` type: ${chalk6.dim(data.feedback.type)}`);
559
+ }
560
+
561
+ // src/commands/guide.ts
562
+ import { readFileSync as readFileSync2 } from "fs";
563
+ import { fileURLToPath as fileURLToPath2 } from "url";
564
+ import { dirname as dirname2, join as join2 } from "path";
565
+ function guide() {
566
+ try {
567
+ const here = dirname2(fileURLToPath2(import.meta.url));
568
+ const readme = readFileSync2(join2(here, "..", "README.md"), "utf8");
504
569
  console.log(readme);
505
570
  } catch {
506
571
  console.log(
@@ -511,7 +576,7 @@ function guide() {
511
576
 
512
577
  // src/index.ts
513
578
  var program = new Command();
514
- program.name("posthorn").description("Posthorn \u2014 domain setup, mailbox creation, and email warmup").version("0.1.0");
579
+ program.name("posthorn").description("Posthorn \u2014 domain setup, mailbox creation, and email warmup").version("0.2.4");
515
580
  program.addHelpText("after", `
516
581
  Agents: run 'posthorn guide' first for the full workflow playbook.
517
582
 
@@ -557,17 +622,18 @@ warmup.command("list").description("List warmup campaigns").action(listCampaigns
557
622
  warmup.command("start <mailbox-id>").description("Start warming a mailbox").action(startWarmup);
558
623
  warmup.command("pause <campaign-id>").description("Pause a warmup campaign").action(pauseWarmup);
559
624
  warmup.command("stats <campaign-id>").description("Show warmup stats and daily breakdown").option("--json", "Force JSON output").option("--pretty", "Force human-readable output").action(warmupStats);
625
+ program.command("feedback <message...>").description("Send feedback to the Posthorn team \u2014 bug reports, feature requests, anything").option("-t, --type <type>", "bug | feature | question | other", "other").action(sendFeedback);
560
626
  program.hook("preAction", () => {
561
627
  });
562
628
  program.parseAsync(process.argv).catch((err) => {
563
629
  if (err.statusCode === 401) {
564
- console.log(chalk6.red("\n Authentication failed. Run: posthorn auth register\n"));
630
+ console.log(chalk7.red("\n Authentication failed. Run: posthorn auth register\n"));
565
631
  } else if (err.statusCode === 403) {
566
- console.log(chalk6.red("\n Account not verified. Run: posthorn auth verify\n"));
632
+ console.log(chalk7.red("\n Account not verified. Run: posthorn auth verify\n"));
567
633
  } else if (err.statusCode === 429) {
568
- console.log(chalk6.yellow("\n Rate limit exceeded. Try again in a minute.\n"));
634
+ console.log(chalk7.yellow("\n Rate limit exceeded. Try again in a minute.\n"));
569
635
  } else {
570
- console.error(chalk6.red(`
636
+ console.error(chalk7.red(`
571
637
  Error: ${err.message}
572
638
  `));
573
639
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthorn",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Posthorn — domain setup, mailbox creation, and email warmup from the command line",
5
5
  "type": "module",
6
6
  "bin": {