@agenticmail/core 0.9.6 → 0.9.7

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.js CHANGED
@@ -390,8 +390,8 @@ var MailReceiver = class {
390
390
  }));
391
391
  }
392
392
  /** Create a new IMAP folder */
393
- async createFolder(path) {
394
- await this.client.mailboxCreate(path);
393
+ async createFolder(path2) {
394
+ await this.client.mailboxCreate(path2);
395
395
  }
396
396
  /** Batch mark multiple messages as seen */
397
397
  async batchMarkSeen(uids, mailbox = "INBOX") {
@@ -931,8 +931,8 @@ var StalwartAdmin = class {
931
931
  }
932
932
  baseUrl;
933
933
  authHeader;
934
- async request(method, path, body) {
935
- const url = `${this.baseUrl}/api${path}`;
934
+ async request(method, path2, body) {
935
+ const url = `${this.baseUrl}/api${path2}`;
936
936
  const response = await fetch(url, {
937
937
  method,
938
938
  headers: {
@@ -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: 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");
1096
+ const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
1097
+ const { homedir: homedir13 } = await import("os");
1098
+ const { join: join15 } = await import("path");
1099
+ const configPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
1100
1100
  try {
1101
- let config = readFileSync8(configPath, "utf-8");
1101
+ let config = readFileSync9(configPath, "utf-8");
1102
1102
  config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
1103
- writeFileSync9(configPath, config);
1103
+ writeFileSync10(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: homedir12 } = __require("os");
1113
- const { join: join14 } = __require("path");
1114
- return join14(homedir12(), ".agenticmail", "stalwart.toml");
1112
+ const { homedir: homedir13 } = __require("os");
1113
+ const { join: join15 } = __require("path");
1114
+ return join15(homedir13(), ".agenticmail", "stalwart.toml");
1115
1115
  }
1116
1116
  /** Path to host-side DKIM key directory */
1117
1117
  get dkimDir() {
1118
- const { homedir: homedir12 } = __require("os");
1119
- const { join: join14 } = __require("path");
1120
- return join14(homedir12(), ".agenticmail");
1118
+ const { homedir: homedir13 } = __require("os");
1119
+ const { join: join15 } = __require("path");
1120
+ return join15(homedir13(), ".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: readFileSync8, writeFileSync: writeFileSync9 } = await import("fs");
1222
- const { homedir: homedir12 } = await import("os");
1223
- const { join: join14 } = await import("path");
1221
+ const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
1222
+ const { homedir: homedir13 } = await import("os");
1223
+ const { join: join15 } = await import("path");
1224
1224
  const routeName = config.routeName ?? "gmail";
1225
- const tomlPath = join14(homedir12(), ".agenticmail", "stalwart.toml");
1226
- let toml = readFileSync8(tomlPath, "utf-8");
1225
+ const tomlPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
1226
+ let toml = readFileSync9(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
- writeFileSync9(tomlPath, toml, "utf-8");
1246
+ writeFileSync10(tomlPath, toml, "utf-8");
1247
1247
  await this.restartContainer();
1248
1248
  }
1249
1249
  };
@@ -1626,11 +1626,11 @@ var AgentDeletionService = class {
1626
1626
  };
1627
1627
  }
1628
1628
  saveToFile(report) {
1629
- const dir = join2(homedir2(), ".agenticmail", "deletions");
1630
- mkdirSync2(dir, { recursive: true });
1629
+ const dir2 = join2(homedir2(), ".agenticmail", "deletions");
1630
+ mkdirSync2(dir2, { recursive: true });
1631
1631
  const timestamp = report.deletedAt.replace(/[:.]/g, "-");
1632
1632
  const filename = `${report.agent.name}_${timestamp}.json`;
1633
- const filePath = join2(dir, filename);
1633
+ const filePath = join2(dir2, filename);
1634
1634
  writeFileSync2(filePath, JSON.stringify(report, null, 2), "utf-8");
1635
1635
  return filePath;
1636
1636
  }
@@ -3917,8 +3917,8 @@ var CloudflareClient = class {
3917
3917
  return resp.result;
3918
3918
  }
3919
3919
  // --- Internal ---
3920
- async request(method, path, body) {
3921
- const url = `${CF_API_BASE}${path}`;
3920
+ async request(method, path2, body) {
3921
+ const url = `${CF_API_BASE}${path2}`;
3922
3922
  const response = await fetch(url, {
3923
3923
  method,
3924
3924
  headers: {
@@ -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: writeFile3, rename: rename2 } = await import("fs/promises");
4243
+ const { writeFile: writeFile4, rename: rename2 } = await import("fs/promises");
4244
4244
  const tmpPath = this.binPath + ".tmp";
4245
- await writeFile3(tmpPath, buffer);
4245
+ await writeFile4(tmpPath, buffer);
4246
4246
  await chmod(tmpPath, 493);
4247
4247
  await rename2(tmpPath, this.binPath);
4248
4248
  return this.binPath;
@@ -4534,6 +4534,33 @@ var SmsManager = class {
4534
4534
  meta.sms = config;
4535
4535
  this.db.prepare("UPDATE agents SET metadata = ?, updated_at = datetime('now') WHERE id = ?").run(JSON.stringify(meta), agentId);
4536
4536
  }
4537
+ /**
4538
+ * Resolve the operator's "where do I get pinged" address from an
4539
+ * agent's SMS config. Used by the dispatcher's bridge-escalation
4540
+ * path: when sub-agents mail a bridge with no fresh host session
4541
+ * available, we email the operator a digest at this address. Their
4542
+ * phone's Gmail push notification surfaces it within seconds —
4543
+ * effectively a free, programmatic alert channel.
4544
+ *
4545
+ * Returns the configured `forwardingEmail` (the same Gmail Google
4546
+ * Voice forwards inbound SMS to, which the operator already has
4547
+ * push notifications enabled for) when SMS is configured AND
4548
+ * enabled. Returns null otherwise — caller falls through to a
4549
+ * silent log + system event.
4550
+ *
4551
+ * Why we don't try real-SMS delivery yet: Google Voice's
4552
+ * `<number>@txt.voice.google.com` email-to-SMS gateway was
4553
+ * deprecated by Google years ago. A future `carrier` field on
4554
+ * SmsConfig (Verizon vtext.com / AT&T txt.att.net / etc) will let
4555
+ * the operator opt into actual SMS, but that's a follow-up — the
4556
+ * email path already gets the operator a phone notification.
4557
+ */
4558
+ getAlertEmail(agentId) {
4559
+ const cfg = this.getSmsConfig(agentId);
4560
+ if (!cfg || !cfg.enabled) return null;
4561
+ if (typeof cfg.forwardingEmail !== "string" || !cfg.forwardingEmail.includes("@")) return null;
4562
+ return cfg.forwardingEmail;
4563
+ }
4537
4564
  /** Remove SMS config from agent metadata */
4538
4565
  removeSmsConfig(agentId) {
4539
4566
  const row = this.db.prepare("SELECT metadata FROM agents WHERE id = ?").get(agentId);
@@ -5149,12 +5176,12 @@ var GatewayManager = class {
5149
5176
  zone = await this.cfClient.createZone(domain);
5150
5177
  }
5151
5178
  const existingRecords = await this.cfClient.listDnsRecords(zone.id);
5152
- const { homedir: homedir12 } = await import("os");
5153
- const backupDir = join4(homedir12(), ".agenticmail");
5179
+ const { homedir: homedir13 } = await import("os");
5180
+ const backupDir = join4(homedir13(), ".agenticmail");
5154
5181
  const backupPath = join4(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
5155
- const { writeFileSync: writeFileSync9, mkdirSync: mkdirSync10 } = await import("fs");
5156
- mkdirSync10(backupDir, { recursive: true });
5157
- writeFileSync9(backupPath, JSON.stringify({
5182
+ const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync11 } = await import("fs");
5183
+ mkdirSync11(backupDir, { recursive: true });
5184
+ writeFileSync10(backupPath, JSON.stringify({
5158
5185
  domain,
5159
5186
  zoneId: zone.id,
5160
5187
  backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -5915,8 +5942,8 @@ function isDisabled() {
5915
5942
  function getInstallId() {
5916
5943
  if (installId) return installId;
5917
5944
  try {
5918
- const dir = join5(homedir4(), ".agenticmail");
5919
- const idFile = join5(dir, ".telemetry-id");
5945
+ const dir2 = join5(homedir4(), ".agenticmail");
5946
+ const idFile = join5(dir2, ".telemetry-id");
5920
5947
  if (existsSync3(idFile)) {
5921
5948
  const id = readFileSync2(idFile, "utf8").trim();
5922
5949
  if (id && id.length > 10) {
@@ -5925,7 +5952,7 @@ function getInstallId() {
5925
5952
  }
5926
5953
  }
5927
5954
  installId = randomUUID();
5928
- if (!existsSync3(dir)) mkdirSync3(dir, { recursive: true });
5955
+ if (!existsSync3(dir2)) mkdirSync3(dir2, { recursive: true });
5929
5956
  writeFileSync3(idFile, installId, "utf8");
5930
5957
  return installId;
5931
5958
  } catch {
@@ -6096,22 +6123,77 @@ function redactObject(input, _depth = 0) {
6096
6123
  return out;
6097
6124
  }
6098
6125
 
6099
- // src/host-sessions.ts
6126
+ // src/operator-prefs.ts
6100
6127
  import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync4 } from "fs";
6101
- import { join as join7 } from "path";
6102
6128
  import { homedir as homedir5 } from "os";
6103
- function storageDir() {
6129
+ import { join as join7 } from "path";
6130
+ function dir() {
6104
6131
  return join7(homedir5(), ".agenticmail");
6105
6132
  }
6133
+ function path() {
6134
+ return join7(dir(), "operator-prefs.json");
6135
+ }
6136
+ function readFile() {
6137
+ if (!existsSync4(path())) return { version: 1 };
6138
+ try {
6139
+ const raw = readFileSync3(path(), "utf-8");
6140
+ if (!raw.trim()) return { version: 1 };
6141
+ const parsed = JSON.parse(raw);
6142
+ return { version: 1, operatorEmail: typeof parsed.operatorEmail === "string" ? parsed.operatorEmail : void 0 };
6143
+ } catch {
6144
+ return { version: 1 };
6145
+ }
6146
+ }
6147
+ function writeFile(shape) {
6148
+ const d = dir();
6149
+ const p = path();
6150
+ if (!existsSync4(d)) mkdirSync4(d, { recursive: true });
6151
+ const tmp = `${p}.agenticmail-tmp-${process.pid}`;
6152
+ writeFileSync4(tmp, JSON.stringify(shape, null, 2), "utf-8");
6153
+ renameSync(tmp, p);
6154
+ }
6155
+ function getOperatorEmail() {
6156
+ const shape = readFile();
6157
+ const email = shape.operatorEmail;
6158
+ if (typeof email !== "string") return null;
6159
+ const trimmed = email.trim();
6160
+ return trimmed.length > 0 && trimmed.includes("@") ? trimmed : null;
6161
+ }
6162
+ function setOperatorEmail(email) {
6163
+ const shape = readFile();
6164
+ if (!email || !email.trim()) {
6165
+ delete shape.operatorEmail;
6166
+ writeFile(shape);
6167
+ return null;
6168
+ }
6169
+ const trimmed = email.trim();
6170
+ if (!trimmed.includes("@")) {
6171
+ throw new Error("operator email must contain an @");
6172
+ }
6173
+ shape.operatorEmail = trimmed;
6174
+ writeFile(shape);
6175
+ return trimmed;
6176
+ }
6177
+ function operatorPrefsStoragePath() {
6178
+ return path();
6179
+ }
6180
+
6181
+ // src/host-sessions.ts
6182
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "fs";
6183
+ import { join as join8 } from "path";
6184
+ import { homedir as homedir6 } from "os";
6185
+ function storageDir() {
6186
+ return join8(homedir6(), ".agenticmail");
6187
+ }
6106
6188
  function storagePath() {
6107
- return join7(storageDir(), "host-sessions.json");
6189
+ return join8(storageDir(), "host-sessions.json");
6108
6190
  }
6109
6191
  var DEFAULT_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
6110
- function readFile() {
6192
+ function readFile2() {
6111
6193
  const p = storagePath();
6112
- if (!existsSync4(p)) return { version: 1, sessions: {} };
6194
+ if (!existsSync5(p)) return { version: 1, sessions: {} };
6113
6195
  try {
6114
- const raw = readFileSync3(p, "utf-8");
6196
+ const raw = readFileSync4(p, "utf-8");
6115
6197
  if (!raw.trim()) return { version: 1, sessions: {} };
6116
6198
  const parsed = JSON.parse(raw);
6117
6199
  return {
@@ -6122,28 +6204,28 @@ function readFile() {
6122
6204
  return { version: 1, sessions: {} };
6123
6205
  }
6124
6206
  }
6125
- function writeFile(shape) {
6126
- const dir = storageDir();
6207
+ function writeFile2(shape) {
6208
+ const dir2 = storageDir();
6127
6209
  const p = storagePath();
6128
- if (!existsSync4(dir)) mkdirSync4(dir, { recursive: true });
6210
+ if (!existsSync5(dir2)) mkdirSync5(dir2, { recursive: true });
6129
6211
  const tmp = `${p}.agenticmail-tmp-${process.pid}`;
6130
- writeFileSync4(tmp, JSON.stringify(shape, null, 2), "utf-8");
6131
- renameSync(tmp, p);
6212
+ writeFileSync5(tmp, JSON.stringify(shape, null, 2), "utf-8");
6213
+ renameSync2(tmp, p);
6132
6214
  }
6133
6215
  function saveHostSession(host, session) {
6134
6216
  if (!session.sessionId) return;
6135
6217
  try {
6136
- const shape = readFile();
6218
+ const shape = readFile2();
6137
6219
  shape.sessions[host] = {
6138
6220
  ...session,
6139
6221
  lastSeenMs: Date.now()
6140
6222
  };
6141
- writeFile(shape);
6223
+ writeFile2(shape);
6142
6224
  } catch {
6143
6225
  }
6144
6226
  }
6145
6227
  function loadHostSession(host, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
6146
- const shape = readFile();
6228
+ const shape = readFile2();
6147
6229
  const record = shape.sessions[host];
6148
6230
  if (!record) return null;
6149
6231
  if (!isSessionFresh(record, maxAgeMs)) return null;
@@ -6155,10 +6237,10 @@ function isSessionFresh(session, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
6155
6237
  }
6156
6238
  function forgetHostSession(host) {
6157
6239
  try {
6158
- const shape = readFile();
6240
+ const shape = readFile2();
6159
6241
  if (!shape.sessions[host]) return;
6160
6242
  delete shape.sessions[host];
6161
- writeFile(shape);
6243
+ writeFile2(shape);
6162
6244
  } catch {
6163
6245
  }
6164
6246
  }
@@ -6208,21 +6290,21 @@ function validateApiUrl(raw) {
6208
6290
  return parsed.origin;
6209
6291
  }
6210
6292
  function buildApiUrl(baseOrigin, pathAndQuery) {
6211
- const path = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
6212
- return new URL(path, baseOrigin + "/").toString();
6293
+ const path2 = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
6294
+ return new URL(path2, baseOrigin + "/").toString();
6213
6295
  }
6214
6296
 
6215
6297
  // src/setup/index.ts
6216
6298
  import { randomBytes as randomBytes3 } from "crypto";
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";
6299
+ import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, chmodSync as chmodSync2 } from "fs";
6300
+ import { join as join12 } from "path";
6301
+ import { homedir as homedir10 } from "os";
6220
6302
 
6221
6303
  // src/setup/deps.ts
6222
6304
  import { execFileSync } from "child_process";
6223
- import { existsSync as existsSync5 } from "fs";
6224
- import { join as join8 } from "path";
6225
- import { homedir as homedir6 } from "os";
6305
+ import { existsSync as existsSync6 } from "fs";
6306
+ import { join as join9 } from "path";
6307
+ import { homedir as homedir7 } from "os";
6226
6308
  var DependencyChecker = class {
6227
6309
  async checkAll() {
6228
6310
  return Promise.all([
@@ -6272,8 +6354,8 @@ var DependencyChecker = class {
6272
6354
  }
6273
6355
  }
6274
6356
  async checkCloudflared() {
6275
- const binPath = join8(homedir6(), ".agenticmail", "bin", "cloudflared");
6276
- if (existsSync5(binPath)) {
6357
+ const binPath = join9(homedir7(), ".agenticmail", "bin", "cloudflared");
6358
+ if (existsSync6(binPath)) {
6277
6359
  let version;
6278
6360
  try {
6279
6361
  const output = execFileSync(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
@@ -6295,10 +6377,10 @@ var DependencyChecker = class {
6295
6377
 
6296
6378
  // src/setup/installer.ts
6297
6379
  import { execFileSync as execFileSync2, execSync, spawn as spawnChild } from "child_process";
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";
6380
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, symlinkSync } from "fs";
6381
+ import { writeFile as writeFile3, rename, chmod as chmod2, mkdir as mkdir2, unlink } from "fs/promises";
6382
+ import { join as join10 } from "path";
6383
+ import { homedir as homedir8, platform as platform3, arch as arch2 } from "os";
6302
6384
  function runShellWithRollingOutput(cmd, opts = {}) {
6303
6385
  const maxLines = opts.maxLines ?? 20;
6304
6386
  const timeout = opts.timeout ?? 3e5;
@@ -6474,11 +6556,11 @@ var DependencyInstaller = class {
6474
6556
  try {
6475
6557
  const composeBin = execFileSync2("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
6476
6558
  if (!composeBin) return;
6477
- const pluginDir = join9(homedir7(), ".docker", "cli-plugins");
6478
- const pluginPath = join9(pluginDir, "docker-compose");
6479
- if (existsSync6(pluginPath)) return;
6559
+ const pluginDir = join10(homedir8(), ".docker", "cli-plugins");
6560
+ const pluginPath = join10(pluginDir, "docker-compose");
6561
+ if (existsSync7(pluginPath)) return;
6480
6562
  try {
6481
- mkdirSync5(pluginDir, { recursive: true });
6563
+ mkdirSync6(pluginDir, { recursive: true });
6482
6564
  } catch {
6483
6565
  }
6484
6566
  try {
@@ -6541,9 +6623,9 @@ var DependencyInstaller = class {
6541
6623
  return;
6542
6624
  }
6543
6625
  this.onProgress("__progress__:5:Installing Docker Engine...");
6544
- const tmpDir = join9(homedir7(), ".agenticmail", "tmp");
6626
+ const tmpDir = join10(homedir8(), ".agenticmail", "tmp");
6545
6627
  await mkdir2(tmpDir, { recursive: true });
6546
- const scriptPath = join9(tmpDir, "install-docker.sh");
6628
+ const scriptPath = join10(tmpDir, "install-docker.sh");
6547
6629
  const dlResult = await runShellWithRollingOutput(
6548
6630
  `curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
6549
6631
  { timeout: 3e5 }
@@ -6611,8 +6693,8 @@ var DependencyInstaller = class {
6611
6693
  }
6612
6694
  try {
6613
6695
  const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
6614
- const dockerExe = join9(programFiles, "Docker", "Docker", "Docker Desktop.exe");
6615
- if (existsSync6(dockerExe)) {
6696
+ const dockerExe = join10(programFiles, "Docker", "Docker", "Docker Desktop.exe");
6697
+ if (existsSync7(dockerExe)) {
6616
6698
  execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
6617
6699
  }
6618
6700
  } catch {
@@ -6662,8 +6744,8 @@ var DependencyInstaller = class {
6662
6744
  this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
6663
6745
  try {
6664
6746
  const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
6665
- const dockerExe = join9(programFiles, "Docker", "Docker", "Docker Desktop.exe");
6666
- if (existsSync6(dockerExe)) {
6747
+ const dockerExe = join10(programFiles, "Docker", "Docker", "Docker Desktop.exe");
6748
+ if (existsSync7(dockerExe)) {
6667
6749
  execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
6668
6750
  }
6669
6751
  } catch {
@@ -6700,7 +6782,7 @@ var DependencyInstaller = class {
6700
6782
  * Start the Stalwart mail server Docker container.
6701
6783
  */
6702
6784
  async startStalwart(composePath) {
6703
- if (!existsSync6(composePath)) {
6785
+ if (!existsSync7(composePath)) {
6704
6786
  throw new Error(`docker-compose.yml not found at: ${composePath}`);
6705
6787
  }
6706
6788
  if (!this.isDockerReady()) {
@@ -6759,16 +6841,16 @@ var DependencyInstaller = class {
6759
6841
  */
6760
6842
  async installCloudflared() {
6761
6843
  const os = platform3();
6762
- const binDir = join9(homedir7(), ".agenticmail", "bin");
6844
+ const binDir = join10(homedir8(), ".agenticmail", "bin");
6763
6845
  const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
6764
- const binPath = join9(binDir, binName);
6765
- if (existsSync6(binPath)) {
6846
+ const binPath = join10(binDir, binName);
6847
+ if (existsSync7(binPath)) {
6766
6848
  return binPath;
6767
6849
  }
6768
6850
  try {
6769
6851
  const whichCmd = os === "win32" ? "where" : "which";
6770
6852
  const sysPath = execFileSync2(whichCmd, ["cloudflared"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n")[0];
6771
- if (sysPath && existsSync6(sysPath)) return sysPath;
6853
+ if (sysPath && existsSync7(sysPath)) return sysPath;
6772
6854
  } catch {
6773
6855
  }
6774
6856
  this.onProgress("Downloading cloudflared...");
@@ -6791,8 +6873,8 @@ var DependencyInstaller = class {
6791
6873
  }
6792
6874
  const buffer = Buffer.from(await response.arrayBuffer());
6793
6875
  if (os === "darwin") {
6794
- const tgzPath = join9(binDir, "cloudflared.tgz");
6795
- await writeFile2(tgzPath, buffer);
6876
+ const tgzPath = join10(binDir, "cloudflared.tgz");
6877
+ await writeFile3(tgzPath, buffer);
6796
6878
  try {
6797
6879
  execFileSync2("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
6798
6880
  await chmod2(binPath, 493);
@@ -6804,11 +6886,11 @@ var DependencyInstaller = class {
6804
6886
  }
6805
6887
  } else {
6806
6888
  const tmpPath = binPath + ".tmp";
6807
- await writeFile2(tmpPath, buffer);
6889
+ await writeFile3(tmpPath, buffer);
6808
6890
  if (os !== "win32") await chmod2(tmpPath, 493);
6809
6891
  await rename(tmpPath, binPath);
6810
6892
  }
6811
- if (!existsSync6(binPath)) {
6893
+ if (!existsSync7(binPath)) {
6812
6894
  throw new Error("cloudflared download succeeded but binary not found after extraction");
6813
6895
  }
6814
6896
  this.onProgress("cloudflared installed");
@@ -6826,9 +6908,9 @@ var DependencyInstaller = class {
6826
6908
 
6827
6909
  // src/setup/service.ts
6828
6910
  import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
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";
6911
+ import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync6, unlinkSync, mkdirSync as mkdirSync7, chmodSync } from "fs";
6912
+ import { join as join11 } from "path";
6913
+ import { homedir as homedir9, platform as platform4 } from "os";
6832
6914
  import { createRequire as createRequire2 } from "module";
6833
6915
  var PLIST_LABEL = "com.agenticmail.server";
6834
6916
  var SYSTEMD_UNIT = "agenticmail.service";
@@ -6839,9 +6921,9 @@ var ServiceManager = class {
6839
6921
  */
6840
6922
  getServicePath() {
6841
6923
  if (this.os === "darwin") {
6842
- return join10(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
6924
+ return join11(homedir9(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
6843
6925
  } else {
6844
- return join10(homedir8(), ".config", "systemd", "user", SYSTEMD_UNIT);
6926
+ return join11(homedir9(), ".config", "systemd", "user", SYSTEMD_UNIT);
6845
6927
  }
6846
6928
  }
6847
6929
  /**
@@ -6875,40 +6957,40 @@ var ServiceManager = class {
6875
6957
  try {
6876
6958
  const req = createRequire2(import.meta.url);
6877
6959
  const resolved = req.resolve("@agenticmail/api");
6878
- if (existsSync7(resolved)) return resolved;
6960
+ if (existsSync8(resolved)) return resolved;
6879
6961
  } catch {
6880
6962
  }
6881
6963
  const parentPackages = [
6882
- join10("@agenticmail", "cli"),
6964
+ join11("@agenticmail", "cli"),
6883
6965
  // current scoped package
6884
6966
  "agenticmail"
6885
6967
  // legacy unscoped package
6886
6968
  ];
6887
6969
  const baseDirs = [
6888
6970
  // user-local install
6889
- join10(homedir8(), "node_modules")
6971
+ join11(homedir9(), "node_modules")
6890
6972
  ];
6891
6973
  try {
6892
6974
  const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
6893
- baseDirs.push(join10(prefix, "lib", "node_modules"));
6894
- baseDirs.push(join10(prefix, "node_modules"));
6975
+ baseDirs.push(join11(prefix, "lib", "node_modules"));
6976
+ baseDirs.push(join11(prefix, "node_modules"));
6895
6977
  } catch {
6896
6978
  }
6897
6979
  baseDirs.push("/opt/homebrew/lib/node_modules");
6898
6980
  baseDirs.push("/usr/local/lib/node_modules");
6899
6981
  for (const base of baseDirs) {
6900
- const sibling = join10(base, "@agenticmail", "api", "dist", "index.js");
6901
- if (existsSync7(sibling)) return sibling;
6982
+ const sibling = join11(base, "@agenticmail", "api", "dist", "index.js");
6983
+ if (existsSync8(sibling)) return sibling;
6902
6984
  for (const parent of parentPackages) {
6903
- const nested = join10(base, parent, "node_modules", "@agenticmail", "api", "dist", "index.js");
6904
- if (existsSync7(nested)) return nested;
6985
+ const nested = join11(base, parent, "node_modules", "@agenticmail", "api", "dist", "index.js");
6986
+ if (existsSync8(nested)) return nested;
6905
6987
  }
6906
6988
  }
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;
6989
+ const dataDir = join11(homedir9(), ".agenticmail");
6990
+ const entryCache = join11(dataDir, "api-entry.path");
6991
+ if (existsSync8(entryCache)) {
6992
+ const cached = readFileSync5(entryCache, "utf-8").trim();
6993
+ if (cached && existsSync8(cached)) return cached;
6912
6994
  }
6913
6995
  throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
6914
6996
  }
@@ -6916,9 +6998,9 @@ var ServiceManager = class {
6916
6998
  * Cache the API entry path so the service can find it later.
6917
6999
  */
6918
7000
  cacheApiEntryPath(entryPath) {
6919
- const dataDir = join10(homedir8(), ".agenticmail");
6920
- if (!existsSync7(dataDir)) mkdirSync6(dataDir, { recursive: true });
6921
- writeFileSync5(join10(dataDir, "api-entry.path"), entryPath);
7001
+ const dataDir = join11(homedir9(), ".agenticmail");
7002
+ if (!existsSync8(dataDir)) mkdirSync7(dataDir, { recursive: true });
7003
+ writeFileSync6(join11(dataDir, "api-entry.path"), entryPath);
6922
7004
  }
6923
7005
  /**
6924
7006
  * Get the current package version.
@@ -6931,36 +7013,36 @@ var ServiceManager = class {
6931
7013
  try {
6932
7014
  const req = createRequire2(import.meta.url);
6933
7015
  const pkgJson = req.resolve("@agenticmail/cli/package.json");
6934
- if (existsSync7(pkgJson)) {
6935
- const pkg = JSON.parse(readFileSync4(pkgJson, "utf-8"));
7016
+ if (existsSync8(pkgJson)) {
7017
+ const pkg = JSON.parse(readFileSync5(pkgJson, "utf-8"));
6936
7018
  if (pkg.version) return pkg.version;
6937
7019
  }
6938
7020
  } catch {
6939
7021
  }
6940
7022
  try {
6941
7023
  const apiEntry = this.getApiEntryPath();
6942
- const apiPkg = join10(apiEntry, "..", "..", "package.json");
6943
- if (existsSync7(apiPkg)) {
6944
- const pkg = JSON.parse(readFileSync4(apiPkg, "utf-8"));
7024
+ const apiPkg = join11(apiEntry, "..", "..", "package.json");
7025
+ if (existsSync8(apiPkg)) {
7026
+ const pkg = JSON.parse(readFileSync5(apiPkg, "utf-8"));
6945
7027
  if (pkg.version) return pkg.version;
6946
7028
  }
6947
7029
  } catch {
6948
7030
  }
6949
7031
  const candidates = [
6950
- join10(homedir8(), "node_modules", "@agenticmail", "cli", "package.json"),
6951
- join10(homedir8(), "node_modules", "agenticmail", "package.json"),
6952
- join10(homedir8(), ".agenticmail", "package-version.json")
7032
+ join11(homedir9(), "node_modules", "@agenticmail", "cli", "package.json"),
7033
+ join11(homedir9(), "node_modules", "agenticmail", "package.json"),
7034
+ join11(homedir9(), ".agenticmail", "package-version.json")
6953
7035
  ];
6954
7036
  try {
6955
7037
  const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
6956
- candidates.push(join10(prefix, "lib", "node_modules", "@agenticmail", "cli", "package.json"));
6957
- candidates.push(join10(prefix, "lib", "node_modules", "agenticmail", "package.json"));
7038
+ candidates.push(join11(prefix, "lib", "node_modules", "@agenticmail", "cli", "package.json"));
7039
+ candidates.push(join11(prefix, "lib", "node_modules", "agenticmail", "package.json"));
6958
7040
  } catch {
6959
7041
  }
6960
7042
  for (const p of candidates) {
6961
7043
  try {
6962
- if (existsSync7(p)) {
6963
- const pkg = JSON.parse(readFileSync4(p, "utf-8"));
7044
+ if (existsSync8(p)) {
7045
+ const pkg = JSON.parse(readFileSync5(p, "utf-8"));
6964
7046
  if (pkg.version) return pkg.version;
6965
7047
  }
6966
7048
  } catch {
@@ -6973,9 +7055,9 @@ var ServiceManager = class {
6973
7055
  * This ensures AgenticMail doesn't fail on boot when Docker is still loading.
6974
7056
  */
6975
7057
  generateStartScript(nodePath, apiEntry) {
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 });
7058
+ const scriptPath = join11(homedir9(), ".agenticmail", "bin", "start-server.sh");
7059
+ const scriptDir = join11(homedir9(), ".agenticmail", "bin");
7060
+ if (!existsSync8(scriptDir)) mkdirSync7(scriptDir, { recursive: true });
6979
7061
  const script = [
6980
7062
  "#!/bin/bash",
6981
7063
  "# AgenticMail auto-start script",
@@ -7026,7 +7108,7 @@ var ServiceManager = class {
7026
7108
  `log "Starting API server: ${nodePath} ${apiEntry}"`,
7027
7109
  `exec "${nodePath}" "${apiEntry}"`
7028
7110
  ].join("\n") + "\n";
7029
- writeFileSync5(scriptPath, script, { mode: 493 });
7111
+ writeFileSync6(scriptPath, script, { mode: 493 });
7030
7112
  return scriptPath;
7031
7113
  }
7032
7114
  /**
@@ -7039,9 +7121,9 @@ var ServiceManager = class {
7039
7121
  * - Service version tracking in env vars
7040
7122
  */
7041
7123
  generatePlist(nodePath, apiEntry, configPath) {
7042
- const config = JSON.parse(readFileSync4(configPath, "utf-8"));
7043
- const logDir = join10(homedir8(), ".agenticmail", "logs");
7044
- if (!existsSync7(logDir)) mkdirSync6(logDir, { recursive: true });
7124
+ const config = JSON.parse(readFileSync5(configPath, "utf-8"));
7125
+ const logDir = join11(homedir9(), ".agenticmail", "logs");
7126
+ if (!existsSync8(logDir)) mkdirSync7(logDir, { recursive: true });
7045
7127
  const version = this.getVersion();
7046
7128
  const startScript = this.generateStartScript(nodePath, apiEntry);
7047
7129
  return `<?xml version="1.0" encoding="UTF-8"?>
@@ -7062,9 +7144,9 @@ var ServiceManager = class {
7062
7144
  <key>EnvironmentVariables</key>
7063
7145
  <dict>
7064
7146
  <key>HOME</key>
7065
- <string>${homedir8()}</string>
7147
+ <string>${homedir9()}</string>
7066
7148
  <key>AGENTICMAIL_DATA_DIR</key>
7067
- <string>${config.dataDir || join10(homedir8(), ".agenticmail")}</string>
7149
+ <string>${config.dataDir || join11(homedir9(), ".agenticmail")}</string>
7068
7150
  <key>PATH</key>
7069
7151
  <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
7070
7152
  <key>AGENTICMAIL_SERVICE_VERSION</key>
@@ -7117,8 +7199,8 @@ var ServiceManager = class {
7117
7199
  * - Proper dependency ordering
7118
7200
  */
7119
7201
  generateSystemdUnit(nodePath, apiEntry, configPath) {
7120
- const config = JSON.parse(readFileSync4(configPath, "utf-8"));
7121
- const dataDir = config.dataDir || join10(homedir8(), ".agenticmail");
7202
+ const config = JSON.parse(readFileSync5(configPath, "utf-8"));
7203
+ const dataDir = config.dataDir || join11(homedir9(), ".agenticmail");
7122
7204
  const version = this.getVersion();
7123
7205
  const startScript = this.generateStartScript(nodePath, apiEntry);
7124
7206
  return `[Unit]
@@ -7135,7 +7217,7 @@ Restart=always
7135
7217
  RestartSec=15
7136
7218
  TimeoutStartSec=660
7137
7219
  LimitNOFILE=8192
7138
- Environment=HOME=${homedir8()}
7220
+ Environment=HOME=${homedir9()}
7139
7221
  Environment=AGENTICMAIL_DATA_DIR=${dataDir}
7140
7222
  Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
7141
7223
  Environment=AGENTICMAIL_SERVICE_VERSION=${version}
@@ -7148,8 +7230,8 @@ WantedBy=default.target
7148
7230
  * Install the auto-start service.
7149
7231
  */
7150
7232
  install() {
7151
- const configPath = join10(homedir8(), ".agenticmail", "config.json");
7152
- if (!existsSync7(configPath)) {
7233
+ const configPath = join11(homedir9(), ".agenticmail", "config.json");
7234
+ if (!existsSync8(configPath)) {
7153
7235
  return { installed: false, message: "Config not found. Run agenticmail setup first." };
7154
7236
  }
7155
7237
  const nodePath = this.getNodePath();
@@ -7161,16 +7243,16 @@ WantedBy=default.target
7161
7243
  }
7162
7244
  const servicePath = this.getServicePath();
7163
7245
  if (this.os === "darwin") {
7164
- const dir = join10(homedir8(), "Library", "LaunchAgents");
7165
- if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true });
7166
- if (existsSync7(servicePath)) {
7246
+ const dir2 = join11(homedir9(), "Library", "LaunchAgents");
7247
+ if (!existsSync8(dir2)) mkdirSync7(dir2, { recursive: true });
7248
+ if (existsSync8(servicePath)) {
7167
7249
  try {
7168
7250
  execFileSync3("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
7169
7251
  } catch {
7170
7252
  }
7171
7253
  }
7172
7254
  const plist = this.generatePlist(nodePath, apiEntry, configPath);
7173
- writeFileSync5(servicePath, plist);
7255
+ writeFileSync6(servicePath, plist);
7174
7256
  chmodSync(servicePath, 384);
7175
7257
  try {
7176
7258
  execFileSync3("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
@@ -7179,10 +7261,10 @@ WantedBy=default.target
7179
7261
  }
7180
7262
  return { installed: true, message: `Service installed at ${servicePath}` };
7181
7263
  } else if (this.os === "linux") {
7182
- const dir = join10(homedir8(), ".config", "systemd", "user");
7183
- if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true });
7264
+ const dir2 = join11(homedir9(), ".config", "systemd", "user");
7265
+ if (!existsSync8(dir2)) mkdirSync7(dir2, { recursive: true });
7184
7266
  const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
7185
- writeFileSync5(servicePath, unit);
7267
+ writeFileSync6(servicePath, unit);
7186
7268
  chmodSync(servicePath, 384);
7187
7269
  try {
7188
7270
  execFileSync3("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
@@ -7205,7 +7287,7 @@ WantedBy=default.target
7205
7287
  */
7206
7288
  uninstall() {
7207
7289
  const servicePath = this.getServicePath();
7208
- if (!existsSync7(servicePath)) {
7290
+ if (!existsSync8(servicePath)) {
7209
7291
  return { removed: false, message: "Service is not installed." };
7210
7292
  }
7211
7293
  if (this.os === "darwin") {
@@ -7243,7 +7325,7 @@ WantedBy=default.target
7243
7325
  status() {
7244
7326
  const servicePath = this.getServicePath();
7245
7327
  const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
7246
- const installed = existsSync7(servicePath);
7328
+ const installed = existsSync8(servicePath);
7247
7329
  let running = false;
7248
7330
  if (installed) {
7249
7331
  if (this.os === "darwin") {
@@ -7298,34 +7380,34 @@ WantedBy=default.target
7298
7380
  needsRepair() {
7299
7381
  if (this.os !== "darwin" && this.os !== "linux") return null;
7300
7382
  const servicePath = this.getServicePath();
7301
- if (!existsSync7(servicePath)) return null;
7383
+ if (!existsSync8(servicePath)) return null;
7302
7384
  let serviceContent = "";
7303
7385
  try {
7304
- serviceContent = readFileSync4(servicePath, "utf-8");
7386
+ serviceContent = readFileSync5(servicePath, "utf-8");
7305
7387
  } catch {
7306
7388
  return { reason: "Service file unreadable" };
7307
7389
  }
7308
- const startScript = join10(homedir8(), ".agenticmail", "bin", "start-server.sh");
7390
+ const startScript = join11(homedir9(), ".agenticmail", "bin", "start-server.sh");
7309
7391
  if (serviceContent.includes(startScript)) {
7310
- if (!existsSync7(startScript)) {
7392
+ if (!existsSync8(startScript)) {
7311
7393
  return { reason: "start-server.sh is missing" };
7312
7394
  }
7313
7395
  let scriptContent = "";
7314
7396
  try {
7315
- scriptContent = readFileSync4(startScript, "utf-8");
7397
+ scriptContent = readFileSync5(startScript, "utf-8");
7316
7398
  } catch {
7317
7399
  return { reason: "start-server.sh unreadable" };
7318
7400
  }
7319
7401
  const apiPathMatch = scriptContent.match(/(\/[^"\s]+@agenticmail\/api\/dist\/index\.js)/);
7320
7402
  if (apiPathMatch) {
7321
7403
  const referenced = apiPathMatch[1];
7322
- if (!existsSync7(referenced)) {
7404
+ if (!existsSync8(referenced)) {
7323
7405
  return { reason: `start-server.sh references missing path: ${referenced}` };
7324
7406
  }
7325
7407
  }
7326
7408
  if (/node_modules\/agenticmail\/(?!.*@agenticmail\/cli)/.test(scriptContent)) {
7327
7409
  const stale = /(\S*node_modules\/agenticmail\/\S*)/.exec(scriptContent)?.[1];
7328
- if (stale && !existsSync7(stale)) {
7410
+ if (stale && !existsSync8(stale)) {
7329
7411
  return { reason: `start-server.sh references legacy unscoped path: ${stale}` };
7330
7412
  }
7331
7413
  }
@@ -7338,11 +7420,11 @@ WantedBy=default.target
7338
7420
  return { reason: `Service version drift (current CLI is v${currentVersion})` };
7339
7421
  }
7340
7422
  }
7341
- const entryCache = join10(homedir8(), ".agenticmail", "api-entry.path");
7342
- if (existsSync7(entryCache)) {
7423
+ const entryCache = join11(homedir9(), ".agenticmail", "api-entry.path");
7424
+ if (existsSync8(entryCache)) {
7343
7425
  try {
7344
- const cached = readFileSync4(entryCache, "utf-8").trim();
7345
- if (cached && !existsSync7(cached)) {
7426
+ const cached = readFileSync5(entryCache, "utf-8").trim();
7427
+ if (cached && !existsSync8(cached)) {
7346
7428
  return { reason: `Cached API entry path no longer exists: ${cached}` };
7347
7429
  }
7348
7430
  } catch {
@@ -7381,8 +7463,8 @@ var SetupManager = class {
7381
7463
  async ensureStalwart(composePath) {
7382
7464
  const status = await this.checker.checkStalwart();
7383
7465
  if (status.installed) return;
7384
- const path = composePath ?? this.getComposePath();
7385
- await this.installer.startStalwart(path);
7466
+ const path2 = composePath ?? this.getComposePath();
7467
+ await this.installer.startStalwart(path2);
7386
7468
  }
7387
7469
  async ensureCloudflared() {
7388
7470
  return this.installer.installCloudflared();
@@ -7393,13 +7475,13 @@ var SetupManager = class {
7393
7475
  * falls back to monorepo location.
7394
7476
  */
7395
7477
  getComposePath() {
7396
- const standalonePath = join11(homedir9(), ".agenticmail", "docker-compose.yml");
7397
- if (existsSync8(standalonePath)) return standalonePath;
7478
+ const standalonePath = join12(homedir10(), ".agenticmail", "docker-compose.yml");
7479
+ if (existsSync9(standalonePath)) return standalonePath;
7398
7480
  const cwd = process.cwd();
7399
- const candidates = [cwd, join11(cwd, "..")];
7400
- for (const dir of candidates) {
7401
- const p = join11(dir, "docker-compose.yml");
7402
- if (existsSync8(p)) return p;
7481
+ const candidates = [cwd, join12(cwd, "..")];
7482
+ for (const dir2 of candidates) {
7483
+ const p = join12(dir2, "docker-compose.yml");
7484
+ if (existsSync9(p)) return p;
7403
7485
  }
7404
7486
  return standalonePath;
7405
7487
  }
@@ -7409,19 +7491,19 @@ var SetupManager = class {
7409
7491
  * Always regenerates Docker files to keep passwords in sync.
7410
7492
  */
7411
7493
  initConfig() {
7412
- const dataDir = join11(homedir9(), ".agenticmail");
7413
- const configPath = join11(dataDir, "config.json");
7414
- const envPath = join11(dataDir, ".env");
7415
- if (existsSync8(configPath)) {
7494
+ const dataDir = join12(homedir10(), ".agenticmail");
7495
+ const configPath = join12(dataDir, "config.json");
7496
+ const envPath = join12(dataDir, ".env");
7497
+ if (existsSync9(configPath)) {
7416
7498
  try {
7417
- const existing = JSON.parse(readFileSync5(configPath, "utf-8"));
7499
+ const existing = JSON.parse(readFileSync6(configPath, "utf-8"));
7418
7500
  this.generateDockerFiles(existing);
7419
7501
  return { configPath, envPath, config: existing, isNew: false };
7420
7502
  } catch {
7421
7503
  }
7422
7504
  }
7423
- if (!existsSync8(dataDir)) {
7424
- mkdirSync7(dataDir, { recursive: true });
7505
+ if (!existsSync9(dataDir)) {
7506
+ mkdirSync8(dataDir, { recursive: true });
7425
7507
  }
7426
7508
  const masterKey = `mk_${randomBytes3(24).toString("hex")}`;
7427
7509
  const stalwartPassword = randomBytes3(16).toString("hex");
@@ -7437,7 +7519,7 @@ var SetupManager = class {
7437
7519
  api: { port: 3829, host: "127.0.0.1" },
7438
7520
  dataDir
7439
7521
  };
7440
- writeFileSync6(configPath, JSON.stringify(config, null, 2));
7522
+ writeFileSync7(configPath, JSON.stringify(config, null, 2));
7441
7523
  chmodSync2(configPath, 384);
7442
7524
  const envContent = `# Auto-generated by agenticmail setup
7443
7525
  STALWART_ADMIN_USER=admin
@@ -7453,7 +7535,7 @@ SMTP_PORT=587
7453
7535
  IMAP_HOST=localhost
7454
7536
  IMAP_PORT=143
7455
7537
  `;
7456
- writeFileSync6(envPath, envContent);
7538
+ writeFileSync7(envPath, envContent);
7457
7539
  chmodSync2(envPath, 384);
7458
7540
  this.generateDockerFiles(config);
7459
7541
  return { configPath, envPath, config, isNew: true };
@@ -7463,13 +7545,13 @@ IMAP_PORT=143
7463
7545
  * with the correct admin password from config.
7464
7546
  */
7465
7547
  generateDockerFiles(config) {
7466
- const dataDir = config.dataDir || join11(homedir9(), ".agenticmail");
7467
- if (!existsSync8(dataDir)) {
7468
- mkdirSync7(dataDir, { recursive: true });
7548
+ const dataDir = config.dataDir || join12(homedir10(), ".agenticmail");
7549
+ if (!existsSync9(dataDir)) {
7550
+ mkdirSync8(dataDir, { recursive: true });
7469
7551
  }
7470
7552
  const password = config.stalwart?.adminPassword || "changeme";
7471
- const composePath = join11(dataDir, "docker-compose.yml");
7472
- writeFileSync6(composePath, `services:
7553
+ const composePath = join12(dataDir, "docker-compose.yml");
7554
+ writeFileSync7(composePath, `services:
7473
7555
  stalwart:
7474
7556
  # Pinned to v0.15.5 \u2014 Stalwart 0.16+ moved its config to JSON
7475
7557
  # at /etc/stalwart/config.json (hardcoded into the container
@@ -7499,8 +7581,8 @@ volumes:
7499
7581
  stalwart-data:
7500
7582
  `);
7501
7583
  chmodSync2(composePath, 384);
7502
- const tomlPath = join11(dataDir, "stalwart.toml");
7503
- writeFileSync6(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
7584
+ const tomlPath = join12(dataDir, "stalwart.toml");
7585
+ writeFileSync7(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
7504
7586
 
7505
7587
  [server]
7506
7588
  hostname = "localhost"
@@ -7556,8 +7638,8 @@ secret = "${password}"
7556
7638
  * Check if config has already been initialized.
7557
7639
  */
7558
7640
  isInitialized() {
7559
- const configPath = join11(homedir9(), ".agenticmail", "config.json");
7560
- return existsSync8(configPath);
7641
+ const configPath = join12(homedir10(), ".agenticmail", "config.json");
7642
+ return existsSync9(configPath);
7561
7643
  }
7562
7644
  };
7563
7645
 
@@ -7596,18 +7678,18 @@ function threadIdFor(input) {
7596
7678
 
7597
7679
  // src/threading/thread-cache.ts
7598
7680
  import {
7599
- existsSync as existsSync9,
7600
- mkdirSync as mkdirSync8,
7601
- readFileSync as readFileSync6,
7602
- writeFileSync as writeFileSync7,
7681
+ existsSync as existsSync10,
7682
+ mkdirSync as mkdirSync9,
7683
+ readFileSync as readFileSync7,
7684
+ writeFileSync as writeFileSync8,
7603
7685
  readdirSync,
7604
7686
  statSync,
7605
7687
  rmSync,
7606
- renameSync as renameSync2
7688
+ renameSync as renameSync3
7607
7689
  } from "fs";
7608
- import { homedir as homedir10 } from "os";
7609
- import { join as join12 } from "path";
7610
- var CACHE_DIR_DEFAULT = join12(homedir10(), ".agenticmail", "thread-cache");
7690
+ import { homedir as homedir11 } from "os";
7691
+ import { join as join13 } from "path";
7692
+ var CACHE_DIR_DEFAULT = join13(homedir11(), ".agenticmail", "thread-cache");
7611
7693
  var DEFAULT_K_MESSAGES = 10;
7612
7694
  var DEFAULT_LRU_CAP = 5e3;
7613
7695
  var PREVIEW_MAX_CHARS = 240;
@@ -7620,18 +7702,18 @@ var ThreadCache = class {
7620
7702
  this.k = opts.k ?? DEFAULT_K_MESSAGES;
7621
7703
  this.lruCap = opts.lruCap ?? DEFAULT_LRU_CAP;
7622
7704
  try {
7623
- mkdirSync8(this.dir, { recursive: true });
7705
+ mkdirSync9(this.dir, { recursive: true });
7624
7706
  } catch {
7625
7707
  }
7626
7708
  }
7627
7709
  pathFor(threadId) {
7628
- return join12(this.dir, `${threadId}.json`);
7710
+ return join13(this.dir, `${threadId}.json`);
7629
7711
  }
7630
7712
  read(threadId) {
7631
7713
  const p = this.pathFor(threadId);
7632
- if (!existsSync9(p)) return null;
7714
+ if (!existsSync10(p)) return null;
7633
7715
  try {
7634
- const raw = readFileSync6(p, "utf-8");
7716
+ const raw = readFileSync7(p, "utf-8");
7635
7717
  return JSON.parse(raw);
7636
7718
  } catch {
7637
7719
  try {
@@ -7696,8 +7778,8 @@ var ThreadCache = class {
7696
7778
  writeAtomic(threadId, entry) {
7697
7779
  const p = this.pathFor(threadId);
7698
7780
  const tmp = `${p}.tmp`;
7699
- writeFileSync7(tmp, JSON.stringify(entry), "utf-8");
7700
- renameSync2(tmp, p);
7781
+ writeFileSync8(tmp, JSON.stringify(entry), "utf-8");
7782
+ renameSync3(tmp, p);
7701
7783
  }
7702
7784
  /**
7703
7785
  * Best-effort LRU eviction. Runs at most every 256 writes (we
@@ -7715,7 +7797,7 @@ var ThreadCache = class {
7715
7797
  }
7716
7798
  if (files.length <= this.lruCap) return;
7717
7799
  const stats = files.map((f) => {
7718
- const p = join12(this.dir, f);
7800
+ const p = join13(this.dir, f);
7719
7801
  try {
7720
7802
  return { p, mtime: statSync(p).mtimeMs };
7721
7803
  } catch {
@@ -7746,36 +7828,36 @@ function dedupAndCap(messages, k) {
7746
7828
 
7747
7829
  // src/threading/agent-memory.ts
7748
7830
  import {
7749
- existsSync as existsSync10,
7750
- mkdirSync as mkdirSync9,
7751
- readFileSync as readFileSync7,
7752
- writeFileSync as writeFileSync8,
7831
+ existsSync as existsSync11,
7832
+ mkdirSync as mkdirSync10,
7833
+ readFileSync as readFileSync8,
7834
+ writeFileSync as writeFileSync9,
7753
7835
  rmSync as rmSync2,
7754
- renameSync as renameSync3
7836
+ renameSync as renameSync4
7755
7837
  } from "fs";
7756
- import { homedir as homedir11 } from "os";
7757
- import { join as join13 } from "path";
7758
- var MEMORY_DIR_DEFAULT = join13(homedir11(), ".agenticmail", "agent-memory");
7838
+ import { homedir as homedir12 } from "os";
7839
+ import { join as join14 } from "path";
7840
+ var MEMORY_DIR_DEFAULT = join14(homedir12(), ".agenticmail", "agent-memory");
7759
7841
  var AgentMemoryStore = class {
7760
7842
  dir;
7761
7843
  constructor(opts = {}) {
7762
7844
  this.dir = opts.memoryDir ?? MEMORY_DIR_DEFAULT;
7763
7845
  try {
7764
- mkdirSync9(this.dir, { recursive: true });
7846
+ mkdirSync10(this.dir, { recursive: true });
7765
7847
  } catch {
7766
7848
  }
7767
7849
  }
7768
7850
  dirFor(agentId) {
7769
- return join13(this.dir, sanitizeId(agentId));
7851
+ return join14(this.dir, sanitizeId(agentId));
7770
7852
  }
7771
7853
  pathFor(agentId, threadId) {
7772
- return join13(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
7854
+ return join14(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
7773
7855
  }
7774
7856
  read(agentId, threadId) {
7775
7857
  const p = this.pathFor(agentId, threadId);
7776
- if (!existsSync10(p)) return null;
7858
+ if (!existsSync11(p)) return null;
7777
7859
  try {
7778
- const raw = readFileSync7(p, "utf-8");
7860
+ const raw = readFileSync8(p, "utf-8");
7779
7861
  const parsed = parse(raw);
7780
7862
  return { ...parsed, raw };
7781
7863
  } catch {
@@ -7785,14 +7867,14 @@ var AgentMemoryStore = class {
7785
7867
  write(agentId, threadId, fields) {
7786
7868
  const agentDir = this.dirFor(agentId);
7787
7869
  try {
7788
- mkdirSync9(agentDir, { recursive: true });
7870
+ mkdirSync10(agentDir, { recursive: true });
7789
7871
  } catch {
7790
7872
  }
7791
7873
  const body = render({ ...fields, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
7792
7874
  const p = this.pathFor(agentId, threadId);
7793
7875
  const tmp = `${p}.tmp`;
7794
- writeFileSync8(tmp, body, "utf-8");
7795
- renameSync3(tmp, p);
7876
+ writeFileSync9(tmp, body, "utf-8");
7877
+ renameSync4(tmp, p);
7796
7878
  }
7797
7879
  delete(agentId, threadId) {
7798
7880
  try {
@@ -7899,6 +7981,7 @@ export {
7899
7981
  flushTelemetry,
7900
7982
  forgetHostSession,
7901
7983
  getDatabase,
7984
+ getOperatorEmail,
7902
7985
  hostSessionStoragePath,
7903
7986
  isInternalEmail,
7904
7987
  isSessionFresh,
@@ -7907,6 +7990,7 @@ export {
7907
7990
  normalizeAddress,
7908
7991
  normalizePhoneNumber,
7909
7992
  normalizeSubject,
7993
+ operatorPrefsStoragePath,
7910
7994
  parseEmail,
7911
7995
  parseGoogleVoiceSms,
7912
7996
  recordToolCall,
@@ -7919,6 +8003,7 @@ export {
7919
8003
  saveHostSession,
7920
8004
  scanOutboundEmail,
7921
8005
  scoreEmail,
8006
+ setOperatorEmail,
7922
8007
  setTelemetryVersion,
7923
8008
  startRelayBridge,
7924
8009
  threadIdFor,