@agenticmail/core 0.5.38 → 0.5.40
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 +22 -1
- package/dist/index.js +234 -126
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1392,6 +1392,27 @@ declare class SmsPoller {
|
|
|
1392
1392
|
private pollOnce;
|
|
1393
1393
|
}
|
|
1394
1394
|
|
|
1395
|
+
/**
|
|
1396
|
+
* AgenticMail Anonymous Telemetry
|
|
1397
|
+
*
|
|
1398
|
+
* Collects anonymous usage counts to help improve the product.
|
|
1399
|
+
* NO personal data, API keys, emails, or content is ever collected.
|
|
1400
|
+
*
|
|
1401
|
+
* Opt out: set AGENTICMAIL_TELEMETRY=0 or DO_NOT_TRACK=1
|
|
1402
|
+
*
|
|
1403
|
+
* What we collect:
|
|
1404
|
+
* - Tool call counts (which tools are popular)
|
|
1405
|
+
* - Package version
|
|
1406
|
+
* - Anonymous install ID (random UUID, no PII)
|
|
1407
|
+
* - OS platform (e.g. "darwin", "linux")
|
|
1408
|
+
*/
|
|
1409
|
+
/** Set the package version for telemetry events */
|
|
1410
|
+
declare function setTelemetryVersion(version: string): void;
|
|
1411
|
+
/** Record a tool call (fire-and-forget, never throws) */
|
|
1412
|
+
declare function recordToolCall(toolName: string): void;
|
|
1413
|
+
/** Flush remaining events on process exit */
|
|
1414
|
+
declare function flushTelemetry(): void;
|
|
1415
|
+
|
|
1395
1416
|
declare function debug(tag: string, message: string): void;
|
|
1396
1417
|
declare function debugWarn(tag: string, message: string): void;
|
|
1397
1418
|
|
|
@@ -1640,4 +1661,4 @@ declare class SetupManager {
|
|
|
1640
1661
|
isInitialized(): boolean;
|
|
1641
1662
|
}
|
|
1642
1663
|
|
|
1643
|
-
export { AGENT_ROLES, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, CloudflareClient, type CreateAgentOptions, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DNSConfigurator, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, type EmailEnvelope, EmailSearchIndex, type FolderInfo, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type InboundEmail, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, type LinkAdvisory, type LocalSmtpConfig, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, type ParsedAttachment, type ParsedEmail, type ParsedSms, type PurchasedDomain, RELAY_PRESETS, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, SPAM_THRESHOLD, type SanitizeDetection, type SanitizeResult, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, ServiceManager, type ServiceStatus, type SetupConfig, SetupManager, type SetupResult, type Severity, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type TunnelConfig, TunnelManager, WARNING_THRESHOLD, type WatcherOptions, buildInboundSecurityAdvisory, closeDatabase, createTestDatabase, debug, debugWarn, ensureDataDir, extractVerificationCode, getDatabase, isInternalEmail, isValidPhoneNumber, normalizePhoneNumber, parseEmail, parseGoogleVoiceSms, resolveConfig, sanitizeEmail, saveConfig, scanOutboundEmail, scoreEmail, startRelayBridge };
|
|
1664
|
+
export { AGENT_ROLES, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, CloudflareClient, type CreateAgentOptions, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DNSConfigurator, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, type EmailEnvelope, EmailSearchIndex, type FolderInfo, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type InboundEmail, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, type LinkAdvisory, type LocalSmtpConfig, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, type ParsedAttachment, type ParsedEmail, type ParsedSms, type PurchasedDomain, RELAY_PRESETS, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, SPAM_THRESHOLD, type SanitizeDetection, type SanitizeResult, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, ServiceManager, type ServiceStatus, type SetupConfig, SetupManager, type SetupResult, type Severity, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type TunnelConfig, TunnelManager, WARNING_THRESHOLD, type WatcherOptions, buildInboundSecurityAdvisory, closeDatabase, createTestDatabase, debug, debugWarn, ensureDataDir, extractVerificationCode, flushTelemetry, getDatabase, isInternalEmail, isValidPhoneNumber, normalizePhoneNumber, parseEmail, parseGoogleVoiceSms, recordToolCall, resolveConfig, sanitizeEmail, saveConfig, scanOutboundEmail, scoreEmail, setTelemetryVersion, startRelayBridge };
|
package/dist/index.js
CHANGED
|
@@ -859,14 +859,14 @@ var StalwartAdmin = class {
|
|
|
859
859
|
if (!isValidDomain(domain)) {
|
|
860
860
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
861
861
|
}
|
|
862
|
-
const { readFileSync:
|
|
863
|
-
const { homedir:
|
|
864
|
-
const { join:
|
|
865
|
-
const configPath =
|
|
862
|
+
const { readFileSync: readFileSync5, writeFileSync: writeFileSync6 } = await import("fs");
|
|
863
|
+
const { homedir: homedir9 } = await import("os");
|
|
864
|
+
const { join: join10 } = await import("path");
|
|
865
|
+
const configPath = join10(homedir9(), ".agenticmail", "stalwart.toml");
|
|
866
866
|
try {
|
|
867
|
-
let config =
|
|
867
|
+
let config = readFileSync5(configPath, "utf-8");
|
|
868
868
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
869
|
-
|
|
869
|
+
writeFileSync6(configPath, config);
|
|
870
870
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
871
871
|
} catch (err) {
|
|
872
872
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -875,15 +875,15 @@ var StalwartAdmin = class {
|
|
|
875
875
|
// --- DKIM ---
|
|
876
876
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
877
877
|
get configPath() {
|
|
878
|
-
const { homedir:
|
|
879
|
-
const { join:
|
|
880
|
-
return
|
|
878
|
+
const { homedir: homedir9 } = __require("os");
|
|
879
|
+
const { join: join10 } = __require("path");
|
|
880
|
+
return join10(homedir9(), ".agenticmail", "stalwart.toml");
|
|
881
881
|
}
|
|
882
882
|
/** Path to host-side DKIM key directory */
|
|
883
883
|
get dkimDir() {
|
|
884
|
-
const { homedir:
|
|
885
|
-
const { join:
|
|
886
|
-
return
|
|
884
|
+
const { homedir: homedir9 } = __require("os");
|
|
885
|
+
const { join: join10 } = __require("path");
|
|
886
|
+
return join10(homedir9(), ".agenticmail");
|
|
887
887
|
}
|
|
888
888
|
/**
|
|
889
889
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -984,12 +984,12 @@ var StalwartAdmin = class {
|
|
|
984
984
|
* This bypasses the need for a PTR record on the sending IP.
|
|
985
985
|
*/
|
|
986
986
|
async configureOutboundRelay(config) {
|
|
987
|
-
const { readFileSync:
|
|
988
|
-
const { homedir:
|
|
989
|
-
const { join:
|
|
987
|
+
const { readFileSync: readFileSync5, writeFileSync: writeFileSync6 } = await import("fs");
|
|
988
|
+
const { homedir: homedir9 } = await import("os");
|
|
989
|
+
const { join: join10 } = await import("path");
|
|
990
990
|
const routeName = config.routeName ?? "gmail";
|
|
991
|
-
const tomlPath =
|
|
992
|
-
let toml =
|
|
991
|
+
const tomlPath = join10(homedir9(), ".agenticmail", "stalwart.toml");
|
|
992
|
+
let toml = readFileSync5(tomlPath, "utf-8");
|
|
993
993
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
994
994
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
995
995
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -1009,7 +1009,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
1009
1009
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
1010
1010
|
{ else = "'${safeRouteName}'" } ]
|
|
1011
1011
|
`;
|
|
1012
|
-
|
|
1012
|
+
writeFileSync6(tomlPath, toml, "utf-8");
|
|
1013
1013
|
await this.restartContainer();
|
|
1014
1014
|
}
|
|
1015
1015
|
};
|
|
@@ -5208,12 +5208,12 @@ var GatewayManager = class {
|
|
|
5208
5208
|
zone = await this.cfClient.createZone(domain);
|
|
5209
5209
|
}
|
|
5210
5210
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
5211
|
-
const { homedir:
|
|
5212
|
-
const backupDir = join4(
|
|
5211
|
+
const { homedir: homedir9 } = await import("os");
|
|
5212
|
+
const backupDir = join4(homedir9(), ".agenticmail");
|
|
5213
5213
|
const backupPath = join4(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
5214
|
-
const { writeFileSync:
|
|
5215
|
-
|
|
5216
|
-
|
|
5214
|
+
const { writeFileSync: writeFileSync6, mkdirSync: mkdirSync7 } = await import("fs");
|
|
5215
|
+
mkdirSync7(backupDir, { recursive: true });
|
|
5216
|
+
writeFileSync6(backupPath, JSON.stringify({
|
|
5217
5217
|
domain,
|
|
5218
5218
|
zoneId: zone.id,
|
|
5219
5219
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5901,17 +5901,122 @@ var RELAY_PRESETS = {
|
|
|
5901
5901
|
}
|
|
5902
5902
|
};
|
|
5903
5903
|
|
|
5904
|
+
// src/telemetry.ts
|
|
5905
|
+
import { randomUUID } from "crypto";
|
|
5906
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
|
|
5907
|
+
import { join as join5 } from "path";
|
|
5908
|
+
import { homedir as homedir4 } from "os";
|
|
5909
|
+
import { platform as platform2 } from "process";
|
|
5910
|
+
var TELEMETRY_ENDPOINT = "https://agenticmail.io/api/telemetry";
|
|
5911
|
+
var BATCH_INTERVAL_MS = 6e4;
|
|
5912
|
+
var MAX_BATCH_SIZE = 100;
|
|
5913
|
+
var installId = null;
|
|
5914
|
+
var packageVersion = "unknown";
|
|
5915
|
+
var disabled = null;
|
|
5916
|
+
var batch = [];
|
|
5917
|
+
var flushTimer = null;
|
|
5918
|
+
var flushing = false;
|
|
5919
|
+
function isDisabled() {
|
|
5920
|
+
if (disabled !== null) return disabled;
|
|
5921
|
+
disabled = process.env.AGENTICMAIL_TELEMETRY === "0" || process.env.AGENTICMAIL_TELEMETRY === "false" || process.env.DO_NOT_TRACK === "1" || process.env.DO_NOT_TRACK === "true" || process.env.CI === "true";
|
|
5922
|
+
return disabled;
|
|
5923
|
+
}
|
|
5924
|
+
function getInstallId() {
|
|
5925
|
+
if (installId) return installId;
|
|
5926
|
+
try {
|
|
5927
|
+
const dir = join5(homedir4(), ".agenticmail");
|
|
5928
|
+
const idFile = join5(dir, ".telemetry-id");
|
|
5929
|
+
if (existsSync3(idFile)) {
|
|
5930
|
+
const id = readFileSync2(idFile, "utf8").trim();
|
|
5931
|
+
if (id && id.length > 10) {
|
|
5932
|
+
installId = id;
|
|
5933
|
+
return installId;
|
|
5934
|
+
}
|
|
5935
|
+
}
|
|
5936
|
+
installId = randomUUID();
|
|
5937
|
+
if (!existsSync3(dir)) mkdirSync3(dir, { recursive: true });
|
|
5938
|
+
writeFileSync3(idFile, installId, "utf8");
|
|
5939
|
+
return installId;
|
|
5940
|
+
} catch {
|
|
5941
|
+
installId = randomUUID();
|
|
5942
|
+
return installId;
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5945
|
+
function setTelemetryVersion(version) {
|
|
5946
|
+
packageVersion = version;
|
|
5947
|
+
}
|
|
5948
|
+
function recordToolCall(toolName) {
|
|
5949
|
+
try {
|
|
5950
|
+
if (isDisabled()) return;
|
|
5951
|
+
batch.push({ tool: toolName, ts: Date.now() });
|
|
5952
|
+
if (batch.length >= MAX_BATCH_SIZE) {
|
|
5953
|
+
flush();
|
|
5954
|
+
return;
|
|
5955
|
+
}
|
|
5956
|
+
if (!flushTimer) {
|
|
5957
|
+
flushTimer = setTimeout(() => {
|
|
5958
|
+
flushTimer = null;
|
|
5959
|
+
flush();
|
|
5960
|
+
}, BATCH_INTERVAL_MS);
|
|
5961
|
+
if (flushTimer && typeof flushTimer === "object" && "unref" in flushTimer) {
|
|
5962
|
+
flushTimer.unref();
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
} catch {
|
|
5966
|
+
}
|
|
5967
|
+
}
|
|
5968
|
+
function flush() {
|
|
5969
|
+
if (flushing || batch.length === 0) return;
|
|
5970
|
+
flushing = true;
|
|
5971
|
+
const events = batch;
|
|
5972
|
+
batch = [];
|
|
5973
|
+
const toolCounts = {};
|
|
5974
|
+
for (const e of events) {
|
|
5975
|
+
toolCounts[e.tool] = (toolCounts[e.tool] || 0) + 1;
|
|
5976
|
+
}
|
|
5977
|
+
const payload = {
|
|
5978
|
+
id: getInstallId(),
|
|
5979
|
+
v: packageVersion,
|
|
5980
|
+
p: platform2,
|
|
5981
|
+
tools: toolCounts,
|
|
5982
|
+
n: events.length
|
|
5983
|
+
// total calls in this batch
|
|
5984
|
+
};
|
|
5985
|
+
fetch(TELEMETRY_ENDPOINT, {
|
|
5986
|
+
method: "POST",
|
|
5987
|
+
headers: { "Content-Type": "application/json" },
|
|
5988
|
+
body: JSON.stringify(payload),
|
|
5989
|
+
signal: AbortSignal.timeout(5e3)
|
|
5990
|
+
}).catch(() => {
|
|
5991
|
+
}).finally(() => {
|
|
5992
|
+
flushing = false;
|
|
5993
|
+
});
|
|
5994
|
+
}
|
|
5995
|
+
function flushTelemetry() {
|
|
5996
|
+
if (flushTimer) {
|
|
5997
|
+
clearTimeout(flushTimer);
|
|
5998
|
+
flushTimer = null;
|
|
5999
|
+
}
|
|
6000
|
+
flush();
|
|
6001
|
+
}
|
|
6002
|
+
try {
|
|
6003
|
+
process.on("beforeExit", flushTelemetry);
|
|
6004
|
+
process.on("SIGINT", flushTelemetry);
|
|
6005
|
+
process.on("SIGTERM", flushTelemetry);
|
|
6006
|
+
} catch {
|
|
6007
|
+
}
|
|
6008
|
+
|
|
5904
6009
|
// src/setup/index.ts
|
|
5905
6010
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
5906
|
-
import { existsSync as
|
|
5907
|
-
import { join as
|
|
5908
|
-
import { homedir as
|
|
6011
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, chmodSync as chmodSync2 } from "fs";
|
|
6012
|
+
import { join as join9 } from "path";
|
|
6013
|
+
import { homedir as homedir8 } from "os";
|
|
5909
6014
|
|
|
5910
6015
|
// src/setup/deps.ts
|
|
5911
6016
|
import { execFileSync } from "child_process";
|
|
5912
|
-
import { existsSync as
|
|
5913
|
-
import { join as
|
|
5914
|
-
import { homedir as
|
|
6017
|
+
import { existsSync as existsSync4 } from "fs";
|
|
6018
|
+
import { join as join6 } from "path";
|
|
6019
|
+
import { homedir as homedir5 } from "os";
|
|
5915
6020
|
var DependencyChecker = class {
|
|
5916
6021
|
async checkAll() {
|
|
5917
6022
|
return Promise.all([
|
|
@@ -5961,8 +6066,8 @@ var DependencyChecker = class {
|
|
|
5961
6066
|
}
|
|
5962
6067
|
}
|
|
5963
6068
|
async checkCloudflared() {
|
|
5964
|
-
const binPath =
|
|
5965
|
-
if (
|
|
6069
|
+
const binPath = join6(homedir5(), ".agenticmail", "bin", "cloudflared");
|
|
6070
|
+
if (existsSync4(binPath)) {
|
|
5966
6071
|
let version;
|
|
5967
6072
|
try {
|
|
5968
6073
|
const output = execFileSync(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -5984,10 +6089,10 @@ var DependencyChecker = class {
|
|
|
5984
6089
|
|
|
5985
6090
|
// src/setup/installer.ts
|
|
5986
6091
|
import { execFileSync as execFileSync2, execSync, spawn as spawnChild } from "child_process";
|
|
5987
|
-
import { existsSync as
|
|
6092
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, symlinkSync } from "fs";
|
|
5988
6093
|
import { writeFile, rename, chmod as chmod2, mkdir as mkdir2, unlink } from "fs/promises";
|
|
5989
|
-
import { join as
|
|
5990
|
-
import { homedir as
|
|
6094
|
+
import { join as join7 } from "path";
|
|
6095
|
+
import { homedir as homedir6, platform as platform3, arch as arch2 } from "os";
|
|
5991
6096
|
function runShellWithRollingOutput(cmd, opts = {}) {
|
|
5992
6097
|
const maxLines = opts.maxLines ?? 20;
|
|
5993
6098
|
const timeout = opts.timeout ?? 3e5;
|
|
@@ -6097,7 +6202,7 @@ var DependencyInstaller = class {
|
|
|
6097
6202
|
*/
|
|
6098
6203
|
async installDocker() {
|
|
6099
6204
|
if (this.isDockerReady()) return;
|
|
6100
|
-
const os =
|
|
6205
|
+
const os = platform3();
|
|
6101
6206
|
if (os === "darwin") {
|
|
6102
6207
|
await this.installDockerMac();
|
|
6103
6208
|
} else if (os === "linux") {
|
|
@@ -6163,11 +6268,11 @@ var DependencyInstaller = class {
|
|
|
6163
6268
|
try {
|
|
6164
6269
|
const composeBin = execFileSync2("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6165
6270
|
if (!composeBin) return;
|
|
6166
|
-
const pluginDir =
|
|
6167
|
-
const pluginPath =
|
|
6168
|
-
if (
|
|
6271
|
+
const pluginDir = join7(homedir6(), ".docker", "cli-plugins");
|
|
6272
|
+
const pluginPath = join7(pluginDir, "docker-compose");
|
|
6273
|
+
if (existsSync5(pluginPath)) return;
|
|
6169
6274
|
try {
|
|
6170
|
-
|
|
6275
|
+
mkdirSync4(pluginDir, { recursive: true });
|
|
6171
6276
|
} catch {
|
|
6172
6277
|
}
|
|
6173
6278
|
try {
|
|
@@ -6230,9 +6335,9 @@ var DependencyInstaller = class {
|
|
|
6230
6335
|
return;
|
|
6231
6336
|
}
|
|
6232
6337
|
this.onProgress("__progress__:5:Installing Docker Engine...");
|
|
6233
|
-
const tmpDir =
|
|
6338
|
+
const tmpDir = join7(homedir6(), ".agenticmail", "tmp");
|
|
6234
6339
|
await mkdir2(tmpDir, { recursive: true });
|
|
6235
|
-
const scriptPath =
|
|
6340
|
+
const scriptPath = join7(tmpDir, "install-docker.sh");
|
|
6236
6341
|
const dlResult = await runShellWithRollingOutput(
|
|
6237
6342
|
`curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
|
|
6238
6343
|
{ timeout: 3e5 }
|
|
@@ -6300,8 +6405,8 @@ var DependencyInstaller = class {
|
|
|
6300
6405
|
}
|
|
6301
6406
|
try {
|
|
6302
6407
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
6303
|
-
const dockerExe =
|
|
6304
|
-
if (
|
|
6408
|
+
const dockerExe = join7(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
6409
|
+
if (existsSync5(dockerExe)) {
|
|
6305
6410
|
execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
6306
6411
|
}
|
|
6307
6412
|
} catch {
|
|
@@ -6351,8 +6456,8 @@ var DependencyInstaller = class {
|
|
|
6351
6456
|
this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
|
|
6352
6457
|
try {
|
|
6353
6458
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
6354
|
-
const dockerExe =
|
|
6355
|
-
if (
|
|
6459
|
+
const dockerExe = join7(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
6460
|
+
if (existsSync5(dockerExe)) {
|
|
6356
6461
|
execSync(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
6357
6462
|
}
|
|
6358
6463
|
} catch {
|
|
@@ -6389,12 +6494,12 @@ var DependencyInstaller = class {
|
|
|
6389
6494
|
* Start the Stalwart mail server Docker container.
|
|
6390
6495
|
*/
|
|
6391
6496
|
async startStalwart(composePath) {
|
|
6392
|
-
if (!
|
|
6497
|
+
if (!existsSync5(composePath)) {
|
|
6393
6498
|
throw new Error(`docker-compose.yml not found at: ${composePath}`);
|
|
6394
6499
|
}
|
|
6395
6500
|
if (!this.isDockerReady()) {
|
|
6396
6501
|
this.onProgress("Starting Docker...");
|
|
6397
|
-
const os =
|
|
6502
|
+
const os = platform3();
|
|
6398
6503
|
if (os === "darwin") {
|
|
6399
6504
|
await this.startColima();
|
|
6400
6505
|
} else if (os === "win32") {
|
|
@@ -6412,7 +6517,7 @@ var DependencyInstaller = class {
|
|
|
6412
6517
|
}
|
|
6413
6518
|
}
|
|
6414
6519
|
this.onProgress("__progress__:10:Pulling mail server image...");
|
|
6415
|
-
if (
|
|
6520
|
+
if (platform3() === "darwin") this.linkComposePlugin();
|
|
6416
6521
|
let composeResult = await runSilent("docker", ["compose", "-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
6417
6522
|
if (composeResult.exitCode !== 0 && hasCommand("docker-compose")) {
|
|
6418
6523
|
composeResult = await runSilent("docker-compose", ["-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
@@ -6447,17 +6552,17 @@ var DependencyInstaller = class {
|
|
|
6447
6552
|
* Returns the path to the installed binary.
|
|
6448
6553
|
*/
|
|
6449
6554
|
async installCloudflared() {
|
|
6450
|
-
const os =
|
|
6451
|
-
const binDir =
|
|
6555
|
+
const os = platform3();
|
|
6556
|
+
const binDir = join7(homedir6(), ".agenticmail", "bin");
|
|
6452
6557
|
const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
6453
|
-
const binPath =
|
|
6454
|
-
if (
|
|
6558
|
+
const binPath = join7(binDir, binName);
|
|
6559
|
+
if (existsSync5(binPath)) {
|
|
6455
6560
|
return binPath;
|
|
6456
6561
|
}
|
|
6457
6562
|
try {
|
|
6458
6563
|
const whichCmd = os === "win32" ? "where" : "which";
|
|
6459
6564
|
const sysPath = execFileSync2(whichCmd, ["cloudflared"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n")[0];
|
|
6460
|
-
if (sysPath &&
|
|
6565
|
+
if (sysPath && existsSync5(sysPath)) return sysPath;
|
|
6461
6566
|
} catch {
|
|
6462
6567
|
}
|
|
6463
6568
|
this.onProgress("Downloading cloudflared...");
|
|
@@ -6480,7 +6585,7 @@ var DependencyInstaller = class {
|
|
|
6480
6585
|
}
|
|
6481
6586
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
6482
6587
|
if (os === "darwin") {
|
|
6483
|
-
const tgzPath =
|
|
6588
|
+
const tgzPath = join7(binDir, "cloudflared.tgz");
|
|
6484
6589
|
await writeFile(tgzPath, buffer);
|
|
6485
6590
|
try {
|
|
6486
6591
|
execFileSync2("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
|
|
@@ -6497,7 +6602,7 @@ var DependencyInstaller = class {
|
|
|
6497
6602
|
if (os !== "win32") await chmod2(tmpPath, 493);
|
|
6498
6603
|
await rename(tmpPath, binPath);
|
|
6499
6604
|
}
|
|
6500
|
-
if (!
|
|
6605
|
+
if (!existsSync5(binPath)) {
|
|
6501
6606
|
throw new Error("cloudflared download succeeded but binary not found after extraction");
|
|
6502
6607
|
}
|
|
6503
6608
|
this.onProgress("cloudflared installed");
|
|
@@ -6515,21 +6620,21 @@ var DependencyInstaller = class {
|
|
|
6515
6620
|
|
|
6516
6621
|
// src/setup/service.ts
|
|
6517
6622
|
import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
|
|
6518
|
-
import { existsSync as
|
|
6519
|
-
import { join as
|
|
6520
|
-
import { homedir as
|
|
6623
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync4, unlinkSync, mkdirSync as mkdirSync5, chmodSync } from "fs";
|
|
6624
|
+
import { join as join8 } from "path";
|
|
6625
|
+
import { homedir as homedir7, platform as platform4 } from "os";
|
|
6521
6626
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
6522
6627
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
6523
6628
|
var ServiceManager = class {
|
|
6524
|
-
os =
|
|
6629
|
+
os = platform4();
|
|
6525
6630
|
/**
|
|
6526
6631
|
* Get the path to the service file.
|
|
6527
6632
|
*/
|
|
6528
6633
|
getServicePath() {
|
|
6529
6634
|
if (this.os === "darwin") {
|
|
6530
|
-
return
|
|
6635
|
+
return join8(homedir7(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
6531
6636
|
} else {
|
|
6532
|
-
return
|
|
6637
|
+
return join8(homedir7(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
6533
6638
|
}
|
|
6534
6639
|
}
|
|
6535
6640
|
/**
|
|
@@ -6549,14 +6654,14 @@ var ServiceManager = class {
|
|
|
6549
6654
|
getApiEntryPath() {
|
|
6550
6655
|
const searchDirs = [
|
|
6551
6656
|
// Global npm install
|
|
6552
|
-
|
|
6657
|
+
join8(homedir7(), "node_modules", "agenticmail"),
|
|
6553
6658
|
// npx cache / global prefix
|
|
6554
6659
|
...(() => {
|
|
6555
6660
|
try {
|
|
6556
6661
|
const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6557
6662
|
return [
|
|
6558
|
-
|
|
6559
|
-
|
|
6663
|
+
join8(prefix, "lib", "node_modules", "agenticmail"),
|
|
6664
|
+
join8(prefix, "node_modules", "agenticmail")
|
|
6560
6665
|
];
|
|
6561
6666
|
} catch {
|
|
6562
6667
|
return [];
|
|
@@ -6568,18 +6673,18 @@ var ServiceManager = class {
|
|
|
6568
6673
|
];
|
|
6569
6674
|
for (const base of searchDirs) {
|
|
6570
6675
|
const apiPaths = [
|
|
6571
|
-
|
|
6572
|
-
|
|
6676
|
+
join8(base, "node_modules", "@agenticmail", "api", "dist", "index.js"),
|
|
6677
|
+
join8(base, "..", "@agenticmail", "api", "dist", "index.js")
|
|
6573
6678
|
];
|
|
6574
6679
|
for (const p of apiPaths) {
|
|
6575
|
-
if (
|
|
6680
|
+
if (existsSync6(p)) return p;
|
|
6576
6681
|
}
|
|
6577
6682
|
}
|
|
6578
|
-
const dataDir =
|
|
6579
|
-
const entryCache =
|
|
6580
|
-
if (
|
|
6581
|
-
const cached =
|
|
6582
|
-
if (
|
|
6683
|
+
const dataDir = join8(homedir7(), ".agenticmail");
|
|
6684
|
+
const entryCache = join8(dataDir, "api-entry.path");
|
|
6685
|
+
if (existsSync6(entryCache)) {
|
|
6686
|
+
const cached = readFileSync3(entryCache, "utf-8").trim();
|
|
6687
|
+
if (existsSync6(cached)) return cached;
|
|
6583
6688
|
}
|
|
6584
6689
|
throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
|
|
6585
6690
|
}
|
|
@@ -6587,9 +6692,9 @@ var ServiceManager = class {
|
|
|
6587
6692
|
* Cache the API entry path so the service can find it later.
|
|
6588
6693
|
*/
|
|
6589
6694
|
cacheApiEntryPath(entryPath) {
|
|
6590
|
-
const dataDir =
|
|
6591
|
-
if (!
|
|
6592
|
-
|
|
6695
|
+
const dataDir = join8(homedir7(), ".agenticmail");
|
|
6696
|
+
if (!existsSync6(dataDir)) mkdirSync5(dataDir, { recursive: true });
|
|
6697
|
+
writeFileSync4(join8(dataDir, "api-entry.path"), entryPath);
|
|
6593
6698
|
}
|
|
6594
6699
|
/**
|
|
6595
6700
|
* Get the current package version.
|
|
@@ -6597,17 +6702,17 @@ var ServiceManager = class {
|
|
|
6597
6702
|
getVersion() {
|
|
6598
6703
|
try {
|
|
6599
6704
|
const pkgPaths = [
|
|
6600
|
-
|
|
6601
|
-
|
|
6705
|
+
join8(homedir7(), "node_modules", "agenticmail", "package.json"),
|
|
6706
|
+
join8(homedir7(), ".agenticmail", "package-version.json")
|
|
6602
6707
|
];
|
|
6603
6708
|
try {
|
|
6604
6709
|
const prefix = execSync2("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
6605
|
-
pkgPaths.push(
|
|
6710
|
+
pkgPaths.push(join8(prefix, "lib", "node_modules", "agenticmail", "package.json"));
|
|
6606
6711
|
} catch {
|
|
6607
6712
|
}
|
|
6608
6713
|
for (const p of pkgPaths) {
|
|
6609
|
-
if (
|
|
6610
|
-
const pkg = JSON.parse(
|
|
6714
|
+
if (existsSync6(p)) {
|
|
6715
|
+
const pkg = JSON.parse(readFileSync3(p, "utf-8"));
|
|
6611
6716
|
if (pkg.version) return pkg.version;
|
|
6612
6717
|
}
|
|
6613
6718
|
}
|
|
@@ -6620,9 +6725,9 @@ var ServiceManager = class {
|
|
|
6620
6725
|
* This ensures AgenticMail doesn't fail on boot when Docker is still loading.
|
|
6621
6726
|
*/
|
|
6622
6727
|
generateStartScript(nodePath, apiEntry) {
|
|
6623
|
-
const scriptPath =
|
|
6624
|
-
const scriptDir =
|
|
6625
|
-
if (!
|
|
6728
|
+
const scriptPath = join8(homedir7(), ".agenticmail", "bin", "start-server.sh");
|
|
6729
|
+
const scriptDir = join8(homedir7(), ".agenticmail", "bin");
|
|
6730
|
+
if (!existsSync6(scriptDir)) mkdirSync5(scriptDir, { recursive: true });
|
|
6626
6731
|
const script = [
|
|
6627
6732
|
"#!/bin/bash",
|
|
6628
6733
|
"# AgenticMail auto-start script",
|
|
@@ -6673,7 +6778,7 @@ var ServiceManager = class {
|
|
|
6673
6778
|
`log "Starting API server: ${nodePath} ${apiEntry}"`,
|
|
6674
6779
|
`exec "${nodePath}" "${apiEntry}"`
|
|
6675
6780
|
].join("\n") + "\n";
|
|
6676
|
-
|
|
6781
|
+
writeFileSync4(scriptPath, script, { mode: 493 });
|
|
6677
6782
|
return scriptPath;
|
|
6678
6783
|
}
|
|
6679
6784
|
/**
|
|
@@ -6686,9 +6791,9 @@ var ServiceManager = class {
|
|
|
6686
6791
|
* - Service version tracking in env vars
|
|
6687
6792
|
*/
|
|
6688
6793
|
generatePlist(nodePath, apiEntry, configPath) {
|
|
6689
|
-
const config = JSON.parse(
|
|
6690
|
-
const logDir =
|
|
6691
|
-
if (!
|
|
6794
|
+
const config = JSON.parse(readFileSync3(configPath, "utf-8"));
|
|
6795
|
+
const logDir = join8(homedir7(), ".agenticmail", "logs");
|
|
6796
|
+
if (!existsSync6(logDir)) mkdirSync5(logDir, { recursive: true });
|
|
6692
6797
|
const version = this.getVersion();
|
|
6693
6798
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
6694
6799
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -6709,9 +6814,9 @@ var ServiceManager = class {
|
|
|
6709
6814
|
<key>EnvironmentVariables</key>
|
|
6710
6815
|
<dict>
|
|
6711
6816
|
<key>HOME</key>
|
|
6712
|
-
<string>${
|
|
6817
|
+
<string>${homedir7()}</string>
|
|
6713
6818
|
<key>AGENTICMAIL_DATA_DIR</key>
|
|
6714
|
-
<string>${config.dataDir ||
|
|
6819
|
+
<string>${config.dataDir || join8(homedir7(), ".agenticmail")}</string>
|
|
6715
6820
|
<key>PATH</key>
|
|
6716
6821
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
6717
6822
|
<key>AGENTICMAIL_SERVICE_VERSION</key>
|
|
@@ -6764,8 +6869,8 @@ var ServiceManager = class {
|
|
|
6764
6869
|
* - Proper dependency ordering
|
|
6765
6870
|
*/
|
|
6766
6871
|
generateSystemdUnit(nodePath, apiEntry, configPath) {
|
|
6767
|
-
const config = JSON.parse(
|
|
6768
|
-
const dataDir = config.dataDir ||
|
|
6872
|
+
const config = JSON.parse(readFileSync3(configPath, "utf-8"));
|
|
6873
|
+
const dataDir = config.dataDir || join8(homedir7(), ".agenticmail");
|
|
6769
6874
|
const version = this.getVersion();
|
|
6770
6875
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
6771
6876
|
return `[Unit]
|
|
@@ -6782,7 +6887,7 @@ Restart=always
|
|
|
6782
6887
|
RestartSec=15
|
|
6783
6888
|
TimeoutStartSec=660
|
|
6784
6889
|
LimitNOFILE=8192
|
|
6785
|
-
Environment=HOME=${
|
|
6890
|
+
Environment=HOME=${homedir7()}
|
|
6786
6891
|
Environment=AGENTICMAIL_DATA_DIR=${dataDir}
|
|
6787
6892
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
|
|
6788
6893
|
Environment=AGENTICMAIL_SERVICE_VERSION=${version}
|
|
@@ -6795,8 +6900,8 @@ WantedBy=default.target
|
|
|
6795
6900
|
* Install the auto-start service.
|
|
6796
6901
|
*/
|
|
6797
6902
|
install() {
|
|
6798
|
-
const configPath =
|
|
6799
|
-
if (!
|
|
6903
|
+
const configPath = join8(homedir7(), ".agenticmail", "config.json");
|
|
6904
|
+
if (!existsSync6(configPath)) {
|
|
6800
6905
|
return { installed: false, message: "Config not found. Run agenticmail setup first." };
|
|
6801
6906
|
}
|
|
6802
6907
|
const nodePath = this.getNodePath();
|
|
@@ -6808,16 +6913,16 @@ WantedBy=default.target
|
|
|
6808
6913
|
}
|
|
6809
6914
|
const servicePath = this.getServicePath();
|
|
6810
6915
|
if (this.os === "darwin") {
|
|
6811
|
-
const dir =
|
|
6812
|
-
if (!
|
|
6813
|
-
if (
|
|
6916
|
+
const dir = join8(homedir7(), "Library", "LaunchAgents");
|
|
6917
|
+
if (!existsSync6(dir)) mkdirSync5(dir, { recursive: true });
|
|
6918
|
+
if (existsSync6(servicePath)) {
|
|
6814
6919
|
try {
|
|
6815
6920
|
execFileSync3("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
6816
6921
|
} catch {
|
|
6817
6922
|
}
|
|
6818
6923
|
}
|
|
6819
6924
|
const plist = this.generatePlist(nodePath, apiEntry, configPath);
|
|
6820
|
-
|
|
6925
|
+
writeFileSync4(servicePath, plist);
|
|
6821
6926
|
chmodSync(servicePath, 384);
|
|
6822
6927
|
try {
|
|
6823
6928
|
execFileSync3("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -6826,10 +6931,10 @@ WantedBy=default.target
|
|
|
6826
6931
|
}
|
|
6827
6932
|
return { installed: true, message: `Service installed at ${servicePath}` };
|
|
6828
6933
|
} else if (this.os === "linux") {
|
|
6829
|
-
const dir =
|
|
6830
|
-
if (!
|
|
6934
|
+
const dir = join8(homedir7(), ".config", "systemd", "user");
|
|
6935
|
+
if (!existsSync6(dir)) mkdirSync5(dir, { recursive: true });
|
|
6831
6936
|
const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
|
|
6832
|
-
|
|
6937
|
+
writeFileSync4(servicePath, unit);
|
|
6833
6938
|
chmodSync(servicePath, 384);
|
|
6834
6939
|
try {
|
|
6835
6940
|
execFileSync3("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -6852,7 +6957,7 @@ WantedBy=default.target
|
|
|
6852
6957
|
*/
|
|
6853
6958
|
uninstall() {
|
|
6854
6959
|
const servicePath = this.getServicePath();
|
|
6855
|
-
if (!
|
|
6960
|
+
if (!existsSync6(servicePath)) {
|
|
6856
6961
|
return { removed: false, message: "Service is not installed." };
|
|
6857
6962
|
}
|
|
6858
6963
|
if (this.os === "darwin") {
|
|
@@ -6890,7 +6995,7 @@ WantedBy=default.target
|
|
|
6890
6995
|
status() {
|
|
6891
6996
|
const servicePath = this.getServicePath();
|
|
6892
6997
|
const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
|
|
6893
|
-
const installed =
|
|
6998
|
+
const installed = existsSync6(servicePath);
|
|
6894
6999
|
let running = false;
|
|
6895
7000
|
if (installed) {
|
|
6896
7001
|
if (this.os === "darwin") {
|
|
@@ -6960,13 +7065,13 @@ var SetupManager = class {
|
|
|
6960
7065
|
* falls back to monorepo location.
|
|
6961
7066
|
*/
|
|
6962
7067
|
getComposePath() {
|
|
6963
|
-
const standalonePath =
|
|
6964
|
-
if (
|
|
7068
|
+
const standalonePath = join9(homedir8(), ".agenticmail", "docker-compose.yml");
|
|
7069
|
+
if (existsSync7(standalonePath)) return standalonePath;
|
|
6965
7070
|
const cwd = process.cwd();
|
|
6966
|
-
const candidates = [cwd,
|
|
7071
|
+
const candidates = [cwd, join9(cwd, "..")];
|
|
6967
7072
|
for (const dir of candidates) {
|
|
6968
|
-
const p =
|
|
6969
|
-
if (
|
|
7073
|
+
const p = join9(dir, "docker-compose.yml");
|
|
7074
|
+
if (existsSync7(p)) return p;
|
|
6970
7075
|
}
|
|
6971
7076
|
return standalonePath;
|
|
6972
7077
|
}
|
|
@@ -6976,19 +7081,19 @@ var SetupManager = class {
|
|
|
6976
7081
|
* Always regenerates Docker files to keep passwords in sync.
|
|
6977
7082
|
*/
|
|
6978
7083
|
initConfig() {
|
|
6979
|
-
const dataDir =
|
|
6980
|
-
const configPath =
|
|
6981
|
-
const envPath =
|
|
6982
|
-
if (
|
|
7084
|
+
const dataDir = join9(homedir8(), ".agenticmail");
|
|
7085
|
+
const configPath = join9(dataDir, "config.json");
|
|
7086
|
+
const envPath = join9(dataDir, ".env");
|
|
7087
|
+
if (existsSync7(configPath)) {
|
|
6983
7088
|
try {
|
|
6984
|
-
const existing = JSON.parse(
|
|
7089
|
+
const existing = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
6985
7090
|
this.generateDockerFiles(existing);
|
|
6986
7091
|
return { configPath, envPath, config: existing, isNew: false };
|
|
6987
7092
|
} catch {
|
|
6988
7093
|
}
|
|
6989
7094
|
}
|
|
6990
|
-
if (!
|
|
6991
|
-
|
|
7095
|
+
if (!existsSync7(dataDir)) {
|
|
7096
|
+
mkdirSync6(dataDir, { recursive: true });
|
|
6992
7097
|
}
|
|
6993
7098
|
const masterKey = `mk_${randomBytes3(24).toString("hex")}`;
|
|
6994
7099
|
const stalwartPassword = randomBytes3(16).toString("hex");
|
|
@@ -7004,7 +7109,7 @@ var SetupManager = class {
|
|
|
7004
7109
|
api: { port: 3100, host: "127.0.0.1" },
|
|
7005
7110
|
dataDir
|
|
7006
7111
|
};
|
|
7007
|
-
|
|
7112
|
+
writeFileSync5(configPath, JSON.stringify(config, null, 2));
|
|
7008
7113
|
chmodSync2(configPath, 384);
|
|
7009
7114
|
const envContent = `# Auto-generated by agenticmail setup
|
|
7010
7115
|
STALWART_ADMIN_USER=admin
|
|
@@ -7020,7 +7125,7 @@ SMTP_PORT=587
|
|
|
7020
7125
|
IMAP_HOST=localhost
|
|
7021
7126
|
IMAP_PORT=143
|
|
7022
7127
|
`;
|
|
7023
|
-
|
|
7128
|
+
writeFileSync5(envPath, envContent);
|
|
7024
7129
|
chmodSync2(envPath, 384);
|
|
7025
7130
|
this.generateDockerFiles(config);
|
|
7026
7131
|
return { configPath, envPath, config, isNew: true };
|
|
@@ -7030,13 +7135,13 @@ IMAP_PORT=143
|
|
|
7030
7135
|
* with the correct admin password from config.
|
|
7031
7136
|
*/
|
|
7032
7137
|
generateDockerFiles(config) {
|
|
7033
|
-
const dataDir = config.dataDir ||
|
|
7034
|
-
if (!
|
|
7035
|
-
|
|
7138
|
+
const dataDir = config.dataDir || join9(homedir8(), ".agenticmail");
|
|
7139
|
+
if (!existsSync7(dataDir)) {
|
|
7140
|
+
mkdirSync6(dataDir, { recursive: true });
|
|
7036
7141
|
}
|
|
7037
7142
|
const password = config.stalwart?.adminPassword || "changeme";
|
|
7038
|
-
const composePath =
|
|
7039
|
-
|
|
7143
|
+
const composePath = join9(dataDir, "docker-compose.yml");
|
|
7144
|
+
writeFileSync5(composePath, `services:
|
|
7040
7145
|
stalwart:
|
|
7041
7146
|
image: stalwartlabs/stalwart:latest
|
|
7042
7147
|
container_name: agenticmail-stalwart
|
|
@@ -7059,8 +7164,8 @@ volumes:
|
|
|
7059
7164
|
stalwart-data:
|
|
7060
7165
|
`);
|
|
7061
7166
|
chmodSync2(composePath, 384);
|
|
7062
|
-
const tomlPath =
|
|
7063
|
-
|
|
7167
|
+
const tomlPath = join9(dataDir, "stalwart.toml");
|
|
7168
|
+
writeFileSync5(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
|
|
7064
7169
|
|
|
7065
7170
|
[server]
|
|
7066
7171
|
hostname = "localhost"
|
|
@@ -7116,8 +7221,8 @@ secret = "${password}"
|
|
|
7116
7221
|
* Check if config has already been initialized.
|
|
7117
7222
|
*/
|
|
7118
7223
|
isInitialized() {
|
|
7119
|
-
const configPath =
|
|
7120
|
-
return
|
|
7224
|
+
const configPath = join9(homedir8(), ".agenticmail", "config.json");
|
|
7225
|
+
return existsSync7(configPath);
|
|
7121
7226
|
}
|
|
7122
7227
|
};
|
|
7123
7228
|
export {
|
|
@@ -7156,16 +7261,19 @@ export {
|
|
|
7156
7261
|
debugWarn,
|
|
7157
7262
|
ensureDataDir,
|
|
7158
7263
|
extractVerificationCode,
|
|
7264
|
+
flushTelemetry,
|
|
7159
7265
|
getDatabase,
|
|
7160
7266
|
isInternalEmail,
|
|
7161
7267
|
isValidPhoneNumber,
|
|
7162
7268
|
normalizePhoneNumber,
|
|
7163
7269
|
parseEmail,
|
|
7164
7270
|
parseGoogleVoiceSms,
|
|
7271
|
+
recordToolCall,
|
|
7165
7272
|
resolveConfig,
|
|
7166
7273
|
sanitizeEmail,
|
|
7167
7274
|
saveConfig,
|
|
7168
7275
|
scanOutboundEmail,
|
|
7169
7276
|
scoreEmail,
|
|
7277
|
+
setTelemetryVersion,
|
|
7170
7278
|
startRelayBridge
|
|
7171
7279
|
};
|