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.
- package/README.md +10 -0
- package/dist/index.js +79 -13
- 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
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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/
|
|
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
|
-
|
|
526
|
+
import chalk6 from "chalk";
|
|
527
|
+
function cliVersion() {
|
|
501
528
|
try {
|
|
502
529
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
503
|
-
|
|
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.
|
|
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(
|
|
630
|
+
console.log(chalk7.red("\n Authentication failed. Run: posthorn auth register\n"));
|
|
565
631
|
} else if (err.statusCode === 403) {
|
|
566
|
-
console.log(
|
|
632
|
+
console.log(chalk7.red("\n Account not verified. Run: posthorn auth verify\n"));
|
|
567
633
|
} else if (err.statusCode === 429) {
|
|
568
|
-
console.log(
|
|
634
|
+
console.log(chalk7.yellow("\n Rate limit exceeded. Try again in a minute.\n"));
|
|
569
635
|
} else {
|
|
570
|
-
console.error(
|
|
636
|
+
console.error(chalk7.red(`
|
|
571
637
|
Error: ${err.message}
|
|
572
638
|
`));
|
|
573
639
|
}
|