@agenticmail/core 0.7.0 → 0.7.2
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 +6 -4
- package/REFERENCE.md +1 -1
- package/dist/index.cjs +14 -11
- package/dist/index.d.cts +3 -33
- package/dist/index.d.ts +3 -33
- package/dist/index.js +10 -8
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ Full custom domain through Cloudflare. Agents send from `agent@yourdomain.com` w
|
|
|
174
174
|
4. Stalwart hostname set to the domain (critical for SMTP EHLO greeting)
|
|
175
175
|
5. DKIM signing key generated in Stalwart (selector: `agenticmail`)
|
|
176
176
|
6. DNS records configured: MX (via Email Routing), SPF, DMARC, DKIM TXT, tunnel CNAME
|
|
177
|
-
7. Tunnel started with ingress rules routing traffic to the API server (port
|
|
177
|
+
7. Tunnel started with ingress rules routing traffic to the API server (port 3829) and Stalwart (port 8080)
|
|
178
178
|
8. Cloudflare Email Routing enabled on the zone
|
|
179
179
|
9. Email Worker deployed — catches all inbound email, base64-encodes the raw RFC822 content, and POSTs it to the AgenticMail inbound webhook with a shared secret
|
|
180
180
|
10. Catch-all Email Routing rule set to route all `*@domain` to the Worker
|
|
@@ -410,7 +410,9 @@ Limits: minimum 1 result, maximum 1000 results per query (default 20).
|
|
|
410
410
|
|
|
411
411
|
## Data Storage
|
|
412
412
|
|
|
413
|
-
AgenticMail uses
|
|
413
|
+
AgenticMail uses Node's built-in **`node:sqlite`** module (stable since Node 22). The database runs with WAL mode (Write-Ahead Logging) for better concurrent access and foreign keys enabled for referential integrity. Automatic migrations run on first `getDatabase()` call.
|
|
414
|
+
|
|
415
|
+
> **Why `node:sqlite` instead of `better-sqlite3`?** Before `0.7.0` this package depended on `better-sqlite3`, a native module that ships pre-built binaries per `NODE_MODULE_VERSION` and intermittently lags new Node releases. When prebuilds were missing, installers fell back to `node-gyp` compile-from-source — which requires Python, a C++ toolchain, and a working network at install time. `node:sqlite` is part of Node itself, so by definition it always matches the runtime. No prebuilds, no gyp, no native compilation, no Python prereq. The on-disk database format is unchanged (still SQLite 3); existing data files migrate transparently. **Cost:** Node 22+ is now the minimum supported runtime.
|
|
414
416
|
|
|
415
417
|
**Database location:** `~/.agenticmail/agenticmail.db`
|
|
416
418
|
|
|
@@ -447,14 +449,14 @@ The SetupManager handles getting everything installed and configured for the fir
|
|
|
447
449
|
- cloudflared — checks managed binary at `~/.agenticmail/bin/cloudflared` or system-wide via `which`
|
|
448
450
|
|
|
449
451
|
**Automatic installation:**
|
|
450
|
-
- Docker: via Homebrew (`brew install
|
|
452
|
+
- Docker: via Homebrew (`brew install colima docker docker-compose`) on macOS — **uses Colima, not Docker Desktop**, so there's no GUI gate and no terms-acceptance dialog. On Linux, the official install script. Starts Colima (`colima start --cpu 2 --memory 2 --disk 10`) and waits for the daemon to come up.
|
|
451
453
|
- Stalwart: starts the container via `docker compose up -d` and waits up to 30 seconds for it to be running.
|
|
452
454
|
- cloudflared: downloads the platform-specific binary from GitHub releases (supports macOS ARM/Intel and Linux ARM/Intel). Installs atomically (write to temp file, chmod, rename) at `~/.agenticmail/bin/cloudflared`.
|
|
453
455
|
|
|
454
456
|
**Configuration generation:**
|
|
455
457
|
- `docker-compose.yml` — Stalwart service with ports 8080 (HTTP admin), 587 (SMTP submission), 143 (IMAP), 25 (SMTP inbound)
|
|
456
458
|
- `stalwart.toml` — Stalwart configuration with RocksDB storage, internal directory, stdout logging, and fallback admin credentials
|
|
457
|
-
- `config.json` — Master key, Stalwart URL/credentials, SMTP/IMAP host/port, API host/
|
|
459
|
+
- `config.json` — Master key, Stalwart URL/credentials, SMTP/IMAP host/port, API host (default `127.0.0.1`) and API port (**default `3829`** — chosen to avoid common dev-tool ports like 3000/3100/3200/3300/4000/5000/8000/8080), data directory (written with mode 0600 for security)
|
|
458
460
|
- `.env` — Environment variables (written with mode 0600)
|
|
459
461
|
|
|
460
462
|
Configuration files are placed in the data directory (default: `~/.agenticmail/`). Calling `initConfig()` is idempotent — it loads existing config if present, but always regenerates Docker files to keep passwords in sync.
|
package/REFERENCE.md
CHANGED
|
@@ -825,7 +825,7 @@ class CloudflareClient {
|
|
|
825
825
|
|
|
826
826
|
**`createTunnel()`** — Reuses existing tunnel if name matches. Generates random 32-byte secret.
|
|
827
827
|
|
|
828
|
-
**`createTunnelRoute()`** — Creates ingress: `/api/agenticmail/*` → apiService (port
|
|
828
|
+
**`createTunnelRoute()`** — Creates ingress: `/api/agenticmail/*` → apiService (port 3829), `*` → primary service (port 8080), catch-all → 404.
|
|
829
829
|
|
|
830
830
|
**`deployEmailWorker()`** — Multipart form upload with ES module metadata and plain_text env var bindings. Compatibility date: 2024-01-01.
|
|
831
831
|
|
package/dist/index.cjs
CHANGED
|
@@ -894,6 +894,10 @@ var MailReceiver = class {
|
|
|
894
894
|
async getMailboxInfo(mailbox = "INBOX") {
|
|
895
895
|
const lock = await this.client.getMailboxLock(mailbox);
|
|
896
896
|
try {
|
|
897
|
+
try {
|
|
898
|
+
await this.client.noop();
|
|
899
|
+
} catch {
|
|
900
|
+
}
|
|
897
901
|
const status = this.client.mailbox;
|
|
898
902
|
if (!status) {
|
|
899
903
|
return { name: mailbox, exists: 0, recent: 0, unseen: 0 };
|
|
@@ -912,12 +916,8 @@ var MailReceiver = class {
|
|
|
912
916
|
const lock = await this.client.getMailboxLock(mailbox);
|
|
913
917
|
try {
|
|
914
918
|
const envelopes = [];
|
|
915
|
-
const mb = this.client.mailbox;
|
|
916
|
-
const total = mb ? mb.exists ?? 0 : 0;
|
|
917
|
-
if (total === 0) return envelopes;
|
|
918
919
|
const limit = Math.min(Math.max(options?.limit ?? 20, 1), 1e3);
|
|
919
920
|
const offset = Math.max(options?.offset ?? 0, 0);
|
|
920
|
-
if (offset >= total) return envelopes;
|
|
921
921
|
const allUids = await this.client.search({ all: true }, { uid: true });
|
|
922
922
|
if (!allUids || allUids.length === 0) return envelopes;
|
|
923
923
|
const sortedUids = Array.from(allUids).sort((a, b) => b - a);
|
|
@@ -3190,13 +3190,16 @@ function buildInboundSecurityAdvisory(security, attachments) {
|
|
|
3190
3190
|
}
|
|
3191
3191
|
|
|
3192
3192
|
// src/storage/db.ts
|
|
3193
|
-
var
|
|
3193
|
+
var import_node_module = require("module");
|
|
3194
|
+
var import_meta = {};
|
|
3195
|
+
var require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
3196
|
+
var { DatabaseSync } = require2("node:sqlite");
|
|
3194
3197
|
var db = null;
|
|
3195
3198
|
function getDatabase(config) {
|
|
3196
3199
|
if (db) return db;
|
|
3197
3200
|
ensureDataDir(config);
|
|
3198
3201
|
const dbPath = `${config.dataDir}/agenticmail.db`;
|
|
3199
|
-
db = new
|
|
3202
|
+
db = new DatabaseSync(dbPath);
|
|
3200
3203
|
db.exec("PRAGMA journal_mode = WAL");
|
|
3201
3204
|
db.exec("PRAGMA foreign_keys = ON");
|
|
3202
3205
|
runMigrations(db);
|
|
@@ -3490,7 +3493,7 @@ function runMigrations(database) {
|
|
|
3490
3493
|
}
|
|
3491
3494
|
}
|
|
3492
3495
|
function createTestDatabase() {
|
|
3493
|
-
const testDb = new
|
|
3496
|
+
const testDb = new DatabaseSync(":memory:");
|
|
3494
3497
|
testDb.exec("PRAGMA journal_mode = WAL");
|
|
3495
3498
|
testDb.exec("PRAGMA foreign_keys = ON");
|
|
3496
3499
|
for (const sql of Object.values(MIGRATIONS)) {
|
|
@@ -7171,8 +7174,8 @@ var import_node_child_process4 = require("child_process");
|
|
|
7171
7174
|
var import_node_fs6 = require("fs");
|
|
7172
7175
|
var import_node_path7 = require("path");
|
|
7173
7176
|
var import_node_os6 = require("os");
|
|
7174
|
-
var
|
|
7175
|
-
var
|
|
7177
|
+
var import_node_module2 = require("module");
|
|
7178
|
+
var import_meta2 = {};
|
|
7176
7179
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
7177
7180
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
7178
7181
|
var ServiceManager = class {
|
|
@@ -7216,7 +7219,7 @@ var ServiceManager = class {
|
|
|
7216
7219
|
*/
|
|
7217
7220
|
getApiEntryPath() {
|
|
7218
7221
|
try {
|
|
7219
|
-
const req = (0,
|
|
7222
|
+
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7220
7223
|
const resolved = req.resolve("@agenticmail/api");
|
|
7221
7224
|
if ((0, import_node_fs6.existsSync)(resolved)) return resolved;
|
|
7222
7225
|
} catch {
|
|
@@ -7272,7 +7275,7 @@ var ServiceManager = class {
|
|
|
7272
7275
|
*/
|
|
7273
7276
|
getVersion() {
|
|
7274
7277
|
try {
|
|
7275
|
-
const req = (0,
|
|
7278
|
+
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7276
7279
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
7277
7280
|
if ((0, import_node_fs6.existsSync)(pkgJson)) {
|
|
7278
7281
|
const pkg = JSON.parse((0, import_node_fs6.readFileSync)(pkgJson, "utf-8"));
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import
|
|
2
|
+
import * as node_sqlite from 'node:sqlite';
|
|
3
3
|
import { ImapFlow } from 'imapflow';
|
|
4
4
|
|
|
5
5
|
interface SendMailOptions {
|
|
@@ -291,38 +291,8 @@ declare class StalwartAdmin {
|
|
|
291
291
|
}): Promise<void>;
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
*
|
|
297
|
-
* Migrated from `better-sqlite3` to Node's built-in `node:sqlite` module
|
|
298
|
-
* (stable since Node 22). The migration eliminates native compilation
|
|
299
|
-
* entirely — `better-sqlite3` ships pre-built binaries per
|
|
300
|
-
* NODE_MODULE_VERSION and intermittently lags new Node releases (Node
|
|
301
|
-
* 25.5.0 was a real example: prebuilds missing, node-gyp fails on the
|
|
302
|
-
* fallback compile-from-source path, fresh `npm install -g
|
|
303
|
-
* @agenticmail/cli` fails for users on bleeding-edge Node). `node:sqlite`
|
|
304
|
-
* is part of Node itself, so by definition it always matches the
|
|
305
|
-
* runtime — no prebuilds, no gyp, no binding errors.
|
|
306
|
-
*
|
|
307
|
-
* # API shape differences this file accommodates
|
|
308
|
-
*
|
|
309
|
-
* - `new DatabaseSync(path)` instead of `new Database(path)`.
|
|
310
|
-
* - No `db.pragma(x)` — use `db.exec("PRAGMA " + x)`.
|
|
311
|
-
* - No `db.transaction(fn)` — wrap in BEGIN/COMMIT manually (see
|
|
312
|
-
* `runTransactionally` below). Migrations are the only transaction
|
|
313
|
-
* site in core right now; if more callers need transactions later
|
|
314
|
-
* they should reuse the same helper.
|
|
315
|
-
* - `stmt.run(...)` still returns `{ changes, lastInsertRowid }`.
|
|
316
|
-
* One subtle gotcha: `lastInsertRowid` is a `bigint` in node:sqlite
|
|
317
|
-
* where better-sqlite3 returned a `number`. Consumers that compare
|
|
318
|
-
* with `===` or pass it to `Number(...)` need to be aware, but no
|
|
319
|
-
* site inside AgenticMail today does that — all our rowids are
|
|
320
|
-
* opaque or string-typed.
|
|
321
|
-
* - The class type is `DatabaseSync`; we re-export it as `Database`
|
|
322
|
-
* so consumer files can keep saying `Database` instead of plumbing
|
|
323
|
-
* `DatabaseSync` through everywhere.
|
|
324
|
-
*/
|
|
325
|
-
|
|
294
|
+
declare const DatabaseSync: typeof node_sqlite.DatabaseSync;
|
|
295
|
+
type DatabaseSync = InstanceType<typeof node_sqlite.DatabaseSync>;
|
|
326
296
|
/**
|
|
327
297
|
* Public type alias for the database instance. Consumers should
|
|
328
298
|
* `import { type Database } from '@agenticmail/core'` rather than
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import
|
|
2
|
+
import * as node_sqlite from 'node:sqlite';
|
|
3
3
|
import { ImapFlow } from 'imapflow';
|
|
4
4
|
|
|
5
5
|
interface SendMailOptions {
|
|
@@ -291,38 +291,8 @@ declare class StalwartAdmin {
|
|
|
291
291
|
}): Promise<void>;
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
*
|
|
297
|
-
* Migrated from `better-sqlite3` to Node's built-in `node:sqlite` module
|
|
298
|
-
* (stable since Node 22). The migration eliminates native compilation
|
|
299
|
-
* entirely — `better-sqlite3` ships pre-built binaries per
|
|
300
|
-
* NODE_MODULE_VERSION and intermittently lags new Node releases (Node
|
|
301
|
-
* 25.5.0 was a real example: prebuilds missing, node-gyp fails on the
|
|
302
|
-
* fallback compile-from-source path, fresh `npm install -g
|
|
303
|
-
* @agenticmail/cli` fails for users on bleeding-edge Node). `node:sqlite`
|
|
304
|
-
* is part of Node itself, so by definition it always matches the
|
|
305
|
-
* runtime — no prebuilds, no gyp, no binding errors.
|
|
306
|
-
*
|
|
307
|
-
* # API shape differences this file accommodates
|
|
308
|
-
*
|
|
309
|
-
* - `new DatabaseSync(path)` instead of `new Database(path)`.
|
|
310
|
-
* - No `db.pragma(x)` — use `db.exec("PRAGMA " + x)`.
|
|
311
|
-
* - No `db.transaction(fn)` — wrap in BEGIN/COMMIT manually (see
|
|
312
|
-
* `runTransactionally` below). Migrations are the only transaction
|
|
313
|
-
* site in core right now; if more callers need transactions later
|
|
314
|
-
* they should reuse the same helper.
|
|
315
|
-
* - `stmt.run(...)` still returns `{ changes, lastInsertRowid }`.
|
|
316
|
-
* One subtle gotcha: `lastInsertRowid` is a `bigint` in node:sqlite
|
|
317
|
-
* where better-sqlite3 returned a `number`. Consumers that compare
|
|
318
|
-
* with `===` or pass it to `Number(...)` need to be aware, but no
|
|
319
|
-
* site inside AgenticMail today does that — all our rowids are
|
|
320
|
-
* opaque or string-typed.
|
|
321
|
-
* - The class type is `DatabaseSync`; we re-export it as `Database`
|
|
322
|
-
* so consumer files can keep saying `Database` instead of plumbing
|
|
323
|
-
* `DatabaseSync` through everywhere.
|
|
324
|
-
*/
|
|
325
|
-
|
|
294
|
+
declare const DatabaseSync: typeof node_sqlite.DatabaseSync;
|
|
295
|
+
type DatabaseSync = InstanceType<typeof node_sqlite.DatabaseSync>;
|
|
326
296
|
/**
|
|
327
297
|
* Public type alias for the database instance. Consumers should
|
|
328
298
|
* `import { type Database } from '@agenticmail/core'` rather than
|
package/dist/index.js
CHANGED
|
@@ -140,6 +140,10 @@ var MailReceiver = class {
|
|
|
140
140
|
async getMailboxInfo(mailbox = "INBOX") {
|
|
141
141
|
const lock = await this.client.getMailboxLock(mailbox);
|
|
142
142
|
try {
|
|
143
|
+
try {
|
|
144
|
+
await this.client.noop();
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
143
147
|
const status = this.client.mailbox;
|
|
144
148
|
if (!status) {
|
|
145
149
|
return { name: mailbox, exists: 0, recent: 0, unseen: 0 };
|
|
@@ -158,12 +162,8 @@ var MailReceiver = class {
|
|
|
158
162
|
const lock = await this.client.getMailboxLock(mailbox);
|
|
159
163
|
try {
|
|
160
164
|
const envelopes = [];
|
|
161
|
-
const mb = this.client.mailbox;
|
|
162
|
-
const total = mb ? mb.exists ?? 0 : 0;
|
|
163
|
-
if (total === 0) return envelopes;
|
|
164
165
|
const limit = Math.min(Math.max(options?.limit ?? 20, 1), 1e3);
|
|
165
166
|
const offset = Math.max(options?.offset ?? 0, 0);
|
|
166
|
-
if (offset >= total) return envelopes;
|
|
167
167
|
const allUids = await this.client.search({ all: true }, { uid: true });
|
|
168
168
|
if (!allUids || allUids.length === 0) return envelopes;
|
|
169
169
|
const sortedUids = Array.from(allUids).sort((a, b) => b - a);
|
|
@@ -2433,7 +2433,9 @@ function buildInboundSecurityAdvisory(security, attachments) {
|
|
|
2433
2433
|
}
|
|
2434
2434
|
|
|
2435
2435
|
// src/storage/db.ts
|
|
2436
|
-
import {
|
|
2436
|
+
import { createRequire } from "module";
|
|
2437
|
+
var require2 = createRequire(import.meta.url);
|
|
2438
|
+
var { DatabaseSync } = require2("node:sqlite");
|
|
2437
2439
|
var db = null;
|
|
2438
2440
|
function getDatabase(config) {
|
|
2439
2441
|
if (db) return db;
|
|
@@ -6413,7 +6415,7 @@ import { execFileSync as execFileSync3, execSync as execSync2 } from "child_proc
|
|
|
6413
6415
|
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync4, unlinkSync, mkdirSync as mkdirSync5, chmodSync } from "fs";
|
|
6414
6416
|
import { join as join8 } from "path";
|
|
6415
6417
|
import { homedir as homedir7, platform as platform4 } from "os";
|
|
6416
|
-
import { createRequire } from "module";
|
|
6418
|
+
import { createRequire as createRequire2 } from "module";
|
|
6417
6419
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
6418
6420
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
6419
6421
|
var ServiceManager = class {
|
|
@@ -6457,7 +6459,7 @@ var ServiceManager = class {
|
|
|
6457
6459
|
*/
|
|
6458
6460
|
getApiEntryPath() {
|
|
6459
6461
|
try {
|
|
6460
|
-
const req =
|
|
6462
|
+
const req = createRequire2(import.meta.url);
|
|
6461
6463
|
const resolved = req.resolve("@agenticmail/api");
|
|
6462
6464
|
if (existsSync6(resolved)) return resolved;
|
|
6463
6465
|
} catch {
|
|
@@ -6513,7 +6515,7 @@ var ServiceManager = class {
|
|
|
6513
6515
|
*/
|
|
6514
6516
|
getVersion() {
|
|
6515
6517
|
try {
|
|
6516
|
-
const req =
|
|
6518
|
+
const req = createRequire2(import.meta.url);
|
|
6517
6519
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
6518
6520
|
if (existsSync6(pkgJson)) {
|
|
6519
6521
|
const pkg = JSON.parse(readFileSync3(pkgJson, "utf-8"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticmail/core",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Core SDK for AgenticMail — email, SMS, and phone number access for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"LICENSE"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "tsup
|
|
24
|
-
"dev": "tsup
|
|
23
|
+
"build": "tsup --config tsup.config.ts",
|
|
24
|
+
"dev": "tsup --config tsup.config.ts --watch",
|
|
25
25
|
"test": "vitest run",
|
|
26
26
|
"test:watch": "vitest",
|
|
27
27
|
"prepublishOnly": "npm run build"
|