@agenticmail/core 0.9.5 → 0.9.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/index.cjs +270 -188
- package/dist/index.d.cts +124 -1
- package/dist/index.d.ts +124 -1
- package/dist/index.js +254 -178
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1093,14 +1093,14 @@ var StalwartAdmin = class {
|
|
|
1093
1093
|
if (!isValidDomain(domain)) {
|
|
1094
1094
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
1095
1095
|
}
|
|
1096
|
-
const { readFileSync:
|
|
1097
|
-
const { homedir:
|
|
1098
|
-
const { join:
|
|
1099
|
-
const configPath =
|
|
1096
|
+
const { readFileSync: readFileSync8, writeFileSync: writeFileSync9 } = await import("fs");
|
|
1097
|
+
const { homedir: homedir12 } = await import("os");
|
|
1098
|
+
const { join: join14 } = await import("path");
|
|
1099
|
+
const configPath = join14(homedir12(), ".agenticmail", "stalwart.toml");
|
|
1100
1100
|
try {
|
|
1101
|
-
let config =
|
|
1101
|
+
let config = readFileSync8(configPath, "utf-8");
|
|
1102
1102
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
1103
|
-
|
|
1103
|
+
writeFileSync9(configPath, config);
|
|
1104
1104
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
1105
1105
|
} catch (err) {
|
|
1106
1106
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -1109,15 +1109,15 @@ var StalwartAdmin = class {
|
|
|
1109
1109
|
// --- DKIM ---
|
|
1110
1110
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
1111
1111
|
get configPath() {
|
|
1112
|
-
const { homedir:
|
|
1113
|
-
const { join:
|
|
1114
|
-
return
|
|
1112
|
+
const { homedir: homedir12 } = __require("os");
|
|
1113
|
+
const { join: join14 } = __require("path");
|
|
1114
|
+
return join14(homedir12(), ".agenticmail", "stalwart.toml");
|
|
1115
1115
|
}
|
|
1116
1116
|
/** Path to host-side DKIM key directory */
|
|
1117
1117
|
get dkimDir() {
|
|
1118
|
-
const { homedir:
|
|
1119
|
-
const { join:
|
|
1120
|
-
return
|
|
1118
|
+
const { homedir: homedir12 } = __require("os");
|
|
1119
|
+
const { join: join14 } = __require("path");
|
|
1120
|
+
return join14(homedir12(), ".agenticmail");
|
|
1121
1121
|
}
|
|
1122
1122
|
/**
|
|
1123
1123
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -1218,12 +1218,12 @@ var StalwartAdmin = class {
|
|
|
1218
1218
|
* This bypasses the need for a PTR record on the sending IP.
|
|
1219
1219
|
*/
|
|
1220
1220
|
async configureOutboundRelay(config) {
|
|
1221
|
-
const { readFileSync:
|
|
1222
|
-
const { homedir:
|
|
1223
|
-
const { join:
|
|
1221
|
+
const { readFileSync: readFileSync8, writeFileSync: writeFileSync9 } = await import("fs");
|
|
1222
|
+
const { homedir: homedir12 } = await import("os");
|
|
1223
|
+
const { join: join14 } = await import("path");
|
|
1224
1224
|
const routeName = config.routeName ?? "gmail";
|
|
1225
|
-
const tomlPath =
|
|
1226
|
-
let toml =
|
|
1225
|
+
const tomlPath = join14(homedir12(), ".agenticmail", "stalwart.toml");
|
|
1226
|
+
let toml = readFileSync8(tomlPath, "utf-8");
|
|
1227
1227
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
1228
1228
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
1229
1229
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -1243,7 +1243,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
1243
1243
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
1244
1244
|
{ else = "'${safeRouteName}'" } ]
|
|
1245
1245
|
`;
|
|
1246
|
-
|
|
1246
|
+
writeFileSync9(tomlPath, toml, "utf-8");
|
|
1247
1247
|
await this.restartContainer();
|
|
1248
1248
|
}
|
|
1249
1249
|
};
|
|
@@ -4240,9 +4240,9 @@ var TunnelManager = class {
|
|
|
4240
4240
|
throw new Error(`Failed to download cloudflared: ${response.statusText}`);
|
|
4241
4241
|
}
|
|
4242
4242
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
4243
|
-
const { writeFile:
|
|
4243
|
+
const { writeFile: writeFile3, rename: rename2 } = await import("fs/promises");
|
|
4244
4244
|
const tmpPath = this.binPath + ".tmp";
|
|
4245
|
-
await
|
|
4245
|
+
await writeFile3(tmpPath, buffer);
|
|
4246
4246
|
await chmod(tmpPath, 493);
|
|
4247
4247
|
await rename2(tmpPath, this.binPath);
|
|
4248
4248
|
return this.binPath;
|
|
@@ -5149,12 +5149,12 @@ var GatewayManager = class {
|
|
|
5149
5149
|
zone = await this.cfClient.createZone(domain);
|
|
5150
5150
|
}
|
|
5151
5151
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
5152
|
-
const { homedir:
|
|
5153
|
-
const backupDir = join4(
|
|
5152
|
+
const { homedir: homedir12 } = await import("os");
|
|
5153
|
+
const backupDir = join4(homedir12(), ".agenticmail");
|
|
5154
5154
|
const backupPath = join4(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
5155
|
-
const { writeFileSync:
|
|
5156
|
-
|
|
5157
|
-
|
|
5155
|
+
const { writeFileSync: writeFileSync9, mkdirSync: mkdirSync10 } = await import("fs");
|
|
5156
|
+
mkdirSync10(backupDir, { recursive: true });
|
|
5157
|
+
writeFileSync9(backupPath, JSON.stringify({
|
|
5158
5158
|
domain,
|
|
5159
5159
|
zoneId: zone.id,
|
|
5160
5160
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6096,6 +6096,76 @@ function redactObject(input, _depth = 0) {
|
|
|
6096
6096
|
return out;
|
|
6097
6097
|
}
|
|
6098
6098
|
|
|
6099
|
+
// src/host-sessions.ts
|
|
6100
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync4 } from "fs";
|
|
6101
|
+
import { join as join7 } from "path";
|
|
6102
|
+
import { homedir as homedir5 } from "os";
|
|
6103
|
+
function storageDir() {
|
|
6104
|
+
return join7(homedir5(), ".agenticmail");
|
|
6105
|
+
}
|
|
6106
|
+
function storagePath() {
|
|
6107
|
+
return join7(storageDir(), "host-sessions.json");
|
|
6108
|
+
}
|
|
6109
|
+
var DEFAULT_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
6110
|
+
function readFile() {
|
|
6111
|
+
const p = storagePath();
|
|
6112
|
+
if (!existsSync4(p)) return { version: 1, sessions: {} };
|
|
6113
|
+
try {
|
|
6114
|
+
const raw = readFileSync3(p, "utf-8");
|
|
6115
|
+
if (!raw.trim()) return { version: 1, sessions: {} };
|
|
6116
|
+
const parsed = JSON.parse(raw);
|
|
6117
|
+
return {
|
|
6118
|
+
version: 1,
|
|
6119
|
+
sessions: parsed.sessions && typeof parsed.sessions === "object" ? parsed.sessions : {}
|
|
6120
|
+
};
|
|
6121
|
+
} catch {
|
|
6122
|
+
return { version: 1, sessions: {} };
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
function writeFile(shape) {
|
|
6126
|
+
const dir = storageDir();
|
|
6127
|
+
const p = storagePath();
|
|
6128
|
+
if (!existsSync4(dir)) mkdirSync4(dir, { recursive: true });
|
|
6129
|
+
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6130
|
+
writeFileSync4(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
6131
|
+
renameSync(tmp, p);
|
|
6132
|
+
}
|
|
6133
|
+
function saveHostSession(host, session) {
|
|
6134
|
+
if (!session.sessionId) return;
|
|
6135
|
+
try {
|
|
6136
|
+
const shape = readFile();
|
|
6137
|
+
shape.sessions[host] = {
|
|
6138
|
+
...session,
|
|
6139
|
+
lastSeenMs: Date.now()
|
|
6140
|
+
};
|
|
6141
|
+
writeFile(shape);
|
|
6142
|
+
} catch {
|
|
6143
|
+
}
|
|
6144
|
+
}
|
|
6145
|
+
function loadHostSession(host, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
6146
|
+
const shape = readFile();
|
|
6147
|
+
const record = shape.sessions[host];
|
|
6148
|
+
if (!record) return null;
|
|
6149
|
+
if (!isSessionFresh(record, maxAgeMs)) return null;
|
|
6150
|
+
return record;
|
|
6151
|
+
}
|
|
6152
|
+
function isSessionFresh(session, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
6153
|
+
if (!session || !Number.isFinite(session.lastSeenMs)) return false;
|
|
6154
|
+
return Date.now() - session.lastSeenMs <= maxAgeMs;
|
|
6155
|
+
}
|
|
6156
|
+
function forgetHostSession(host) {
|
|
6157
|
+
try {
|
|
6158
|
+
const shape = readFile();
|
|
6159
|
+
if (!shape.sessions[host]) return;
|
|
6160
|
+
delete shape.sessions[host];
|
|
6161
|
+
writeFile(shape);
|
|
6162
|
+
} catch {
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
function hostSessionStoragePath() {
|
|
6166
|
+
return storagePath();
|
|
6167
|
+
}
|
|
6168
|
+
|
|
6099
6169
|
// src/util/safe-url.ts
|
|
6100
6170
|
var UnsafeApiUrlError = class extends Error {
|
|
6101
6171
|
constructor(raw, reason) {
|
|
@@ -6144,15 +6214,15 @@ function buildApiUrl(baseOrigin, pathAndQuery) {
|
|
|
6144
6214
|
|
|
6145
6215
|
// src/setup/index.ts
|
|
6146
6216
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
6147
|
-
import { existsSync as
|
|
6148
|
-
import { join as
|
|
6149
|
-
import { homedir as
|
|
6217
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, chmodSync as chmodSync2 } from "fs";
|
|
6218
|
+
import { join as join11 } from "path";
|
|
6219
|
+
import { homedir as homedir9 } from "os";
|
|
6150
6220
|
|
|
6151
6221
|
// src/setup/deps.ts
|
|
6152
6222
|
import { execFileSync } from "child_process";
|
|
6153
|
-
import { existsSync as
|
|
6154
|
-
import { join as
|
|
6155
|
-
import { homedir as
|
|
6223
|
+
import { existsSync as existsSync5 } from "fs";
|
|
6224
|
+
import { join as join8 } from "path";
|
|
6225
|
+
import { homedir as homedir6 } from "os";
|
|
6156
6226
|
var DependencyChecker = class {
|
|
6157
6227
|
async checkAll() {
|
|
6158
6228
|
return Promise.all([
|
|
@@ -6202,8 +6272,8 @@ var DependencyChecker = class {
|
|
|
6202
6272
|
}
|
|
6203
6273
|
}
|
|
6204
6274
|
async checkCloudflared() {
|
|
6205
|
-
const binPath =
|
|
6206
|
-
if (
|
|
6275
|
+
const binPath = join8(homedir6(), ".agenticmail", "bin", "cloudflared");
|
|
6276
|
+
if (existsSync5(binPath)) {
|
|
6207
6277
|
let version;
|
|
6208
6278
|
try {
|
|
6209
6279
|
const output = execFileSync(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -6225,10 +6295,10 @@ var DependencyChecker = class {
|
|
|
6225
6295
|
|
|
6226
6296
|
// src/setup/installer.ts
|
|
6227
6297
|
import { execFileSync as execFileSync2, execSync, spawn as spawnChild } from "child_process";
|
|
6228
|
-
import { existsSync as
|
|
6229
|
-
import { writeFile, rename, chmod as chmod2, mkdir as mkdir2, unlink } from "fs/promises";
|
|
6230
|
-
import { join as
|
|
6231
|
-
import { homedir as
|
|
6298
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, symlinkSync } from "fs";
|
|
6299
|
+
import { writeFile as writeFile2, rename, chmod as chmod2, mkdir as mkdir2, unlink } from "fs/promises";
|
|
6300
|
+
import { join as join9 } from "path";
|
|
6301
|
+
import { homedir as homedir7, platform as platform3, arch as arch2 } from "os";
|
|
6232
6302
|
function runShellWithRollingOutput(cmd, opts = {}) {
|
|
6233
6303
|
const maxLines = opts.maxLines ?? 20;
|
|
6234
6304
|
const timeout = opts.timeout ?? 3e5;
|
|
@@ -6404,11 +6474,11 @@ var DependencyInstaller = class {
|
|
|
6404
6474
|
try {
|
|
6405
6475
|
const composeBin = execFileSync2("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6406
6476
|
if (!composeBin) return;
|
|
6407
|
-
const pluginDir =
|
|
6408
|
-
const pluginPath =
|
|
6409
|
-
if (
|
|
6477
|
+
const pluginDir = join9(homedir7(), ".docker", "cli-plugins");
|
|
6478
|
+
const pluginPath = join9(pluginDir, "docker-compose");
|
|
6479
|
+
if (existsSync6(pluginPath)) return;
|
|
6410
6480
|
try {
|
|
6411
|
-
|
|
6481
|
+
mkdirSync5(pluginDir, { recursive: true });
|
|
6412
6482
|
} catch {
|
|
6413
6483
|
}
|
|
6414
6484
|
try {
|
|
@@ -6471,9 +6541,9 @@ var DependencyInstaller = class {
|
|
|
6471
6541
|
return;
|
|
6472
6542
|
}
|
|
6473
6543
|
this.onProgress("__progress__:5:Installing Docker Engine...");
|
|
6474
|
-
const tmpDir =
|
|
6544
|
+
const tmpDir = join9(homedir7(), ".agenticmail", "tmp");
|
|
6475
6545
|
await mkdir2(tmpDir, { recursive: true });
|
|
6476
|
-
const scriptPath =
|
|
6546
|
+
const scriptPath = join9(tmpDir, "install-docker.sh");
|
|
6477
6547
|
const dlResult = await runShellWithRollingOutput(
|
|
6478
6548
|
`curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
|
|
6479
6549
|
{ timeout: 3e5 }
|
|
@@ -6541,8 +6611,8 @@ var DependencyInstaller = class {
|
|
|
6541
6611
|
}
|
|
6542
6612
|
try {
|
|
6543
6613
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
6544
|
-
const dockerExe =
|
|
6545
|
-
if (
|
|
6614
|
+
const dockerExe = join9(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
6615
|
+
if (existsSync6(dockerExe)) {
|
|
6546
6616
|
execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
6547
6617
|
}
|
|
6548
6618
|
} catch {
|
|
@@ -6592,8 +6662,8 @@ var DependencyInstaller = class {
|
|
|
6592
6662
|
this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
|
|
6593
6663
|
try {
|
|
6594
6664
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
6595
|
-
const dockerExe =
|
|
6596
|
-
if (
|
|
6665
|
+
const dockerExe = join9(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
6666
|
+
if (existsSync6(dockerExe)) {
|
|
6597
6667
|
execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
6598
6668
|
}
|
|
6599
6669
|
} catch {
|
|
@@ -6630,7 +6700,7 @@ var DependencyInstaller = class {
|
|
|
6630
6700
|
* Start the Stalwart mail server Docker container.
|
|
6631
6701
|
*/
|
|
6632
6702
|
async startStalwart(composePath) {
|
|
6633
|
-
if (!
|
|
6703
|
+
if (!existsSync6(composePath)) {
|
|
6634
6704
|
throw new Error(`docker-compose.yml not found at: ${composePath}`);
|
|
6635
6705
|
}
|
|
6636
6706
|
if (!this.isDockerReady()) {
|
|
@@ -6689,16 +6759,16 @@ var DependencyInstaller = class {
|
|
|
6689
6759
|
*/
|
|
6690
6760
|
async installCloudflared() {
|
|
6691
6761
|
const os = platform3();
|
|
6692
|
-
const binDir =
|
|
6762
|
+
const binDir = join9(homedir7(), ".agenticmail", "bin");
|
|
6693
6763
|
const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
6694
|
-
const binPath =
|
|
6695
|
-
if (
|
|
6764
|
+
const binPath = join9(binDir, binName);
|
|
6765
|
+
if (existsSync6(binPath)) {
|
|
6696
6766
|
return binPath;
|
|
6697
6767
|
}
|
|
6698
6768
|
try {
|
|
6699
6769
|
const whichCmd = os === "win32" ? "where" : "which";
|
|
6700
6770
|
const sysPath = execFileSync2(whichCmd, ["cloudflared"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n")[0];
|
|
6701
|
-
if (sysPath &&
|
|
6771
|
+
if (sysPath && existsSync6(sysPath)) return sysPath;
|
|
6702
6772
|
} catch {
|
|
6703
6773
|
}
|
|
6704
6774
|
this.onProgress("Downloading cloudflared...");
|
|
@@ -6721,8 +6791,8 @@ var DependencyInstaller = class {
|
|
|
6721
6791
|
}
|
|
6722
6792
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
6723
6793
|
if (os === "darwin") {
|
|
6724
|
-
const tgzPath =
|
|
6725
|
-
await
|
|
6794
|
+
const tgzPath = join9(binDir, "cloudflared.tgz");
|
|
6795
|
+
await writeFile2(tgzPath, buffer);
|
|
6726
6796
|
try {
|
|
6727
6797
|
execFileSync2("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
|
|
6728
6798
|
await chmod2(binPath, 493);
|
|
@@ -6734,11 +6804,11 @@ var DependencyInstaller = class {
|
|
|
6734
6804
|
}
|
|
6735
6805
|
} else {
|
|
6736
6806
|
const tmpPath = binPath + ".tmp";
|
|
6737
|
-
await
|
|
6807
|
+
await writeFile2(tmpPath, buffer);
|
|
6738
6808
|
if (os !== "win32") await chmod2(tmpPath, 493);
|
|
6739
6809
|
await rename(tmpPath, binPath);
|
|
6740
6810
|
}
|
|
6741
|
-
if (!
|
|
6811
|
+
if (!existsSync6(binPath)) {
|
|
6742
6812
|
throw new Error("cloudflared download succeeded but binary not found after extraction");
|
|
6743
6813
|
}
|
|
6744
6814
|
this.onProgress("cloudflared installed");
|
|
@@ -6756,9 +6826,9 @@ var DependencyInstaller = class {
|
|
|
6756
6826
|
|
|
6757
6827
|
// src/setup/service.ts
|
|
6758
6828
|
import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
|
|
6759
|
-
import { existsSync as
|
|
6760
|
-
import { join as
|
|
6761
|
-
import { homedir as
|
|
6829
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync5, unlinkSync, mkdirSync as mkdirSync6, chmodSync } from "fs";
|
|
6830
|
+
import { join as join10 } from "path";
|
|
6831
|
+
import { homedir as homedir8, platform as platform4 } from "os";
|
|
6762
6832
|
import { createRequire as createRequire2 } from "module";
|
|
6763
6833
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
6764
6834
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
@@ -6769,9 +6839,9 @@ var ServiceManager = class {
|
|
|
6769
6839
|
*/
|
|
6770
6840
|
getServicePath() {
|
|
6771
6841
|
if (this.os === "darwin") {
|
|
6772
|
-
return
|
|
6842
|
+
return join10(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
6773
6843
|
} else {
|
|
6774
|
-
return
|
|
6844
|
+
return join10(homedir8(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
6775
6845
|
}
|
|
6776
6846
|
}
|
|
6777
6847
|
/**
|
|
@@ -6805,40 +6875,40 @@ var ServiceManager = class {
|
|
|
6805
6875
|
try {
|
|
6806
6876
|
const req = createRequire2(import.meta.url);
|
|
6807
6877
|
const resolved = req.resolve("@agenticmail/api");
|
|
6808
|
-
if (
|
|
6878
|
+
if (existsSync7(resolved)) return resolved;
|
|
6809
6879
|
} catch {
|
|
6810
6880
|
}
|
|
6811
6881
|
const parentPackages = [
|
|
6812
|
-
|
|
6882
|
+
join10("@agenticmail", "cli"),
|
|
6813
6883
|
// current scoped package
|
|
6814
6884
|
"agenticmail"
|
|
6815
6885
|
// legacy unscoped package
|
|
6816
6886
|
];
|
|
6817
6887
|
const baseDirs = [
|
|
6818
6888
|
// user-local install
|
|
6819
|
-
|
|
6889
|
+
join10(homedir8(), "node_modules")
|
|
6820
6890
|
];
|
|
6821
6891
|
try {
|
|
6822
6892
|
const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6823
|
-
baseDirs.push(
|
|
6824
|
-
baseDirs.push(
|
|
6893
|
+
baseDirs.push(join10(prefix, "lib", "node_modules"));
|
|
6894
|
+
baseDirs.push(join10(prefix, "node_modules"));
|
|
6825
6895
|
} catch {
|
|
6826
6896
|
}
|
|
6827
6897
|
baseDirs.push("/opt/homebrew/lib/node_modules");
|
|
6828
6898
|
baseDirs.push("/usr/local/lib/node_modules");
|
|
6829
6899
|
for (const base of baseDirs) {
|
|
6830
|
-
const sibling =
|
|
6831
|
-
if (
|
|
6900
|
+
const sibling = join10(base, "@agenticmail", "api", "dist", "index.js");
|
|
6901
|
+
if (existsSync7(sibling)) return sibling;
|
|
6832
6902
|
for (const parent of parentPackages) {
|
|
6833
|
-
const nested =
|
|
6834
|
-
if (
|
|
6903
|
+
const nested = join10(base, parent, "node_modules", "@agenticmail", "api", "dist", "index.js");
|
|
6904
|
+
if (existsSync7(nested)) return nested;
|
|
6835
6905
|
}
|
|
6836
6906
|
}
|
|
6837
|
-
const dataDir =
|
|
6838
|
-
const entryCache =
|
|
6839
|
-
if (
|
|
6840
|
-
const cached =
|
|
6841
|
-
if (cached &&
|
|
6907
|
+
const dataDir = join10(homedir8(), ".agenticmail");
|
|
6908
|
+
const entryCache = join10(dataDir, "api-entry.path");
|
|
6909
|
+
if (existsSync7(entryCache)) {
|
|
6910
|
+
const cached = readFileSync4(entryCache, "utf-8").trim();
|
|
6911
|
+
if (cached && existsSync7(cached)) return cached;
|
|
6842
6912
|
}
|
|
6843
6913
|
throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
|
|
6844
6914
|
}
|
|
@@ -6846,9 +6916,9 @@ var ServiceManager = class {
|
|
|
6846
6916
|
* Cache the API entry path so the service can find it later.
|
|
6847
6917
|
*/
|
|
6848
6918
|
cacheApiEntryPath(entryPath) {
|
|
6849
|
-
const dataDir =
|
|
6850
|
-
if (!
|
|
6851
|
-
|
|
6919
|
+
const dataDir = join10(homedir8(), ".agenticmail");
|
|
6920
|
+
if (!existsSync7(dataDir)) mkdirSync6(dataDir, { recursive: true });
|
|
6921
|
+
writeFileSync5(join10(dataDir, "api-entry.path"), entryPath);
|
|
6852
6922
|
}
|
|
6853
6923
|
/**
|
|
6854
6924
|
* Get the current package version.
|
|
@@ -6861,36 +6931,36 @@ var ServiceManager = class {
|
|
|
6861
6931
|
try {
|
|
6862
6932
|
const req = createRequire2(import.meta.url);
|
|
6863
6933
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
6864
|
-
if (
|
|
6865
|
-
const pkg = JSON.parse(
|
|
6934
|
+
if (existsSync7(pkgJson)) {
|
|
6935
|
+
const pkg = JSON.parse(readFileSync4(pkgJson, "utf-8"));
|
|
6866
6936
|
if (pkg.version) return pkg.version;
|
|
6867
6937
|
}
|
|
6868
6938
|
} catch {
|
|
6869
6939
|
}
|
|
6870
6940
|
try {
|
|
6871
6941
|
const apiEntry = this.getApiEntryPath();
|
|
6872
|
-
const apiPkg =
|
|
6873
|
-
if (
|
|
6874
|
-
const pkg = JSON.parse(
|
|
6942
|
+
const apiPkg = join10(apiEntry, "..", "..", "package.json");
|
|
6943
|
+
if (existsSync7(apiPkg)) {
|
|
6944
|
+
const pkg = JSON.parse(readFileSync4(apiPkg, "utf-8"));
|
|
6875
6945
|
if (pkg.version) return pkg.version;
|
|
6876
6946
|
}
|
|
6877
6947
|
} catch {
|
|
6878
6948
|
}
|
|
6879
6949
|
const candidates = [
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6950
|
+
join10(homedir8(), "node_modules", "@agenticmail", "cli", "package.json"),
|
|
6951
|
+
join10(homedir8(), "node_modules", "agenticmail", "package.json"),
|
|
6952
|
+
join10(homedir8(), ".agenticmail", "package-version.json")
|
|
6883
6953
|
];
|
|
6884
6954
|
try {
|
|
6885
6955
|
const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6886
|
-
candidates.push(
|
|
6887
|
-
candidates.push(
|
|
6956
|
+
candidates.push(join10(prefix, "lib", "node_modules", "@agenticmail", "cli", "package.json"));
|
|
6957
|
+
candidates.push(join10(prefix, "lib", "node_modules", "agenticmail", "package.json"));
|
|
6888
6958
|
} catch {
|
|
6889
6959
|
}
|
|
6890
6960
|
for (const p of candidates) {
|
|
6891
6961
|
try {
|
|
6892
|
-
if (
|
|
6893
|
-
const pkg = JSON.parse(
|
|
6962
|
+
if (existsSync7(p)) {
|
|
6963
|
+
const pkg = JSON.parse(readFileSync4(p, "utf-8"));
|
|
6894
6964
|
if (pkg.version) return pkg.version;
|
|
6895
6965
|
}
|
|
6896
6966
|
} catch {
|
|
@@ -6903,9 +6973,9 @@ var ServiceManager = class {
|
|
|
6903
6973
|
* This ensures AgenticMail doesn't fail on boot when Docker is still loading.
|
|
6904
6974
|
*/
|
|
6905
6975
|
generateStartScript(nodePath, apiEntry) {
|
|
6906
|
-
const scriptPath =
|
|
6907
|
-
const scriptDir =
|
|
6908
|
-
if (!
|
|
6976
|
+
const scriptPath = join10(homedir8(), ".agenticmail", "bin", "start-server.sh");
|
|
6977
|
+
const scriptDir = join10(homedir8(), ".agenticmail", "bin");
|
|
6978
|
+
if (!existsSync7(scriptDir)) mkdirSync6(scriptDir, { recursive: true });
|
|
6909
6979
|
const script = [
|
|
6910
6980
|
"#!/bin/bash",
|
|
6911
6981
|
"# AgenticMail auto-start script",
|
|
@@ -6956,7 +7026,7 @@ var ServiceManager = class {
|
|
|
6956
7026
|
`log "Starting API server: ${nodePath} ${apiEntry}"`,
|
|
6957
7027
|
`exec "${nodePath}" "${apiEntry}"`
|
|
6958
7028
|
].join("\n") + "\n";
|
|
6959
|
-
|
|
7029
|
+
writeFileSync5(scriptPath, script, { mode: 493 });
|
|
6960
7030
|
return scriptPath;
|
|
6961
7031
|
}
|
|
6962
7032
|
/**
|
|
@@ -6969,9 +7039,9 @@ var ServiceManager = class {
|
|
|
6969
7039
|
* - Service version tracking in env vars
|
|
6970
7040
|
*/
|
|
6971
7041
|
generatePlist(nodePath, apiEntry, configPath) {
|
|
6972
|
-
const config = JSON.parse(
|
|
6973
|
-
const logDir =
|
|
6974
|
-
if (!
|
|
7042
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7043
|
+
const logDir = join10(homedir8(), ".agenticmail", "logs");
|
|
7044
|
+
if (!existsSync7(logDir)) mkdirSync6(logDir, { recursive: true });
|
|
6975
7045
|
const version = this.getVersion();
|
|
6976
7046
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
6977
7047
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -6992,9 +7062,9 @@ var ServiceManager = class {
|
|
|
6992
7062
|
<key>EnvironmentVariables</key>
|
|
6993
7063
|
<dict>
|
|
6994
7064
|
<key>HOME</key>
|
|
6995
|
-
<string>${
|
|
7065
|
+
<string>${homedir8()}</string>
|
|
6996
7066
|
<key>AGENTICMAIL_DATA_DIR</key>
|
|
6997
|
-
<string>${config.dataDir ||
|
|
7067
|
+
<string>${config.dataDir || join10(homedir8(), ".agenticmail")}</string>
|
|
6998
7068
|
<key>PATH</key>
|
|
6999
7069
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
7000
7070
|
<key>AGENTICMAIL_SERVICE_VERSION</key>
|
|
@@ -7047,8 +7117,8 @@ var ServiceManager = class {
|
|
|
7047
7117
|
* - Proper dependency ordering
|
|
7048
7118
|
*/
|
|
7049
7119
|
generateSystemdUnit(nodePath, apiEntry, configPath) {
|
|
7050
|
-
const config = JSON.parse(
|
|
7051
|
-
const dataDir = config.dataDir ||
|
|
7120
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7121
|
+
const dataDir = config.dataDir || join10(homedir8(), ".agenticmail");
|
|
7052
7122
|
const version = this.getVersion();
|
|
7053
7123
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7054
7124
|
return `[Unit]
|
|
@@ -7065,7 +7135,7 @@ Restart=always
|
|
|
7065
7135
|
RestartSec=15
|
|
7066
7136
|
TimeoutStartSec=660
|
|
7067
7137
|
LimitNOFILE=8192
|
|
7068
|
-
Environment=HOME=${
|
|
7138
|
+
Environment=HOME=${homedir8()}
|
|
7069
7139
|
Environment=AGENTICMAIL_DATA_DIR=${dataDir}
|
|
7070
7140
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
|
|
7071
7141
|
Environment=AGENTICMAIL_SERVICE_VERSION=${version}
|
|
@@ -7078,8 +7148,8 @@ WantedBy=default.target
|
|
|
7078
7148
|
* Install the auto-start service.
|
|
7079
7149
|
*/
|
|
7080
7150
|
install() {
|
|
7081
|
-
const configPath =
|
|
7082
|
-
if (!
|
|
7151
|
+
const configPath = join10(homedir8(), ".agenticmail", "config.json");
|
|
7152
|
+
if (!existsSync7(configPath)) {
|
|
7083
7153
|
return { installed: false, message: "Config not found. Run agenticmail setup first." };
|
|
7084
7154
|
}
|
|
7085
7155
|
const nodePath = this.getNodePath();
|
|
@@ -7091,16 +7161,16 @@ WantedBy=default.target
|
|
|
7091
7161
|
}
|
|
7092
7162
|
const servicePath = this.getServicePath();
|
|
7093
7163
|
if (this.os === "darwin") {
|
|
7094
|
-
const dir =
|
|
7095
|
-
if (!
|
|
7096
|
-
if (
|
|
7164
|
+
const dir = join10(homedir8(), "Library", "LaunchAgents");
|
|
7165
|
+
if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true });
|
|
7166
|
+
if (existsSync7(servicePath)) {
|
|
7097
7167
|
try {
|
|
7098
7168
|
execFileSync3("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7099
7169
|
} catch {
|
|
7100
7170
|
}
|
|
7101
7171
|
}
|
|
7102
7172
|
const plist = this.generatePlist(nodePath, apiEntry, configPath);
|
|
7103
|
-
|
|
7173
|
+
writeFileSync5(servicePath, plist);
|
|
7104
7174
|
chmodSync(servicePath, 384);
|
|
7105
7175
|
try {
|
|
7106
7176
|
execFileSync3("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -7109,10 +7179,10 @@ WantedBy=default.target
|
|
|
7109
7179
|
}
|
|
7110
7180
|
return { installed: true, message: `Service installed at ${servicePath}` };
|
|
7111
7181
|
} else if (this.os === "linux") {
|
|
7112
|
-
const dir =
|
|
7113
|
-
if (!
|
|
7182
|
+
const dir = join10(homedir8(), ".config", "systemd", "user");
|
|
7183
|
+
if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true });
|
|
7114
7184
|
const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
|
|
7115
|
-
|
|
7185
|
+
writeFileSync5(servicePath, unit);
|
|
7116
7186
|
chmodSync(servicePath, 384);
|
|
7117
7187
|
try {
|
|
7118
7188
|
execFileSync3("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -7135,7 +7205,7 @@ WantedBy=default.target
|
|
|
7135
7205
|
*/
|
|
7136
7206
|
uninstall() {
|
|
7137
7207
|
const servicePath = this.getServicePath();
|
|
7138
|
-
if (!
|
|
7208
|
+
if (!existsSync7(servicePath)) {
|
|
7139
7209
|
return { removed: false, message: "Service is not installed." };
|
|
7140
7210
|
}
|
|
7141
7211
|
if (this.os === "darwin") {
|
|
@@ -7173,7 +7243,7 @@ WantedBy=default.target
|
|
|
7173
7243
|
status() {
|
|
7174
7244
|
const servicePath = this.getServicePath();
|
|
7175
7245
|
const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
|
|
7176
|
-
const installed =
|
|
7246
|
+
const installed = existsSync7(servicePath);
|
|
7177
7247
|
let running = false;
|
|
7178
7248
|
if (installed) {
|
|
7179
7249
|
if (this.os === "darwin") {
|
|
@@ -7228,34 +7298,34 @@ WantedBy=default.target
|
|
|
7228
7298
|
needsRepair() {
|
|
7229
7299
|
if (this.os !== "darwin" && this.os !== "linux") return null;
|
|
7230
7300
|
const servicePath = this.getServicePath();
|
|
7231
|
-
if (!
|
|
7301
|
+
if (!existsSync7(servicePath)) return null;
|
|
7232
7302
|
let serviceContent = "";
|
|
7233
7303
|
try {
|
|
7234
|
-
serviceContent =
|
|
7304
|
+
serviceContent = readFileSync4(servicePath, "utf-8");
|
|
7235
7305
|
} catch {
|
|
7236
7306
|
return { reason: "Service file unreadable" };
|
|
7237
7307
|
}
|
|
7238
|
-
const startScript =
|
|
7308
|
+
const startScript = join10(homedir8(), ".agenticmail", "bin", "start-server.sh");
|
|
7239
7309
|
if (serviceContent.includes(startScript)) {
|
|
7240
|
-
if (!
|
|
7310
|
+
if (!existsSync7(startScript)) {
|
|
7241
7311
|
return { reason: "start-server.sh is missing" };
|
|
7242
7312
|
}
|
|
7243
7313
|
let scriptContent = "";
|
|
7244
7314
|
try {
|
|
7245
|
-
scriptContent =
|
|
7315
|
+
scriptContent = readFileSync4(startScript, "utf-8");
|
|
7246
7316
|
} catch {
|
|
7247
7317
|
return { reason: "start-server.sh unreadable" };
|
|
7248
7318
|
}
|
|
7249
7319
|
const apiPathMatch = scriptContent.match(/(\/[^"\s]+@agenticmail\/api\/dist\/index\.js)/);
|
|
7250
7320
|
if (apiPathMatch) {
|
|
7251
7321
|
const referenced = apiPathMatch[1];
|
|
7252
|
-
if (!
|
|
7322
|
+
if (!existsSync7(referenced)) {
|
|
7253
7323
|
return { reason: `start-server.sh references missing path: ${referenced}` };
|
|
7254
7324
|
}
|
|
7255
7325
|
}
|
|
7256
7326
|
if (/node_modules\/agenticmail\/(?!.*@agenticmail\/cli)/.test(scriptContent)) {
|
|
7257
7327
|
const stale = /(\S*node_modules\/agenticmail\/\S*)/.exec(scriptContent)?.[1];
|
|
7258
|
-
if (stale && !
|
|
7328
|
+
if (stale && !existsSync7(stale)) {
|
|
7259
7329
|
return { reason: `start-server.sh references legacy unscoped path: ${stale}` };
|
|
7260
7330
|
}
|
|
7261
7331
|
}
|
|
@@ -7268,11 +7338,11 @@ WantedBy=default.target
|
|
|
7268
7338
|
return { reason: `Service version drift (current CLI is v${currentVersion})` };
|
|
7269
7339
|
}
|
|
7270
7340
|
}
|
|
7271
|
-
const entryCache =
|
|
7272
|
-
if (
|
|
7341
|
+
const entryCache = join10(homedir8(), ".agenticmail", "api-entry.path");
|
|
7342
|
+
if (existsSync7(entryCache)) {
|
|
7273
7343
|
try {
|
|
7274
|
-
const cached =
|
|
7275
|
-
if (cached && !
|
|
7344
|
+
const cached = readFileSync4(entryCache, "utf-8").trim();
|
|
7345
|
+
if (cached && !existsSync7(cached)) {
|
|
7276
7346
|
return { reason: `Cached API entry path no longer exists: ${cached}` };
|
|
7277
7347
|
}
|
|
7278
7348
|
} catch {
|
|
@@ -7323,13 +7393,13 @@ var SetupManager = class {
|
|
|
7323
7393
|
* falls back to monorepo location.
|
|
7324
7394
|
*/
|
|
7325
7395
|
getComposePath() {
|
|
7326
|
-
const standalonePath =
|
|
7327
|
-
if (
|
|
7396
|
+
const standalonePath = join11(homedir9(), ".agenticmail", "docker-compose.yml");
|
|
7397
|
+
if (existsSync8(standalonePath)) return standalonePath;
|
|
7328
7398
|
const cwd = process.cwd();
|
|
7329
|
-
const candidates = [cwd,
|
|
7399
|
+
const candidates = [cwd, join11(cwd, "..")];
|
|
7330
7400
|
for (const dir of candidates) {
|
|
7331
|
-
const p =
|
|
7332
|
-
if (
|
|
7401
|
+
const p = join11(dir, "docker-compose.yml");
|
|
7402
|
+
if (existsSync8(p)) return p;
|
|
7333
7403
|
}
|
|
7334
7404
|
return standalonePath;
|
|
7335
7405
|
}
|
|
@@ -7339,19 +7409,19 @@ var SetupManager = class {
|
|
|
7339
7409
|
* Always regenerates Docker files to keep passwords in sync.
|
|
7340
7410
|
*/
|
|
7341
7411
|
initConfig() {
|
|
7342
|
-
const dataDir =
|
|
7343
|
-
const configPath =
|
|
7344
|
-
const envPath =
|
|
7345
|
-
if (
|
|
7412
|
+
const dataDir = join11(homedir9(), ".agenticmail");
|
|
7413
|
+
const configPath = join11(dataDir, "config.json");
|
|
7414
|
+
const envPath = join11(dataDir, ".env");
|
|
7415
|
+
if (existsSync8(configPath)) {
|
|
7346
7416
|
try {
|
|
7347
|
-
const existing = JSON.parse(
|
|
7417
|
+
const existing = JSON.parse(readFileSync5(configPath, "utf-8"));
|
|
7348
7418
|
this.generateDockerFiles(existing);
|
|
7349
7419
|
return { configPath, envPath, config: existing, isNew: false };
|
|
7350
7420
|
} catch {
|
|
7351
7421
|
}
|
|
7352
7422
|
}
|
|
7353
|
-
if (!
|
|
7354
|
-
|
|
7423
|
+
if (!existsSync8(dataDir)) {
|
|
7424
|
+
mkdirSync7(dataDir, { recursive: true });
|
|
7355
7425
|
}
|
|
7356
7426
|
const masterKey = `mk_${randomBytes3(24).toString("hex")}`;
|
|
7357
7427
|
const stalwartPassword = randomBytes3(16).toString("hex");
|
|
@@ -7367,7 +7437,7 @@ var SetupManager = class {
|
|
|
7367
7437
|
api: { port: 3829, host: "127.0.0.1" },
|
|
7368
7438
|
dataDir
|
|
7369
7439
|
};
|
|
7370
|
-
|
|
7440
|
+
writeFileSync6(configPath, JSON.stringify(config, null, 2));
|
|
7371
7441
|
chmodSync2(configPath, 384);
|
|
7372
7442
|
const envContent = `# Auto-generated by agenticmail setup
|
|
7373
7443
|
STALWART_ADMIN_USER=admin
|
|
@@ -7383,7 +7453,7 @@ SMTP_PORT=587
|
|
|
7383
7453
|
IMAP_HOST=localhost
|
|
7384
7454
|
IMAP_PORT=143
|
|
7385
7455
|
`;
|
|
7386
|
-
|
|
7456
|
+
writeFileSync6(envPath, envContent);
|
|
7387
7457
|
chmodSync2(envPath, 384);
|
|
7388
7458
|
this.generateDockerFiles(config);
|
|
7389
7459
|
return { configPath, envPath, config, isNew: true };
|
|
@@ -7393,13 +7463,13 @@ IMAP_PORT=143
|
|
|
7393
7463
|
* with the correct admin password from config.
|
|
7394
7464
|
*/
|
|
7395
7465
|
generateDockerFiles(config) {
|
|
7396
|
-
const dataDir = config.dataDir ||
|
|
7397
|
-
if (!
|
|
7398
|
-
|
|
7466
|
+
const dataDir = config.dataDir || join11(homedir9(), ".agenticmail");
|
|
7467
|
+
if (!existsSync8(dataDir)) {
|
|
7468
|
+
mkdirSync7(dataDir, { recursive: true });
|
|
7399
7469
|
}
|
|
7400
7470
|
const password = config.stalwart?.adminPassword || "changeme";
|
|
7401
|
-
const composePath =
|
|
7402
|
-
|
|
7471
|
+
const composePath = join11(dataDir, "docker-compose.yml");
|
|
7472
|
+
writeFileSync6(composePath, `services:
|
|
7403
7473
|
stalwart:
|
|
7404
7474
|
# Pinned to v0.15.5 \u2014 Stalwart 0.16+ moved its config to JSON
|
|
7405
7475
|
# at /etc/stalwart/config.json (hardcoded into the container
|
|
@@ -7429,8 +7499,8 @@ volumes:
|
|
|
7429
7499
|
stalwart-data:
|
|
7430
7500
|
`);
|
|
7431
7501
|
chmodSync2(composePath, 384);
|
|
7432
|
-
const tomlPath =
|
|
7433
|
-
|
|
7502
|
+
const tomlPath = join11(dataDir, "stalwart.toml");
|
|
7503
|
+
writeFileSync6(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
|
|
7434
7504
|
|
|
7435
7505
|
[server]
|
|
7436
7506
|
hostname = "localhost"
|
|
@@ -7486,8 +7556,8 @@ secret = "${password}"
|
|
|
7486
7556
|
* Check if config has already been initialized.
|
|
7487
7557
|
*/
|
|
7488
7558
|
isInitialized() {
|
|
7489
|
-
const configPath =
|
|
7490
|
-
return
|
|
7559
|
+
const configPath = join11(homedir9(), ".agenticmail", "config.json");
|
|
7560
|
+
return existsSync8(configPath);
|
|
7491
7561
|
}
|
|
7492
7562
|
};
|
|
7493
7563
|
|
|
@@ -7526,18 +7596,18 @@ function threadIdFor(input) {
|
|
|
7526
7596
|
|
|
7527
7597
|
// src/threading/thread-cache.ts
|
|
7528
7598
|
import {
|
|
7529
|
-
existsSync as
|
|
7530
|
-
mkdirSync as
|
|
7531
|
-
readFileSync as
|
|
7532
|
-
writeFileSync as
|
|
7599
|
+
existsSync as existsSync9,
|
|
7600
|
+
mkdirSync as mkdirSync8,
|
|
7601
|
+
readFileSync as readFileSync6,
|
|
7602
|
+
writeFileSync as writeFileSync7,
|
|
7533
7603
|
readdirSync,
|
|
7534
7604
|
statSync,
|
|
7535
7605
|
rmSync,
|
|
7536
|
-
renameSync
|
|
7606
|
+
renameSync as renameSync2
|
|
7537
7607
|
} from "fs";
|
|
7538
|
-
import { homedir as
|
|
7539
|
-
import { join as
|
|
7540
|
-
var CACHE_DIR_DEFAULT =
|
|
7608
|
+
import { homedir as homedir10 } from "os";
|
|
7609
|
+
import { join as join12 } from "path";
|
|
7610
|
+
var CACHE_DIR_DEFAULT = join12(homedir10(), ".agenticmail", "thread-cache");
|
|
7541
7611
|
var DEFAULT_K_MESSAGES = 10;
|
|
7542
7612
|
var DEFAULT_LRU_CAP = 5e3;
|
|
7543
7613
|
var PREVIEW_MAX_CHARS = 240;
|
|
@@ -7550,18 +7620,18 @@ var ThreadCache = class {
|
|
|
7550
7620
|
this.k = opts.k ?? DEFAULT_K_MESSAGES;
|
|
7551
7621
|
this.lruCap = opts.lruCap ?? DEFAULT_LRU_CAP;
|
|
7552
7622
|
try {
|
|
7553
|
-
|
|
7623
|
+
mkdirSync8(this.dir, { recursive: true });
|
|
7554
7624
|
} catch {
|
|
7555
7625
|
}
|
|
7556
7626
|
}
|
|
7557
7627
|
pathFor(threadId) {
|
|
7558
|
-
return
|
|
7628
|
+
return join12(this.dir, `${threadId}.json`);
|
|
7559
7629
|
}
|
|
7560
7630
|
read(threadId) {
|
|
7561
7631
|
const p = this.pathFor(threadId);
|
|
7562
|
-
if (!
|
|
7632
|
+
if (!existsSync9(p)) return null;
|
|
7563
7633
|
try {
|
|
7564
|
-
const raw =
|
|
7634
|
+
const raw = readFileSync6(p, "utf-8");
|
|
7565
7635
|
return JSON.parse(raw);
|
|
7566
7636
|
} catch {
|
|
7567
7637
|
try {
|
|
@@ -7626,8 +7696,8 @@ var ThreadCache = class {
|
|
|
7626
7696
|
writeAtomic(threadId, entry) {
|
|
7627
7697
|
const p = this.pathFor(threadId);
|
|
7628
7698
|
const tmp = `${p}.tmp`;
|
|
7629
|
-
|
|
7630
|
-
|
|
7699
|
+
writeFileSync7(tmp, JSON.stringify(entry), "utf-8");
|
|
7700
|
+
renameSync2(tmp, p);
|
|
7631
7701
|
}
|
|
7632
7702
|
/**
|
|
7633
7703
|
* Best-effort LRU eviction. Runs at most every 256 writes (we
|
|
@@ -7645,7 +7715,7 @@ var ThreadCache = class {
|
|
|
7645
7715
|
}
|
|
7646
7716
|
if (files.length <= this.lruCap) return;
|
|
7647
7717
|
const stats = files.map((f) => {
|
|
7648
|
-
const p =
|
|
7718
|
+
const p = join12(this.dir, f);
|
|
7649
7719
|
try {
|
|
7650
7720
|
return { p, mtime: statSync(p).mtimeMs };
|
|
7651
7721
|
} catch {
|
|
@@ -7676,36 +7746,36 @@ function dedupAndCap(messages, k) {
|
|
|
7676
7746
|
|
|
7677
7747
|
// src/threading/agent-memory.ts
|
|
7678
7748
|
import {
|
|
7679
|
-
existsSync as
|
|
7680
|
-
mkdirSync as
|
|
7681
|
-
readFileSync as
|
|
7682
|
-
writeFileSync as
|
|
7749
|
+
existsSync as existsSync10,
|
|
7750
|
+
mkdirSync as mkdirSync9,
|
|
7751
|
+
readFileSync as readFileSync7,
|
|
7752
|
+
writeFileSync as writeFileSync8,
|
|
7683
7753
|
rmSync as rmSync2,
|
|
7684
|
-
renameSync as
|
|
7754
|
+
renameSync as renameSync3
|
|
7685
7755
|
} from "fs";
|
|
7686
|
-
import { homedir as
|
|
7687
|
-
import { join as
|
|
7688
|
-
var MEMORY_DIR_DEFAULT =
|
|
7756
|
+
import { homedir as homedir11 } from "os";
|
|
7757
|
+
import { join as join13 } from "path";
|
|
7758
|
+
var MEMORY_DIR_DEFAULT = join13(homedir11(), ".agenticmail", "agent-memory");
|
|
7689
7759
|
var AgentMemoryStore = class {
|
|
7690
7760
|
dir;
|
|
7691
7761
|
constructor(opts = {}) {
|
|
7692
7762
|
this.dir = opts.memoryDir ?? MEMORY_DIR_DEFAULT;
|
|
7693
7763
|
try {
|
|
7694
|
-
|
|
7764
|
+
mkdirSync9(this.dir, { recursive: true });
|
|
7695
7765
|
} catch {
|
|
7696
7766
|
}
|
|
7697
7767
|
}
|
|
7698
7768
|
dirFor(agentId) {
|
|
7699
|
-
return
|
|
7769
|
+
return join13(this.dir, sanitizeId(agentId));
|
|
7700
7770
|
}
|
|
7701
7771
|
pathFor(agentId, threadId) {
|
|
7702
|
-
return
|
|
7772
|
+
return join13(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
|
|
7703
7773
|
}
|
|
7704
7774
|
read(agentId, threadId) {
|
|
7705
7775
|
const p = this.pathFor(agentId, threadId);
|
|
7706
|
-
if (!
|
|
7776
|
+
if (!existsSync10(p)) return null;
|
|
7707
7777
|
try {
|
|
7708
|
-
const raw =
|
|
7778
|
+
const raw = readFileSync7(p, "utf-8");
|
|
7709
7779
|
const parsed = parse(raw);
|
|
7710
7780
|
return { ...parsed, raw };
|
|
7711
7781
|
} catch {
|
|
@@ -7715,14 +7785,14 @@ var AgentMemoryStore = class {
|
|
|
7715
7785
|
write(agentId, threadId, fields) {
|
|
7716
7786
|
const agentDir = this.dirFor(agentId);
|
|
7717
7787
|
try {
|
|
7718
|
-
|
|
7788
|
+
mkdirSync9(agentDir, { recursive: true });
|
|
7719
7789
|
} catch {
|
|
7720
7790
|
}
|
|
7721
7791
|
const body = render({ ...fields, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
7722
7792
|
const p = this.pathFor(agentId, threadId);
|
|
7723
7793
|
const tmp = `${p}.tmp`;
|
|
7724
|
-
|
|
7725
|
-
|
|
7794
|
+
writeFileSync8(tmp, body, "utf-8");
|
|
7795
|
+
renameSync3(tmp, p);
|
|
7726
7796
|
}
|
|
7727
7797
|
delete(agentId, threadId) {
|
|
7728
7798
|
try {
|
|
@@ -7790,6 +7860,7 @@ export {
|
|
|
7790
7860
|
CloudflareClient,
|
|
7791
7861
|
DEFAULT_AGENT_NAME,
|
|
7792
7862
|
DEFAULT_AGENT_ROLE,
|
|
7863
|
+
DEFAULT_SESSION_MAX_AGE_MS,
|
|
7793
7864
|
DNSConfigurator,
|
|
7794
7865
|
DependencyChecker,
|
|
7795
7866
|
DependencyInstaller,
|
|
@@ -7826,9 +7897,13 @@ export {
|
|
|
7826
7897
|
ensureDataDir,
|
|
7827
7898
|
extractVerificationCode,
|
|
7828
7899
|
flushTelemetry,
|
|
7900
|
+
forgetHostSession,
|
|
7829
7901
|
getDatabase,
|
|
7902
|
+
hostSessionStoragePath,
|
|
7830
7903
|
isInternalEmail,
|
|
7904
|
+
isSessionFresh,
|
|
7831
7905
|
isValidPhoneNumber,
|
|
7906
|
+
loadHostSession,
|
|
7832
7907
|
normalizeAddress,
|
|
7833
7908
|
normalizePhoneNumber,
|
|
7834
7909
|
normalizeSubject,
|
|
@@ -7841,6 +7916,7 @@ export {
|
|
|
7841
7916
|
safeJoin,
|
|
7842
7917
|
sanitizeEmail,
|
|
7843
7918
|
saveConfig,
|
|
7919
|
+
saveHostSession,
|
|
7844
7920
|
scanOutboundEmail,
|
|
7845
7921
|
scoreEmail,
|
|
7846
7922
|
setTelemetryVersion,
|