@agenticmail/enterprise 0.5.289 → 0.5.290

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.
@@ -0,0 +1,45 @@
1
+ import {
2
+ AgentRuntime,
3
+ EmailChannel,
4
+ FollowUpScheduler,
5
+ SessionManager,
6
+ SubAgentManager,
7
+ ToolRegistry,
8
+ callLLM,
9
+ createAgentRuntime,
10
+ createNoopHooks,
11
+ createRuntimeHooks,
12
+ estimateMessageTokens,
13
+ estimateTokens,
14
+ executeTool,
15
+ runAgentLoop,
16
+ toolsToDefinitions
17
+ } from "./chunk-2YOTK5B7.js";
18
+ import {
19
+ PROVIDER_REGISTRY,
20
+ listAllProviders,
21
+ resolveApiKeyForProvider,
22
+ resolveProvider
23
+ } from "./chunk-UF3ZJMJO.js";
24
+ import "./chunk-KFQGP6VL.js";
25
+ export {
26
+ AgentRuntime,
27
+ EmailChannel,
28
+ FollowUpScheduler,
29
+ PROVIDER_REGISTRY,
30
+ SessionManager,
31
+ SubAgentManager,
32
+ ToolRegistry,
33
+ callLLM,
34
+ createAgentRuntime,
35
+ createNoopHooks,
36
+ createRuntimeHooks,
37
+ estimateMessageTokens,
38
+ estimateTokens,
39
+ executeTool,
40
+ listAllProviders,
41
+ resolveApiKeyForProvider,
42
+ resolveProvider,
43
+ runAgentLoop,
44
+ toolsToDefinitions
45
+ };
@@ -0,0 +1,15 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-PG5CNF22.js";
4
+ import "./chunk-OF4MUWWS.js";
5
+ import "./chunk-UF3ZJMJO.js";
6
+ import "./chunk-3OC6RH7W.js";
7
+ import "./chunk-2DDKGTD6.js";
8
+ import "./chunk-YVK6F5OD.js";
9
+ import "./chunk-MKRNEM5A.js";
10
+ import "./chunk-DRXMYYKN.js";
11
+ import "./chunk-6WSX7QXF.js";
12
+ import "./chunk-KFQGP6VL.js";
13
+ export {
14
+ createServer
15
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-HE5H6NHI.js";
10
+ import "./chunk-ULRBF2T7.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.289",
3
+ "version": "0.5.290",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,138 @@
1
+ /**
2
+ * CLI Command: reset-password
3
+ *
4
+ * Reset the admin password directly in the database.
5
+ * Useful for recovery or when locked out.
6
+ *
7
+ * Usage:
8
+ * npx @agenticmail/enterprise reset-password
9
+ * DATABASE_URL=postgres://... npx @agenticmail/enterprise reset-password
10
+ */
11
+
12
+ import { existsSync, readFileSync } from 'fs';
13
+ import { join } from 'path';
14
+ import { homedir } from 'os';
15
+
16
+ export async function runResetPassword(_args: string[]): Promise<void> {
17
+ const { default: inquirer } = await import('inquirer');
18
+ const { default: chalk } = await import('chalk');
19
+ const { default: ora } = await import('ora');
20
+
21
+ console.log('');
22
+ console.log(chalk.bold(' AgenticMail Enterprise — Password Reset'));
23
+ console.log(chalk.dim(' Reset your admin login password.\n'));
24
+
25
+ // Find DATABASE_URL
26
+ let dbUrl = process.env.DATABASE_URL;
27
+ if (!dbUrl) {
28
+ // Try loading from .env
29
+ const envPaths = [
30
+ join(process.cwd(), '.env'),
31
+ join(homedir(), '.agenticmail', '.env'),
32
+ ];
33
+ for (const p of envPaths) {
34
+ if (!existsSync(p)) continue;
35
+ try {
36
+ for (const line of readFileSync(p, 'utf8').split('\n')) {
37
+ const t = line.trim();
38
+ if (t.startsWith('DATABASE_URL=')) {
39
+ dbUrl = t.slice('DATABASE_URL='.length).replace(/^["']|["']$/g, '');
40
+ console.log(chalk.dim(` Found DATABASE_URL in ${p}`));
41
+ break;
42
+ }
43
+ }
44
+ if (dbUrl) break;
45
+ } catch {}
46
+ }
47
+ }
48
+
49
+ if (!dbUrl) {
50
+ const answer = await inquirer.prompt([{
51
+ type: 'input',
52
+ name: 'dbUrl',
53
+ message: 'DATABASE_URL:',
54
+ validate: (v: string) => v.trim().length > 5 ? true : 'Enter your database connection string',
55
+ }]);
56
+ dbUrl = answer.dbUrl.trim();
57
+ }
58
+
59
+ // Get new password
60
+ const { newPassword } = await inquirer.prompt([{
61
+ type: 'password',
62
+ name: 'newPassword',
63
+ message: 'New admin password:',
64
+ mask: '*',
65
+ validate: (v: string) => v.length >= 8 ? true : 'Password must be at least 8 characters',
66
+ }]);
67
+
68
+ const { confirmPassword } = await inquirer.prompt([{
69
+ type: 'password',
70
+ name: 'confirmPassword',
71
+ message: 'Confirm password:',
72
+ mask: '*',
73
+ validate: (v: string) => v === newPassword ? true : 'Passwords do not match',
74
+ }]);
75
+
76
+ if (newPassword !== confirmPassword) {
77
+ console.log(chalk.red(' Passwords do not match.'));
78
+ process.exit(1);
79
+ }
80
+
81
+ const spinner = ora('Resetting admin password...').start();
82
+
83
+ try {
84
+ const bcryptMod = await import('bcryptjs');
85
+ const bcrypt = bcryptMod.default || bcryptMod;
86
+ const hash = await bcrypt.hash(newPassword, 12);
87
+
88
+ if (dbUrl!.startsWith('postgres')) {
89
+ const pgMod = await import('postgres' as string);
90
+ const sql = (pgMod.default || pgMod)(dbUrl!);
91
+ // Update the first admin/owner user
92
+ const result = await sql`
93
+ UPDATE users SET password_hash = ${hash}, updated_at = NOW()
94
+ WHERE id = (
95
+ SELECT id FROM users
96
+ WHERE role IN ('admin', 'owner')
97
+ ORDER BY created_at ASC
98
+ LIMIT 1
99
+ )
100
+ RETURNING email, role
101
+ `;
102
+ await sql.end();
103
+
104
+ if (result.length > 0) {
105
+ spinner.succeed(`Password reset for ${result[0].email} (${result[0].role})`);
106
+ } else {
107
+ spinner.warn('No admin user found in database. Run setup first.');
108
+ }
109
+ } else {
110
+ // SQLite
111
+ const sqliteMod = await import('better-sqlite3' as string);
112
+ const Database = sqliteMod.default || sqliteMod;
113
+ const dbPath = dbUrl!.replace('file:', '').replace('sqlite:', '');
114
+ const db = new Database(dbPath);
115
+
116
+ const user = db.prepare(
117
+ "SELECT id, email, role FROM users WHERE role IN ('admin', 'owner') ORDER BY created_at ASC LIMIT 1"
118
+ ).get() as any;
119
+
120
+ if (user) {
121
+ db.prepare('UPDATE users SET password_hash = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(hash, user.id);
122
+ db.close();
123
+ spinner.succeed(`Password reset for ${user.email} (${user.role})`);
124
+ } else {
125
+ db.close();
126
+ spinner.warn('No admin user found in database. Run setup first.');
127
+ }
128
+ }
129
+
130
+ console.log('');
131
+ console.log(chalk.green(' You can now log in with your new password.'));
132
+ console.log('');
133
+ } catch (e: any) {
134
+ spinner.fail('Failed: ' + e.message);
135
+ console.log(chalk.dim(' Make sure DATABASE_URL is correct and the database is accessible.'));
136
+ process.exit(1);
137
+ }
138
+ }
package/src/cli.ts CHANGED
@@ -44,6 +44,10 @@ switch (command) {
44
44
  import('./domain-lock/cli-verify.js').then(m => m.runVerifyDomain(args.slice(1))).catch(fatal);
45
45
  break;
46
46
 
47
+ case 'reset-password':
48
+ import('./cli-reset-password.js').then(m => m.runResetPassword(args.slice(1))).catch(fatal);
49
+ break;
50
+
47
51
  case '--help':
48
52
  case '-h':
49
53
  console.log(`
@@ -57,7 +61,8 @@ Commands:
57
61
  --json Machine-readable output
58
62
  build-skill AI-assisted skill scaffolding
59
63
  submit-skill <path> Submit a skill as a PR
60
- recover Recover a domain registration on a new machine
64
+ recover Recover a domain/subdomain on a new machine
65
+ reset-password Reset admin password directly in the database
61
66
  verify-domain Check DNS verification for your domain
62
67
 
63
68
  Domain Recovery & Verification:
@@ -443,6 +443,69 @@ async function runCloudRecover(args: string[], inquirer: any, chalk: any, ora: a
443
443
  console.log(chalk.dim(' Users will need to log in again. This is normal for recovery.'));
444
444
  }
445
445
 
446
+ // Offer to reset admin password
447
+ const { wantsReset } = await inquirer.prompt([{
448
+ type: 'confirm',
449
+ name: 'wantsReset',
450
+ message: 'Reset your admin password?',
451
+ default: false,
452
+ }]);
453
+
454
+ if (wantsReset) {
455
+ // Read DATABASE_URL from current env
456
+ let dbUrl = '';
457
+ for (const line of currentEnv.split('\n')) {
458
+ const t = line.trim();
459
+ if (t.startsWith('DATABASE_URL=')) dbUrl = t.slice('DATABASE_URL='.length);
460
+ }
461
+
462
+ if (!dbUrl) {
463
+ console.log(chalk.yellow(' Cannot reset password without DATABASE_URL.'));
464
+ } else {
465
+ const { newPassword } = await inquirer.prompt([{
466
+ type: 'password',
467
+ name: 'newPassword',
468
+ message: 'New admin password:',
469
+ mask: '*',
470
+ validate: (v: string) => v.length >= 8 ? true : 'Password must be at least 8 characters',
471
+ }]);
472
+ const { confirmPassword } = await inquirer.prompt([{
473
+ type: 'password',
474
+ name: 'confirmPassword',
475
+ message: 'Confirm password:',
476
+ mask: '*',
477
+ validate: (v: string) => v === newPassword ? true : 'Passwords do not match',
478
+ }]);
479
+
480
+ if (newPassword === confirmPassword) {
481
+ const resetSpinner = ora('Resetting admin password...').start();
482
+ try {
483
+ const bcryptMod = await import('bcryptjs');
484
+ const bcrypt = bcryptMod.default || bcryptMod;
485
+ const hash = await bcrypt.hash(newPassword, 12);
486
+
487
+ if (dbUrl.startsWith('postgres')) {
488
+ const pgMod = await import('postgres' as string);
489
+ const sql = (pgMod.default || pgMod)(dbUrl);
490
+ await sql`UPDATE users SET password_hash = ${hash} WHERE role = 'admin' OR role = 'owner' ORDER BY created_at ASC LIMIT 1`;
491
+ await sql.end();
492
+ } else {
493
+ // SQLite
494
+ const sqliteMod = await import('better-sqlite3' as string);
495
+ const Database = sqliteMod.default || sqliteMod;
496
+ const db = new Database(dbUrl.replace('file:', '').replace('sqlite:', ''));
497
+ db.prepare('UPDATE users SET password_hash = ? WHERE rowid = (SELECT rowid FROM users WHERE role IN (?, ?) ORDER BY created_at ASC LIMIT 1)').run(hash, 'admin', 'owner');
498
+ db.close();
499
+ }
500
+ resetSpinner.succeed('Admin password reset successfully');
501
+ } catch (e: any) {
502
+ resetSpinner.fail('Could not reset password: ' + e.message);
503
+ console.log(chalk.dim(' You can reset it later from the dashboard or by re-running recovery.'));
504
+ }
505
+ }
506
+ }
507
+ }
508
+
446
509
  console.log('');
447
510
  console.log(` Start your instance:`);
448
511
  console.log(` ${chalk.cyan('npx @agenticmail/enterprise start')}`);