agenticmail 0.3.4 → 0.3.6
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/dist/cli.js +164 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -580,7 +580,7 @@ async function interactiveShell(options) {
|
|
|
580
580
|
}
|
|
581
581
|
},
|
|
582
582
|
agents: {
|
|
583
|
-
desc: "List
|
|
583
|
+
desc: "List agents or create a new one",
|
|
584
584
|
run: async () => {
|
|
585
585
|
log("");
|
|
586
586
|
try {
|
|
@@ -593,7 +593,7 @@ async function interactiveShell(options) {
|
|
|
593
593
|
const data = await resp.json();
|
|
594
594
|
const agents = data.agents || data || [];
|
|
595
595
|
if (agents.length === 0) {
|
|
596
|
-
info("No agents yet.
|
|
596
|
+
info("No agents yet.");
|
|
597
597
|
} else {
|
|
598
598
|
for (const agent of agents) {
|
|
599
599
|
const owner = agent.metadata?.ownerName;
|
|
@@ -607,6 +607,68 @@ async function interactiveShell(options) {
|
|
|
607
607
|
info("Use /switch to change active agent");
|
|
608
608
|
}
|
|
609
609
|
}
|
|
610
|
+
log("");
|
|
611
|
+
log(` ${c.green("[1]")} Create new agent`);
|
|
612
|
+
log(` ${c.green("[2]")} Back`);
|
|
613
|
+
log("");
|
|
614
|
+
const choice = await question(` ${c.dim(">")}: `);
|
|
615
|
+
if (isBack(choice) || choice.trim() === "2") {
|
|
616
|
+
log("");
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (choice.trim() !== "1") {
|
|
620
|
+
log("");
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
log("");
|
|
624
|
+
const nameInput = await question(` ${c.cyan("Agent name:")} `);
|
|
625
|
+
if (isBack(nameInput) || !nameInput.trim()) {
|
|
626
|
+
log("");
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const agentName = nameInput.trim();
|
|
630
|
+
log("");
|
|
631
|
+
log(` ${c.bold("Role")}`);
|
|
632
|
+
log(` ${c.green("[1]")} secretary ${c.dim("(default)")}`);
|
|
633
|
+
log(` ${c.green("[2]")} assistant`);
|
|
634
|
+
log(` ${c.green("[3]")} researcher`);
|
|
635
|
+
log(` ${c.green("[4]")} writer`);
|
|
636
|
+
log(` ${c.green("[5]")} custom`);
|
|
637
|
+
log("");
|
|
638
|
+
const roleChoice = await question(` ${c.dim(">")}: `);
|
|
639
|
+
if (isBack(roleChoice)) {
|
|
640
|
+
log("");
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const roles = ["secretary", "assistant", "researcher", "writer", "custom"];
|
|
644
|
+
const roleIdx = parseInt(roleChoice.trim()) - 1;
|
|
645
|
+
const role = roleIdx >= 0 && roleIdx < roles.length ? roles[roleIdx] : "secretary";
|
|
646
|
+
log("");
|
|
647
|
+
info("Creating agent...");
|
|
648
|
+
const createResp = await apiFetch("/api/agenticmail/accounts", {
|
|
649
|
+
method: "POST",
|
|
650
|
+
body: JSON.stringify({ name: agentName, role }),
|
|
651
|
+
signal: AbortSignal.timeout(15e3)
|
|
652
|
+
});
|
|
653
|
+
if (!createResp.ok) {
|
|
654
|
+
const text = await createResp.text();
|
|
655
|
+
let parsed = {};
|
|
656
|
+
try {
|
|
657
|
+
parsed = JSON.parse(text);
|
|
658
|
+
} catch {
|
|
659
|
+
}
|
|
660
|
+
fail(parsed.error || text);
|
|
661
|
+
log("");
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const created = await createResp.json();
|
|
665
|
+
ok(`Agent ${c.bold('"' + created.name + '"')} created!`);
|
|
666
|
+
log(` ${c.dim("Email:")} ${c.cyan(created.email || created.subAddress || "")}`);
|
|
667
|
+
log(` ${c.dim("Key:")} ${c.yellow(created.apiKey)}`);
|
|
668
|
+
log(` ${c.dim("Role:")} ${role}`);
|
|
669
|
+
currentAgent = { name: created.name, email: created.email || created.subAddress, apiKey: created.apiKey };
|
|
670
|
+
ok(`Switched to ${c.bold(created.name)}`);
|
|
671
|
+
log("");
|
|
610
672
|
} catch (err) {
|
|
611
673
|
fail(`Error: ${errMsg(err)}`);
|
|
612
674
|
}
|
|
@@ -3356,10 +3418,108 @@ ${c.dim(boxChar.bl + boxChar.h.repeat(bWidth) + boxChar.br)}`);
|
|
|
3356
3418
|
}
|
|
3357
3419
|
},
|
|
3358
3420
|
setup: {
|
|
3359
|
-
desc: "
|
|
3421
|
+
desc: "Set up email connection",
|
|
3360
3422
|
run: async () => {
|
|
3361
3423
|
log("");
|
|
3362
|
-
|
|
3424
|
+
log(` ${c.bold("Email Setup")}`);
|
|
3425
|
+
log("");
|
|
3426
|
+
log(` ${c.cyan("1.")} Gmail`);
|
|
3427
|
+
log(` ${c.cyan("2.")} Outlook / Hotmail`);
|
|
3428
|
+
log(` ${c.cyan("3.")} Skip`);
|
|
3429
|
+
log("");
|
|
3430
|
+
const provChoice = await question(` ${c.dim(">")}: `);
|
|
3431
|
+
if (isBack(provChoice)) {
|
|
3432
|
+
log("");
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3435
|
+
const ch = provChoice.trim();
|
|
3436
|
+
if (ch === "3") {
|
|
3437
|
+
info("Skipped. You can run /setup anytime.");
|
|
3438
|
+
log("");
|
|
3439
|
+
return;
|
|
3440
|
+
}
|
|
3441
|
+
let provider;
|
|
3442
|
+
if (ch === "1") provider = "gmail";
|
|
3443
|
+
else if (ch === "2") provider = "outlook";
|
|
3444
|
+
else {
|
|
3445
|
+
fail("Invalid choice.");
|
|
3446
|
+
log("");
|
|
3447
|
+
return;
|
|
3448
|
+
}
|
|
3449
|
+
const email = await question(` ${c.cyan("Your email address:")} `);
|
|
3450
|
+
if (isBack(email) || !email.trim()) {
|
|
3451
|
+
log("");
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
log("");
|
|
3455
|
+
if (provider === "gmail") {
|
|
3456
|
+
info("You need a Gmail App Password.");
|
|
3457
|
+
info(`Go to ${c.cyan("https://myaccount.google.com/apppasswords")}`);
|
|
3458
|
+
info("Create one and paste it below (spaces are fine).");
|
|
3459
|
+
} else {
|
|
3460
|
+
info("You need an Outlook App Password from your account security settings.");
|
|
3461
|
+
}
|
|
3462
|
+
log("");
|
|
3463
|
+
const agentNameInput = await question(` ${c.cyan("Agent name")} ${c.dim("(secretary)")}: `);
|
|
3464
|
+
if (isBack(agentNameInput)) {
|
|
3465
|
+
log("");
|
|
3466
|
+
return;
|
|
3467
|
+
}
|
|
3468
|
+
const agentName = agentNameInput.trim() || "secretary";
|
|
3469
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
3470
|
+
const rawPassword = await question(` ${c.cyan("App password:")} `);
|
|
3471
|
+
if (isBack(rawPassword)) {
|
|
3472
|
+
log("");
|
|
3473
|
+
return;
|
|
3474
|
+
}
|
|
3475
|
+
const password = rawPassword.replace(/\s+/g, "");
|
|
3476
|
+
if (!password) {
|
|
3477
|
+
fail("Password cannot be empty.");
|
|
3478
|
+
continue;
|
|
3479
|
+
}
|
|
3480
|
+
log("");
|
|
3481
|
+
info("Connecting...");
|
|
3482
|
+
try {
|
|
3483
|
+
const resp = await apiFetch("/api/agenticmail/gateway/relay", {
|
|
3484
|
+
method: "POST",
|
|
3485
|
+
body: JSON.stringify({ provider, email: email.trim(), password, agentName }),
|
|
3486
|
+
signal: AbortSignal.timeout(3e4)
|
|
3487
|
+
});
|
|
3488
|
+
if (!resp.ok) {
|
|
3489
|
+
const text = await resp.text();
|
|
3490
|
+
let parsed = {};
|
|
3491
|
+
try {
|
|
3492
|
+
parsed = JSON.parse(text);
|
|
3493
|
+
} catch {
|
|
3494
|
+
}
|
|
3495
|
+
const error = parsed.error || text;
|
|
3496
|
+
const isAuth = /Username and Password not accepted|Invalid login|Authentication failed|AUTHENTICATIONFAILED|Invalid credentials|535/.test(error);
|
|
3497
|
+
if (isAuth && attempt < 3) {
|
|
3498
|
+
fail("Incorrect email or password.");
|
|
3499
|
+
info(`Let's try again. (attempt ${attempt} of 3)`);
|
|
3500
|
+
log("");
|
|
3501
|
+
continue;
|
|
3502
|
+
}
|
|
3503
|
+
fail(error.slice(0, 200));
|
|
3504
|
+
log("");
|
|
3505
|
+
return;
|
|
3506
|
+
}
|
|
3507
|
+
const data = await resp.json();
|
|
3508
|
+
ok("Email connected!");
|
|
3509
|
+
if (data.agent) {
|
|
3510
|
+
ok(`Agent ${c.bold('"' + data.agent.name + '"')} is ready!`);
|
|
3511
|
+
log(` ${c.dim("Email:")} ${c.cyan(data.agent.subAddress)}`);
|
|
3512
|
+
log(` ${c.dim("Key:")} ${c.yellow(data.agent.apiKey)}`);
|
|
3513
|
+
currentAgent = { name: data.agent.name, email: data.agent.email || data.agent.subAddress, apiKey: data.agent.apiKey };
|
|
3514
|
+
}
|
|
3515
|
+
log("");
|
|
3516
|
+
return;
|
|
3517
|
+
} catch (err) {
|
|
3518
|
+
fail(`Connection failed: ${errMsg(err)}`);
|
|
3519
|
+
log("");
|
|
3520
|
+
return;
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3363
3523
|
log("");
|
|
3364
3524
|
}
|
|
3365
3525
|
},
|