@agenticmail/core 0.5.8 → 0.5.9

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.d.ts CHANGED
@@ -1439,6 +1439,20 @@ declare class DependencyInstaller {
1439
1439
  * Validates symlinks aren't broken.
1440
1440
  */
1441
1441
  private findDockerApp;
1442
+ /**
1443
+ * Pre-accept the Docker Desktop license agreement by writing the settings
1444
+ * file that Docker checks on startup. This prevents the license dialog from
1445
+ * appearing and blocking automated setup.
1446
+ *
1447
+ * Docker Desktop checks /Library/Application Support/com.docker.docker/install-settings.json
1448
+ * (system-level, requires sudo) for {"acceptLicense": true}. The --accept-license
1449
+ * flag on the installer binary tries to write this but fails without sudo.
1450
+ *
1451
+ * We try multiple approaches:
1452
+ * 1. Write to the system-level path (may fail without sudo — that's OK)
1453
+ * 2. Write to the user-level Docker settings (Group Containers)
1454
+ */
1455
+ private preAcceptDockerLicense;
1442
1456
  /**
1443
1457
  * Docker.app exists but CLI isn't available or daemon isn't running.
1444
1458
  * Runs the built-in installer silently (--accept-license to link CLI tools),
package/dist/index.js CHANGED
@@ -850,14 +850,14 @@ var StalwartAdmin = class {
850
850
  * Critical for email deliverability — must match the sending domain.
851
851
  */
852
852
  async setHostname(domain) {
853
- const { readFileSync: readFileSync4, writeFileSync: writeFileSync5 } = await import("fs");
853
+ const { readFileSync: readFileSync5, writeFileSync: writeFileSync6 } = await import("fs");
854
854
  const { homedir: homedir8 } = await import("os");
855
855
  const { join: join9 } = await import("path");
856
856
  const configPath = join9(homedir8(), ".agenticmail", "stalwart.toml");
857
857
  try {
858
- let config = readFileSync4(configPath, "utf-8");
858
+ let config = readFileSync5(configPath, "utf-8");
859
859
  config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${domain}"`);
860
- writeFileSync5(configPath, config);
860
+ writeFileSync6(configPath, config);
861
861
  console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
862
862
  } catch (err) {
863
863
  throw new Error(`Failed to set config server.hostname=${domain}`);
@@ -975,12 +975,12 @@ var StalwartAdmin = class {
975
975
  * This bypasses the need for a PTR record on the sending IP.
976
976
  */
977
977
  async configureOutboundRelay(config) {
978
- const { readFileSync: readFileSync4, writeFileSync: writeFileSync5 } = await import("fs");
978
+ const { readFileSync: readFileSync5, writeFileSync: writeFileSync6 } = await import("fs");
979
979
  const { homedir: homedir8 } = await import("os");
980
980
  const { join: join9 } = await import("path");
981
981
  const routeName = config.routeName ?? "gmail";
982
982
  const tomlPath = join9(homedir8(), ".agenticmail", "stalwart.toml");
983
- let toml = readFileSync4(tomlPath, "utf-8");
983
+ let toml = readFileSync5(tomlPath, "utf-8");
984
984
  toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
985
985
  toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
986
986
  toml += `
@@ -999,7 +999,7 @@ auth.secret = "${config.password}"
999
999
  route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
1000
1000
  { else = "'${routeName}'" } ]
1001
1001
  `;
1002
- writeFileSync5(tomlPath, toml, "utf-8");
1002
+ writeFileSync6(tomlPath, toml, "utf-8");
1003
1003
  await this.restartContainer();
1004
1004
  }
1005
1005
  };
@@ -5180,9 +5180,9 @@ var GatewayManager = class {
5180
5180
  const { homedir: homedir8 } = await import("os");
5181
5181
  const backupDir = join4(homedir8(), ".agenticmail");
5182
5182
  const backupPath = join4(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
5183
- const { writeFileSync: writeFileSync5, mkdirSync: mkdirSync5 } = await import("fs");
5183
+ const { writeFileSync: writeFileSync6, mkdirSync: mkdirSync5 } = await import("fs");
5184
5184
  mkdirSync5(backupDir, { recursive: true });
5185
- writeFileSync5(backupPath, JSON.stringify({
5185
+ writeFileSync6(backupPath, JSON.stringify({
5186
5186
  domain,
5187
5187
  zoneId: zone.id,
5188
5188
  backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -5813,7 +5813,7 @@ var RELAY_PRESETS = {
5813
5813
 
5814
5814
  // src/setup/index.ts
5815
5815
  import { randomBytes as randomBytes2 } from "crypto";
5816
- import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, chmodSync } from "fs";
5816
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, chmodSync } from "fs";
5817
5817
  import { join as join8 } from "path";
5818
5818
  import { homedir as homedir7 } from "os";
5819
5819
 
@@ -5894,7 +5894,7 @@ var DependencyChecker = class {
5894
5894
 
5895
5895
  // src/setup/installer.ts
5896
5896
  import { execFileSync as execFileSync2, execSync, spawn as spawnChild } from "child_process";
5897
- import { existsSync as existsSync4, readdirSync, lstatSync, readlinkSync } from "fs";
5897
+ import { existsSync as existsSync4, readdirSync, lstatSync, readlinkSync, writeFileSync as writeFileSync3, readFileSync as readFileSync2 } from "fs";
5898
5898
  import { writeFile, rename, chmod as chmod2, mkdir as mkdir2, unlink } from "fs/promises";
5899
5899
  import { join as join6 } from "path";
5900
5900
  import { homedir as homedir5, platform as platform2, arch as arch2 } from "os";
@@ -6149,6 +6149,57 @@ var DependencyInstaller = class {
6149
6149
  }
6150
6150
  return null;
6151
6151
  }
6152
+ /**
6153
+ * Pre-accept the Docker Desktop license agreement by writing the settings
6154
+ * file that Docker checks on startup. This prevents the license dialog from
6155
+ * appearing and blocking automated setup.
6156
+ *
6157
+ * Docker Desktop checks /Library/Application Support/com.docker.docker/install-settings.json
6158
+ * (system-level, requires sudo) for {"acceptLicense": true}. The --accept-license
6159
+ * flag on the installer binary tries to write this but fails without sudo.
6160
+ *
6161
+ * We try multiple approaches:
6162
+ * 1. Write to the system-level path (may fail without sudo — that's OK)
6163
+ * 2. Write to the user-level Docker settings (Group Containers)
6164
+ */
6165
+ preAcceptDockerLicense() {
6166
+ const systemDir = "/Library/Application Support/com.docker.docker";
6167
+ const systemFile = join6(systemDir, "install-settings.json");
6168
+ const licenseJson = JSON.stringify({ acceptLicense: true });
6169
+ try {
6170
+ if (!existsSync4(systemDir)) {
6171
+ execSync(`mkdir -p "${systemDir}"`, { timeout: 5e3, stdio: "ignore" });
6172
+ }
6173
+ writeFileSync3(systemFile, licenseJson, { mode: 420 });
6174
+ } catch {
6175
+ try {
6176
+ execSync(`sudo -n mkdir -p "${systemDir}" 2>/dev/null && sudo -n tee "${systemFile}" > /dev/null 2>&1`, {
6177
+ timeout: 5e3,
6178
+ input: licenseJson,
6179
+ stdio: ["pipe", "ignore", "ignore"]
6180
+ });
6181
+ } catch {
6182
+ }
6183
+ }
6184
+ try {
6185
+ const userDockerDir = join6(process.env.HOME || "", "Library/Group Containers/group.com.docker");
6186
+ const settingsFile = join6(userDockerDir, "settings-store.json");
6187
+ if (existsSync4(settingsFile)) {
6188
+ const raw = readFileSync2(settingsFile, "utf-8");
6189
+ try {
6190
+ const settings = JSON.parse(raw);
6191
+ if (!settings.AcceptedLicense) {
6192
+ settings.AcceptedLicense = true;
6193
+ writeFileSync3(settingsFile, JSON.stringify(settings, null, 2));
6194
+ }
6195
+ } catch {
6196
+ }
6197
+ } else if (existsSync4(userDockerDir)) {
6198
+ writeFileSync3(settingsFile, JSON.stringify({ AcceptedLicense: true }, null, 2));
6199
+ }
6200
+ } catch {
6201
+ }
6202
+ }
6152
6203
  /**
6153
6204
  * Docker.app exists but CLI isn't available or daemon isn't running.
6154
6205
  * Runs the built-in installer silently (--accept-license to link CLI tools),
@@ -6156,6 +6207,7 @@ var DependencyInstaller = class {
6156
6207
  */
6157
6208
  async setupExistingDockerApp(appPath) {
6158
6209
  const installBin = join6(appPath, "Contents", "MacOS", "install");
6210
+ this.preAcceptDockerLicense();
6159
6211
  if (existsSync4(installBin)) {
6160
6212
  this.onProgress("__progress__:30:Setting up Docker CLI tools...");
6161
6213
  const user = process.env.USER || execSync("whoami", { timeout: 5e3 }).toString().trim();
@@ -6249,6 +6301,7 @@ var DependencyInstaller = class {
6249
6301
  } catch {
6250
6302
  throw new Error("Failed to mount Docker DMG. The download may be corrupted \u2014 try again.");
6251
6303
  }
6304
+ this.preAcceptDockerLicense();
6252
6305
  this.onProgress("__progress__:55:Running Docker installer...");
6253
6306
  const user = process.env.USER || execSync("whoami", { timeout: 5e3 }).toString().trim();
6254
6307
  try {
@@ -6580,7 +6633,7 @@ var DependencyInstaller = class {
6580
6633
 
6581
6634
  // src/setup/service.ts
6582
6635
  import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
6583
- import { existsSync as existsSync5, readFileSync as readFileSync2, writeFileSync as writeFileSync3, unlinkSync, mkdirSync as mkdirSync3 } from "fs";
6636
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync4, unlinkSync, mkdirSync as mkdirSync3 } from "fs";
6584
6637
  import { join as join7 } from "path";
6585
6638
  import { homedir as homedir6, platform as platform3 } from "os";
6586
6639
  var PLIST_LABEL = "com.agenticmail.server";
@@ -6643,7 +6696,7 @@ var ServiceManager = class {
6643
6696
  const dataDir = join7(homedir6(), ".agenticmail");
6644
6697
  const entryCache = join7(dataDir, "api-entry.path");
6645
6698
  if (existsSync5(entryCache)) {
6646
- const cached = readFileSync2(entryCache, "utf-8").trim();
6699
+ const cached = readFileSync3(entryCache, "utf-8").trim();
6647
6700
  if (existsSync5(cached)) return cached;
6648
6701
  }
6649
6702
  throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
@@ -6654,7 +6707,7 @@ var ServiceManager = class {
6654
6707
  cacheApiEntryPath(entryPath) {
6655
6708
  const dataDir = join7(homedir6(), ".agenticmail");
6656
6709
  if (!existsSync5(dataDir)) mkdirSync3(dataDir, { recursive: true });
6657
- writeFileSync3(join7(dataDir, "api-entry.path"), entryPath);
6710
+ writeFileSync4(join7(dataDir, "api-entry.path"), entryPath);
6658
6711
  }
6659
6712
  /**
6660
6713
  * Get the current package version.
@@ -6672,7 +6725,7 @@ var ServiceManager = class {
6672
6725
  }
6673
6726
  for (const p of pkgPaths) {
6674
6727
  if (existsSync5(p)) {
6675
- const pkg = JSON.parse(readFileSync2(p, "utf-8"));
6728
+ const pkg = JSON.parse(readFileSync3(p, "utf-8"));
6676
6729
  if (pkg.version) return pkg.version;
6677
6730
  }
6678
6731
  }
@@ -6738,7 +6791,7 @@ var ServiceManager = class {
6738
6791
  `log "Starting API server: ${nodePath} ${apiEntry}"`,
6739
6792
  `exec "${nodePath}" "${apiEntry}"`
6740
6793
  ].join("\n") + "\n";
6741
- writeFileSync3(scriptPath, script, { mode: 493 });
6794
+ writeFileSync4(scriptPath, script, { mode: 493 });
6742
6795
  return scriptPath;
6743
6796
  }
6744
6797
  /**
@@ -6751,7 +6804,7 @@ var ServiceManager = class {
6751
6804
  * - Service version tracking in env vars
6752
6805
  */
6753
6806
  generatePlist(nodePath, apiEntry, configPath) {
6754
- const config = JSON.parse(readFileSync2(configPath, "utf-8"));
6807
+ const config = JSON.parse(readFileSync3(configPath, "utf-8"));
6755
6808
  const logDir = join7(homedir6(), ".agenticmail", "logs");
6756
6809
  if (!existsSync5(logDir)) mkdirSync3(logDir, { recursive: true });
6757
6810
  const version = this.getVersion();
@@ -6849,7 +6902,7 @@ var ServiceManager = class {
6849
6902
  * - Proper dependency ordering
6850
6903
  */
6851
6904
  generateSystemdUnit(nodePath, apiEntry, configPath) {
6852
- const config = JSON.parse(readFileSync2(configPath, "utf-8"));
6905
+ const config = JSON.parse(readFileSync3(configPath, "utf-8"));
6853
6906
  const dataDir = config.dataDir || join7(homedir6(), ".agenticmail");
6854
6907
  const version = this.getVersion();
6855
6908
  const startScript = this.generateStartScript(nodePath, apiEntry);
@@ -6912,7 +6965,7 @@ WantedBy=default.target
6912
6965
  }
6913
6966
  }
6914
6967
  const plist = this.generatePlist(nodePath, apiEntry, configPath);
6915
- writeFileSync3(servicePath, plist);
6968
+ writeFileSync4(servicePath, plist);
6916
6969
  try {
6917
6970
  execFileSync3("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
6918
6971
  } catch (err) {
@@ -6923,7 +6976,7 @@ WantedBy=default.target
6923
6976
  const dir = join7(homedir6(), ".config", "systemd", "user");
6924
6977
  if (!existsSync5(dir)) mkdirSync3(dir, { recursive: true });
6925
6978
  const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
6926
- writeFileSync3(servicePath, unit);
6979
+ writeFileSync4(servicePath, unit);
6927
6980
  try {
6928
6981
  execFileSync3("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
6929
6982
  execFileSync3("systemctl", ["--user", "enable", SYSTEMD_UNIT], { timeout: 1e4, stdio: "ignore" });
@@ -7074,7 +7127,7 @@ var SetupManager = class {
7074
7127
  const envPath = join8(dataDir, ".env");
7075
7128
  if (existsSync6(configPath)) {
7076
7129
  try {
7077
- const existing = JSON.parse(readFileSync3(configPath, "utf-8"));
7130
+ const existing = JSON.parse(readFileSync4(configPath, "utf-8"));
7078
7131
  this.generateDockerFiles(existing);
7079
7132
  return { configPath, envPath, config: existing, isNew: false };
7080
7133
  } catch {
@@ -7097,7 +7150,7 @@ var SetupManager = class {
7097
7150
  api: { port: 3100, host: "127.0.0.1" },
7098
7151
  dataDir
7099
7152
  };
7100
- writeFileSync4(configPath, JSON.stringify(config, null, 2));
7153
+ writeFileSync5(configPath, JSON.stringify(config, null, 2));
7101
7154
  chmodSync(configPath, 384);
7102
7155
  const envContent = `# Auto-generated by agenticmail setup
7103
7156
  STALWART_ADMIN_USER=admin
@@ -7113,7 +7166,7 @@ SMTP_PORT=587
7113
7166
  IMAP_HOST=localhost
7114
7167
  IMAP_PORT=143
7115
7168
  `;
7116
- writeFileSync4(envPath, envContent);
7169
+ writeFileSync5(envPath, envContent);
7117
7170
  chmodSync(envPath, 384);
7118
7171
  this.generateDockerFiles(config);
7119
7172
  return { configPath, envPath, config, isNew: true };
@@ -7129,7 +7182,7 @@ IMAP_PORT=143
7129
7182
  }
7130
7183
  const password = config.stalwart?.adminPassword || "changeme";
7131
7184
  const composePath = join8(dataDir, "docker-compose.yml");
7132
- writeFileSync4(composePath, `services:
7185
+ writeFileSync5(composePath, `services:
7133
7186
  stalwart:
7134
7187
  image: stalwartlabs/stalwart:latest
7135
7188
  container_name: agenticmail-stalwart
@@ -7152,7 +7205,7 @@ volumes:
7152
7205
  stalwart-data:
7153
7206
  `);
7154
7207
  const tomlPath = join8(dataDir, "stalwart.toml");
7155
- writeFileSync4(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
7208
+ writeFileSync5(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
7156
7209
 
7157
7210
  [server]
7158
7211
  hostname = "localhost"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/core",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Core SDK for AgenticMail \u2014 email, SMS, and phone number access for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",