@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.cjs +310 -222
- package/dist/index.d.cts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +297 -212
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -755,6 +755,7 @@ __export(index_exports, {
|
|
|
755
755
|
flushTelemetry: () => flushTelemetry,
|
|
756
756
|
forgetHostSession: () => forgetHostSession,
|
|
757
757
|
getDatabase: () => getDatabase,
|
|
758
|
+
getOperatorEmail: () => getOperatorEmail,
|
|
758
759
|
hostSessionStoragePath: () => hostSessionStoragePath,
|
|
759
760
|
isInternalEmail: () => isInternalEmail,
|
|
760
761
|
isSessionFresh: () => isSessionFresh,
|
|
@@ -763,6 +764,7 @@ __export(index_exports, {
|
|
|
763
764
|
normalizeAddress: () => normalizeAddress,
|
|
764
765
|
normalizePhoneNumber: () => normalizePhoneNumber,
|
|
765
766
|
normalizeSubject: () => normalizeSubject,
|
|
767
|
+
operatorPrefsStoragePath: () => operatorPrefsStoragePath,
|
|
766
768
|
parseEmail: () => parseEmail,
|
|
767
769
|
parseGoogleVoiceSms: () => parseGoogleVoiceSms,
|
|
768
770
|
recordToolCall: () => recordToolCall,
|
|
@@ -775,6 +777,7 @@ __export(index_exports, {
|
|
|
775
777
|
saveHostSession: () => saveHostSession,
|
|
776
778
|
scanOutboundEmail: () => scanOutboundEmail,
|
|
777
779
|
scoreEmail: () => scoreEmail,
|
|
780
|
+
setOperatorEmail: () => setOperatorEmail,
|
|
778
781
|
setTelemetryVersion: () => setTelemetryVersion,
|
|
779
782
|
startRelayBridge: () => startRelayBridge,
|
|
780
783
|
threadIdFor: () => threadIdFor,
|
|
@@ -1165,8 +1168,8 @@ var MailReceiver = class {
|
|
|
1165
1168
|
}));
|
|
1166
1169
|
}
|
|
1167
1170
|
/** Create a new IMAP folder */
|
|
1168
|
-
async createFolder(
|
|
1169
|
-
await this.client.mailboxCreate(
|
|
1171
|
+
async createFolder(path2) {
|
|
1172
|
+
await this.client.mailboxCreate(path2);
|
|
1170
1173
|
}
|
|
1171
1174
|
/** Batch mark multiple messages as seen */
|
|
1172
1175
|
async batchMarkSeen(uids, mailbox = "INBOX") {
|
|
@@ -1706,8 +1709,8 @@ var StalwartAdmin = class {
|
|
|
1706
1709
|
}
|
|
1707
1710
|
baseUrl;
|
|
1708
1711
|
authHeader;
|
|
1709
|
-
async request(method,
|
|
1710
|
-
const url = `${this.baseUrl}/api${
|
|
1712
|
+
async request(method, path2, body) {
|
|
1713
|
+
const url = `${this.baseUrl}/api${path2}`;
|
|
1711
1714
|
const response = await fetch(url, {
|
|
1712
1715
|
method,
|
|
1713
1716
|
headers: {
|
|
@@ -1868,14 +1871,14 @@ var StalwartAdmin = class {
|
|
|
1868
1871
|
if (!isValidDomain(domain)) {
|
|
1869
1872
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
1870
1873
|
}
|
|
1871
|
-
const { readFileSync:
|
|
1872
|
-
const { homedir:
|
|
1873
|
-
const { join:
|
|
1874
|
-
const configPath =
|
|
1874
|
+
const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
|
|
1875
|
+
const { homedir: homedir13 } = await import("os");
|
|
1876
|
+
const { join: join15 } = await import("path");
|
|
1877
|
+
const configPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
1875
1878
|
try {
|
|
1876
|
-
let config =
|
|
1879
|
+
let config = readFileSync9(configPath, "utf-8");
|
|
1877
1880
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
1878
|
-
|
|
1881
|
+
writeFileSync10(configPath, config);
|
|
1879
1882
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
1880
1883
|
} catch (err) {
|
|
1881
1884
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -1884,15 +1887,15 @@ var StalwartAdmin = class {
|
|
|
1884
1887
|
// --- DKIM ---
|
|
1885
1888
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
1886
1889
|
get configPath() {
|
|
1887
|
-
const { homedir:
|
|
1888
|
-
const { join:
|
|
1889
|
-
return
|
|
1890
|
+
const { homedir: homedir13 } = require("os");
|
|
1891
|
+
const { join: join15 } = require("path");
|
|
1892
|
+
return join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
1890
1893
|
}
|
|
1891
1894
|
/** Path to host-side DKIM key directory */
|
|
1892
1895
|
get dkimDir() {
|
|
1893
|
-
const { homedir:
|
|
1894
|
-
const { join:
|
|
1895
|
-
return
|
|
1896
|
+
const { homedir: homedir13 } = require("os");
|
|
1897
|
+
const { join: join15 } = require("path");
|
|
1898
|
+
return join15(homedir13(), ".agenticmail");
|
|
1896
1899
|
}
|
|
1897
1900
|
/**
|
|
1898
1901
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -1993,12 +1996,12 @@ var StalwartAdmin = class {
|
|
|
1993
1996
|
* This bypasses the need for a PTR record on the sending IP.
|
|
1994
1997
|
*/
|
|
1995
1998
|
async configureOutboundRelay(config) {
|
|
1996
|
-
const { readFileSync:
|
|
1997
|
-
const { homedir:
|
|
1998
|
-
const { join:
|
|
1999
|
+
const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
|
|
2000
|
+
const { homedir: homedir13 } = await import("os");
|
|
2001
|
+
const { join: join15 } = await import("path");
|
|
1999
2002
|
const routeName = config.routeName ?? "gmail";
|
|
2000
|
-
const tomlPath =
|
|
2001
|
-
let toml =
|
|
2003
|
+
const tomlPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
2004
|
+
let toml = readFileSync9(tomlPath, "utf-8");
|
|
2002
2005
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
2003
2006
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
2004
2007
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -2018,7 +2021,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
2018
2021
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
2019
2022
|
{ else = "'${safeRouteName}'" } ]
|
|
2020
2023
|
`;
|
|
2021
|
-
|
|
2024
|
+
writeFileSync10(tomlPath, toml, "utf-8");
|
|
2022
2025
|
await this.restartContainer();
|
|
2023
2026
|
}
|
|
2024
2027
|
};
|
|
@@ -2401,11 +2404,11 @@ var AgentDeletionService = class {
|
|
|
2401
2404
|
};
|
|
2402
2405
|
}
|
|
2403
2406
|
saveToFile(report) {
|
|
2404
|
-
const
|
|
2405
|
-
(0, import_node_fs2.mkdirSync)(
|
|
2407
|
+
const dir2 = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".agenticmail", "deletions");
|
|
2408
|
+
(0, import_node_fs2.mkdirSync)(dir2, { recursive: true });
|
|
2406
2409
|
const timestamp = report.deletedAt.replace(/[:.]/g, "-");
|
|
2407
2410
|
const filename = `${report.agent.name}_${timestamp}.json`;
|
|
2408
|
-
const filePath = (0, import_node_path2.join)(
|
|
2411
|
+
const filePath = (0, import_node_path2.join)(dir2, filename);
|
|
2409
2412
|
(0, import_node_fs2.writeFileSync)(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
2410
2413
|
return filePath;
|
|
2411
2414
|
}
|
|
@@ -4696,8 +4699,8 @@ var CloudflareClient = class {
|
|
|
4696
4699
|
return resp.result;
|
|
4697
4700
|
}
|
|
4698
4701
|
// --- Internal ---
|
|
4699
|
-
async request(method,
|
|
4700
|
-
const url = `${CF_API_BASE}${
|
|
4702
|
+
async request(method, path2, body) {
|
|
4703
|
+
const url = `${CF_API_BASE}${path2}`;
|
|
4701
4704
|
const response = await fetch(url, {
|
|
4702
4705
|
method,
|
|
4703
4706
|
headers: {
|
|
@@ -5019,9 +5022,9 @@ var TunnelManager = class {
|
|
|
5019
5022
|
throw new Error(`Failed to download cloudflared: ${response.statusText}`);
|
|
5020
5023
|
}
|
|
5021
5024
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
5022
|
-
const { writeFile:
|
|
5025
|
+
const { writeFile: writeFile4, rename: rename2 } = await import("fs/promises");
|
|
5023
5026
|
const tmpPath = this.binPath + ".tmp";
|
|
5024
|
-
await
|
|
5027
|
+
await writeFile4(tmpPath, buffer);
|
|
5025
5028
|
await (0, import_promises.chmod)(tmpPath, 493);
|
|
5026
5029
|
await rename2(tmpPath, this.binPath);
|
|
5027
5030
|
return this.binPath;
|
|
@@ -5314,6 +5317,33 @@ var SmsManager = class {
|
|
|
5314
5317
|
meta.sms = config;
|
|
5315
5318
|
this.db.prepare("UPDATE agents SET metadata = ?, updated_at = datetime('now') WHERE id = ?").run(JSON.stringify(meta), agentId);
|
|
5316
5319
|
}
|
|
5320
|
+
/**
|
|
5321
|
+
* Resolve the operator's "where do I get pinged" address from an
|
|
5322
|
+
* agent's SMS config. Used by the dispatcher's bridge-escalation
|
|
5323
|
+
* path: when sub-agents mail a bridge with no fresh host session
|
|
5324
|
+
* available, we email the operator a digest at this address. Their
|
|
5325
|
+
* phone's Gmail push notification surfaces it within seconds —
|
|
5326
|
+
* effectively a free, programmatic alert channel.
|
|
5327
|
+
*
|
|
5328
|
+
* Returns the configured `forwardingEmail` (the same Gmail Google
|
|
5329
|
+
* Voice forwards inbound SMS to, which the operator already has
|
|
5330
|
+
* push notifications enabled for) when SMS is configured AND
|
|
5331
|
+
* enabled. Returns null otherwise — caller falls through to a
|
|
5332
|
+
* silent log + system event.
|
|
5333
|
+
*
|
|
5334
|
+
* Why we don't try real-SMS delivery yet: Google Voice's
|
|
5335
|
+
* `<number>@txt.voice.google.com` email-to-SMS gateway was
|
|
5336
|
+
* deprecated by Google years ago. A future `carrier` field on
|
|
5337
|
+
* SmsConfig (Verizon vtext.com / AT&T txt.att.net / etc) will let
|
|
5338
|
+
* the operator opt into actual SMS, but that's a follow-up — the
|
|
5339
|
+
* email path already gets the operator a phone notification.
|
|
5340
|
+
*/
|
|
5341
|
+
getAlertEmail(agentId) {
|
|
5342
|
+
const cfg = this.getSmsConfig(agentId);
|
|
5343
|
+
if (!cfg || !cfg.enabled) return null;
|
|
5344
|
+
if (typeof cfg.forwardingEmail !== "string" || !cfg.forwardingEmail.includes("@")) return null;
|
|
5345
|
+
return cfg.forwardingEmail;
|
|
5346
|
+
}
|
|
5317
5347
|
/** Remove SMS config from agent metadata */
|
|
5318
5348
|
removeSmsConfig(agentId) {
|
|
5319
5349
|
const row = this.db.prepare("SELECT metadata FROM agents WHERE id = ?").get(agentId);
|
|
@@ -5929,12 +5959,12 @@ var GatewayManager = class {
|
|
|
5929
5959
|
zone = await this.cfClient.createZone(domain);
|
|
5930
5960
|
}
|
|
5931
5961
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
5932
|
-
const { homedir:
|
|
5933
|
-
const backupDir = (0, import_node_path4.join)(
|
|
5962
|
+
const { homedir: homedir13 } = await import("os");
|
|
5963
|
+
const backupDir = (0, import_node_path4.join)(homedir13(), ".agenticmail");
|
|
5934
5964
|
const backupPath = (0, import_node_path4.join)(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
5935
|
-
const { writeFileSync:
|
|
5936
|
-
|
|
5937
|
-
|
|
5965
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync11 } = await import("fs");
|
|
5966
|
+
mkdirSync11(backupDir, { recursive: true });
|
|
5967
|
+
writeFileSync10(backupPath, JSON.stringify({
|
|
5938
5968
|
domain,
|
|
5939
5969
|
zoneId: zone.id,
|
|
5940
5970
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6695,8 +6725,8 @@ function isDisabled() {
|
|
|
6695
6725
|
function getInstallId() {
|
|
6696
6726
|
if (installId) return installId;
|
|
6697
6727
|
try {
|
|
6698
|
-
const
|
|
6699
|
-
const idFile = (0, import_path.join)(
|
|
6728
|
+
const dir2 = (0, import_path.join)((0, import_os.homedir)(), ".agenticmail");
|
|
6729
|
+
const idFile = (0, import_path.join)(dir2, ".telemetry-id");
|
|
6700
6730
|
if ((0, import_fs.existsSync)(idFile)) {
|
|
6701
6731
|
const id = (0, import_fs.readFileSync)(idFile, "utf8").trim();
|
|
6702
6732
|
if (id && id.length > 10) {
|
|
@@ -6705,7 +6735,7 @@ function getInstallId() {
|
|
|
6705
6735
|
}
|
|
6706
6736
|
}
|
|
6707
6737
|
installId = (0, import_crypto.randomUUID)();
|
|
6708
|
-
if (!(0, import_fs.existsSync)(
|
|
6738
|
+
if (!(0, import_fs.existsSync)(dir2)) (0, import_fs.mkdirSync)(dir2, { recursive: true });
|
|
6709
6739
|
(0, import_fs.writeFileSync)(idFile, installId, "utf8");
|
|
6710
6740
|
return installId;
|
|
6711
6741
|
} catch {
|
|
@@ -6876,22 +6906,77 @@ function redactObject(input, _depth = 0) {
|
|
|
6876
6906
|
return out;
|
|
6877
6907
|
}
|
|
6878
6908
|
|
|
6879
|
-
// src/
|
|
6909
|
+
// src/operator-prefs.ts
|
|
6880
6910
|
var import_node_fs4 = require("fs");
|
|
6881
|
-
var import_node_path6 = require("path");
|
|
6882
6911
|
var import_node_os4 = require("os");
|
|
6883
|
-
|
|
6912
|
+
var import_node_path6 = require("path");
|
|
6913
|
+
function dir() {
|
|
6884
6914
|
return (0, import_node_path6.join)((0, import_node_os4.homedir)(), ".agenticmail");
|
|
6885
6915
|
}
|
|
6916
|
+
function path() {
|
|
6917
|
+
return (0, import_node_path6.join)(dir(), "operator-prefs.json");
|
|
6918
|
+
}
|
|
6919
|
+
function readFile() {
|
|
6920
|
+
if (!(0, import_node_fs4.existsSync)(path())) return { version: 1 };
|
|
6921
|
+
try {
|
|
6922
|
+
const raw = (0, import_node_fs4.readFileSync)(path(), "utf-8");
|
|
6923
|
+
if (!raw.trim()) return { version: 1 };
|
|
6924
|
+
const parsed = JSON.parse(raw);
|
|
6925
|
+
return { version: 1, operatorEmail: typeof parsed.operatorEmail === "string" ? parsed.operatorEmail : void 0 };
|
|
6926
|
+
} catch {
|
|
6927
|
+
return { version: 1 };
|
|
6928
|
+
}
|
|
6929
|
+
}
|
|
6930
|
+
function writeFile(shape) {
|
|
6931
|
+
const d = dir();
|
|
6932
|
+
const p = path();
|
|
6933
|
+
if (!(0, import_node_fs4.existsSync)(d)) (0, import_node_fs4.mkdirSync)(d, { recursive: true });
|
|
6934
|
+
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6935
|
+
(0, import_node_fs4.writeFileSync)(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
6936
|
+
(0, import_node_fs4.renameSync)(tmp, p);
|
|
6937
|
+
}
|
|
6938
|
+
function getOperatorEmail() {
|
|
6939
|
+
const shape = readFile();
|
|
6940
|
+
const email = shape.operatorEmail;
|
|
6941
|
+
if (typeof email !== "string") return null;
|
|
6942
|
+
const trimmed = email.trim();
|
|
6943
|
+
return trimmed.length > 0 && trimmed.includes("@") ? trimmed : null;
|
|
6944
|
+
}
|
|
6945
|
+
function setOperatorEmail(email) {
|
|
6946
|
+
const shape = readFile();
|
|
6947
|
+
if (!email || !email.trim()) {
|
|
6948
|
+
delete shape.operatorEmail;
|
|
6949
|
+
writeFile(shape);
|
|
6950
|
+
return null;
|
|
6951
|
+
}
|
|
6952
|
+
const trimmed = email.trim();
|
|
6953
|
+
if (!trimmed.includes("@")) {
|
|
6954
|
+
throw new Error("operator email must contain an @");
|
|
6955
|
+
}
|
|
6956
|
+
shape.operatorEmail = trimmed;
|
|
6957
|
+
writeFile(shape);
|
|
6958
|
+
return trimmed;
|
|
6959
|
+
}
|
|
6960
|
+
function operatorPrefsStoragePath() {
|
|
6961
|
+
return path();
|
|
6962
|
+
}
|
|
6963
|
+
|
|
6964
|
+
// src/host-sessions.ts
|
|
6965
|
+
var import_node_fs5 = require("fs");
|
|
6966
|
+
var import_node_path7 = require("path");
|
|
6967
|
+
var import_node_os5 = require("os");
|
|
6968
|
+
function storageDir() {
|
|
6969
|
+
return (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".agenticmail");
|
|
6970
|
+
}
|
|
6886
6971
|
function storagePath() {
|
|
6887
|
-
return (0,
|
|
6972
|
+
return (0, import_node_path7.join)(storageDir(), "host-sessions.json");
|
|
6888
6973
|
}
|
|
6889
6974
|
var DEFAULT_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
6890
|
-
function
|
|
6975
|
+
function readFile2() {
|
|
6891
6976
|
const p = storagePath();
|
|
6892
|
-
if (!(0,
|
|
6977
|
+
if (!(0, import_node_fs5.existsSync)(p)) return { version: 1, sessions: {} };
|
|
6893
6978
|
try {
|
|
6894
|
-
const raw = (0,
|
|
6979
|
+
const raw = (0, import_node_fs5.readFileSync)(p, "utf-8");
|
|
6895
6980
|
if (!raw.trim()) return { version: 1, sessions: {} };
|
|
6896
6981
|
const parsed = JSON.parse(raw);
|
|
6897
6982
|
return {
|
|
@@ -6902,28 +6987,28 @@ function readFile() {
|
|
|
6902
6987
|
return { version: 1, sessions: {} };
|
|
6903
6988
|
}
|
|
6904
6989
|
}
|
|
6905
|
-
function
|
|
6906
|
-
const
|
|
6990
|
+
function writeFile2(shape) {
|
|
6991
|
+
const dir2 = storageDir();
|
|
6907
6992
|
const p = storagePath();
|
|
6908
|
-
if (!(0,
|
|
6993
|
+
if (!(0, import_node_fs5.existsSync)(dir2)) (0, import_node_fs5.mkdirSync)(dir2, { recursive: true });
|
|
6909
6994
|
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6910
|
-
(0,
|
|
6911
|
-
(0,
|
|
6995
|
+
(0, import_node_fs5.writeFileSync)(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
6996
|
+
(0, import_node_fs5.renameSync)(tmp, p);
|
|
6912
6997
|
}
|
|
6913
6998
|
function saveHostSession(host, session) {
|
|
6914
6999
|
if (!session.sessionId) return;
|
|
6915
7000
|
try {
|
|
6916
|
-
const shape =
|
|
7001
|
+
const shape = readFile2();
|
|
6917
7002
|
shape.sessions[host] = {
|
|
6918
7003
|
...session,
|
|
6919
7004
|
lastSeenMs: Date.now()
|
|
6920
7005
|
};
|
|
6921
|
-
|
|
7006
|
+
writeFile2(shape);
|
|
6922
7007
|
} catch {
|
|
6923
7008
|
}
|
|
6924
7009
|
}
|
|
6925
7010
|
function loadHostSession(host, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
6926
|
-
const shape =
|
|
7011
|
+
const shape = readFile2();
|
|
6927
7012
|
const record = shape.sessions[host];
|
|
6928
7013
|
if (!record) return null;
|
|
6929
7014
|
if (!isSessionFresh(record, maxAgeMs)) return null;
|
|
@@ -6935,10 +7020,10 @@ function isSessionFresh(session, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
|
6935
7020
|
}
|
|
6936
7021
|
function forgetHostSession(host) {
|
|
6937
7022
|
try {
|
|
6938
|
-
const shape =
|
|
7023
|
+
const shape = readFile2();
|
|
6939
7024
|
if (!shape.sessions[host]) return;
|
|
6940
7025
|
delete shape.sessions[host];
|
|
6941
|
-
|
|
7026
|
+
writeFile2(shape);
|
|
6942
7027
|
} catch {
|
|
6943
7028
|
}
|
|
6944
7029
|
}
|
|
@@ -6988,21 +7073,21 @@ function validateApiUrl(raw) {
|
|
|
6988
7073
|
return parsed.origin;
|
|
6989
7074
|
}
|
|
6990
7075
|
function buildApiUrl(baseOrigin, pathAndQuery) {
|
|
6991
|
-
const
|
|
6992
|
-
return new URL(
|
|
7076
|
+
const path2 = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
|
|
7077
|
+
return new URL(path2, baseOrigin + "/").toString();
|
|
6993
7078
|
}
|
|
6994
7079
|
|
|
6995
7080
|
// src/setup/index.ts
|
|
6996
7081
|
var import_node_crypto3 = require("crypto");
|
|
6997
|
-
var
|
|
6998
|
-
var
|
|
6999
|
-
var
|
|
7082
|
+
var import_node_fs9 = require("fs");
|
|
7083
|
+
var import_node_path11 = require("path");
|
|
7084
|
+
var import_node_os9 = require("os");
|
|
7000
7085
|
|
|
7001
7086
|
// src/setup/deps.ts
|
|
7002
7087
|
var import_node_child_process2 = require("child_process");
|
|
7003
|
-
var
|
|
7004
|
-
var
|
|
7005
|
-
var
|
|
7088
|
+
var import_node_fs6 = require("fs");
|
|
7089
|
+
var import_node_path8 = require("path");
|
|
7090
|
+
var import_node_os6 = require("os");
|
|
7006
7091
|
var DependencyChecker = class {
|
|
7007
7092
|
async checkAll() {
|
|
7008
7093
|
return Promise.all([
|
|
@@ -7052,8 +7137,8 @@ var DependencyChecker = class {
|
|
|
7052
7137
|
}
|
|
7053
7138
|
}
|
|
7054
7139
|
async checkCloudflared() {
|
|
7055
|
-
const binPath = (0,
|
|
7056
|
-
if ((0,
|
|
7140
|
+
const binPath = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".agenticmail", "bin", "cloudflared");
|
|
7141
|
+
if ((0, import_node_fs6.existsSync)(binPath)) {
|
|
7057
7142
|
let version;
|
|
7058
7143
|
try {
|
|
7059
7144
|
const output = (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -7075,10 +7160,10 @@ var DependencyChecker = class {
|
|
|
7075
7160
|
|
|
7076
7161
|
// src/setup/installer.ts
|
|
7077
7162
|
var import_node_child_process3 = require("child_process");
|
|
7078
|
-
var
|
|
7163
|
+
var import_node_fs7 = require("fs");
|
|
7079
7164
|
var import_promises2 = require("fs/promises");
|
|
7080
|
-
var
|
|
7081
|
-
var
|
|
7165
|
+
var import_node_path9 = require("path");
|
|
7166
|
+
var import_node_os7 = require("os");
|
|
7082
7167
|
function runShellWithRollingOutput(cmd, opts = {}) {
|
|
7083
7168
|
const maxLines = opts.maxLines ?? 20;
|
|
7084
7169
|
const timeout = opts.timeout ?? 3e5;
|
|
@@ -7188,7 +7273,7 @@ var DependencyInstaller = class {
|
|
|
7188
7273
|
*/
|
|
7189
7274
|
async installDocker() {
|
|
7190
7275
|
if (this.isDockerReady()) return;
|
|
7191
|
-
const os = (0,
|
|
7276
|
+
const os = (0, import_node_os7.platform)();
|
|
7192
7277
|
if (os === "darwin") {
|
|
7193
7278
|
await this.installDockerMac();
|
|
7194
7279
|
} else if (os === "linux") {
|
|
@@ -7254,15 +7339,15 @@ var DependencyInstaller = class {
|
|
|
7254
7339
|
try {
|
|
7255
7340
|
const composeBin = (0, import_node_child_process3.execFileSync)("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7256
7341
|
if (!composeBin) return;
|
|
7257
|
-
const pluginDir = (0,
|
|
7258
|
-
const pluginPath = (0,
|
|
7259
|
-
if ((0,
|
|
7342
|
+
const pluginDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".docker", "cli-plugins");
|
|
7343
|
+
const pluginPath = (0, import_node_path9.join)(pluginDir, "docker-compose");
|
|
7344
|
+
if ((0, import_node_fs7.existsSync)(pluginPath)) return;
|
|
7260
7345
|
try {
|
|
7261
|
-
(0,
|
|
7346
|
+
(0, import_node_fs7.mkdirSync)(pluginDir, { recursive: true });
|
|
7262
7347
|
} catch {
|
|
7263
7348
|
}
|
|
7264
7349
|
try {
|
|
7265
|
-
(0,
|
|
7350
|
+
(0, import_node_fs7.symlinkSync)(composeBin, pluginPath);
|
|
7266
7351
|
} catch {
|
|
7267
7352
|
}
|
|
7268
7353
|
} catch {
|
|
@@ -7321,9 +7406,9 @@ var DependencyInstaller = class {
|
|
|
7321
7406
|
return;
|
|
7322
7407
|
}
|
|
7323
7408
|
this.onProgress("__progress__:5:Installing Docker Engine...");
|
|
7324
|
-
const tmpDir = (0,
|
|
7409
|
+
const tmpDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".agenticmail", "tmp");
|
|
7325
7410
|
await (0, import_promises2.mkdir)(tmpDir, { recursive: true });
|
|
7326
|
-
const scriptPath = (0,
|
|
7411
|
+
const scriptPath = (0, import_node_path9.join)(tmpDir, "install-docker.sh");
|
|
7327
7412
|
const dlResult = await runShellWithRollingOutput(
|
|
7328
7413
|
`curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
|
|
7329
7414
|
{ timeout: 3e5 }
|
|
@@ -7391,8 +7476,8 @@ var DependencyInstaller = class {
|
|
|
7391
7476
|
}
|
|
7392
7477
|
try {
|
|
7393
7478
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7394
|
-
const dockerExe = (0,
|
|
7395
|
-
if ((0,
|
|
7479
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7480
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7396
7481
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7397
7482
|
}
|
|
7398
7483
|
} catch {
|
|
@@ -7442,8 +7527,8 @@ var DependencyInstaller = class {
|
|
|
7442
7527
|
this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
|
|
7443
7528
|
try {
|
|
7444
7529
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7445
|
-
const dockerExe = (0,
|
|
7446
|
-
if ((0,
|
|
7530
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7531
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7447
7532
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7448
7533
|
}
|
|
7449
7534
|
} catch {
|
|
@@ -7480,12 +7565,12 @@ var DependencyInstaller = class {
|
|
|
7480
7565
|
* Start the Stalwart mail server Docker container.
|
|
7481
7566
|
*/
|
|
7482
7567
|
async startStalwart(composePath) {
|
|
7483
|
-
if (!(0,
|
|
7568
|
+
if (!(0, import_node_fs7.existsSync)(composePath)) {
|
|
7484
7569
|
throw new Error(`docker-compose.yml not found at: ${composePath}`);
|
|
7485
7570
|
}
|
|
7486
7571
|
if (!this.isDockerReady()) {
|
|
7487
7572
|
this.onProgress("Starting Docker...");
|
|
7488
|
-
const os = (0,
|
|
7573
|
+
const os = (0, import_node_os7.platform)();
|
|
7489
7574
|
if (os === "darwin") {
|
|
7490
7575
|
await this.startColima();
|
|
7491
7576
|
} else if (os === "win32") {
|
|
@@ -7503,7 +7588,7 @@ var DependencyInstaller = class {
|
|
|
7503
7588
|
}
|
|
7504
7589
|
}
|
|
7505
7590
|
this.onProgress("__progress__:10:Pulling mail server image...");
|
|
7506
|
-
if ((0,
|
|
7591
|
+
if ((0, import_node_os7.platform)() === "darwin") this.linkComposePlugin();
|
|
7507
7592
|
let composeResult = await runSilent("docker", ["compose", "-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
7508
7593
|
if (composeResult.exitCode !== 0 && hasCommand("docker-compose")) {
|
|
7509
7594
|
composeResult = await runSilent("docker-compose", ["-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
@@ -7538,22 +7623,22 @@ var DependencyInstaller = class {
|
|
|
7538
7623
|
* Returns the path to the installed binary.
|
|
7539
7624
|
*/
|
|
7540
7625
|
async installCloudflared() {
|
|
7541
|
-
const os = (0,
|
|
7542
|
-
const binDir = (0,
|
|
7626
|
+
const os = (0, import_node_os7.platform)();
|
|
7627
|
+
const binDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".agenticmail", "bin");
|
|
7543
7628
|
const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
7544
|
-
const binPath = (0,
|
|
7545
|
-
if ((0,
|
|
7629
|
+
const binPath = (0, import_node_path9.join)(binDir, binName);
|
|
7630
|
+
if ((0, import_node_fs7.existsSync)(binPath)) {
|
|
7546
7631
|
return binPath;
|
|
7547
7632
|
}
|
|
7548
7633
|
try {
|
|
7549
7634
|
const whichCmd = os === "win32" ? "where" : "which";
|
|
7550
7635
|
const sysPath = (0, import_node_child_process3.execFileSync)(whichCmd, ["cloudflared"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n")[0];
|
|
7551
|
-
if (sysPath && (0,
|
|
7636
|
+
if (sysPath && (0, import_node_fs7.existsSync)(sysPath)) return sysPath;
|
|
7552
7637
|
} catch {
|
|
7553
7638
|
}
|
|
7554
7639
|
this.onProgress("Downloading cloudflared...");
|
|
7555
7640
|
await (0, import_promises2.mkdir)(binDir, { recursive: true });
|
|
7556
|
-
const cpu = (0,
|
|
7641
|
+
const cpu = (0, import_node_os7.arch)();
|
|
7557
7642
|
const archName = cpu === "arm64" ? "arm64" : "amd64";
|
|
7558
7643
|
let downloadUrl;
|
|
7559
7644
|
if (os === "darwin") {
|
|
@@ -7571,7 +7656,7 @@ var DependencyInstaller = class {
|
|
|
7571
7656
|
}
|
|
7572
7657
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7573
7658
|
if (os === "darwin") {
|
|
7574
|
-
const tgzPath = (0,
|
|
7659
|
+
const tgzPath = (0, import_node_path9.join)(binDir, "cloudflared.tgz");
|
|
7575
7660
|
await (0, import_promises2.writeFile)(tgzPath, buffer);
|
|
7576
7661
|
try {
|
|
7577
7662
|
(0, import_node_child_process3.execFileSync)("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
|
|
@@ -7588,7 +7673,7 @@ var DependencyInstaller = class {
|
|
|
7588
7673
|
if (os !== "win32") await (0, import_promises2.chmod)(tmpPath, 493);
|
|
7589
7674
|
await (0, import_promises2.rename)(tmpPath, binPath);
|
|
7590
7675
|
}
|
|
7591
|
-
if (!(0,
|
|
7676
|
+
if (!(0, import_node_fs7.existsSync)(binPath)) {
|
|
7592
7677
|
throw new Error("cloudflared download succeeded but binary not found after extraction");
|
|
7593
7678
|
}
|
|
7594
7679
|
this.onProgress("cloudflared installed");
|
|
@@ -7606,23 +7691,23 @@ var DependencyInstaller = class {
|
|
|
7606
7691
|
|
|
7607
7692
|
// src/setup/service.ts
|
|
7608
7693
|
var import_node_child_process4 = require("child_process");
|
|
7609
|
-
var
|
|
7610
|
-
var
|
|
7611
|
-
var
|
|
7694
|
+
var import_node_fs8 = require("fs");
|
|
7695
|
+
var import_node_path10 = require("path");
|
|
7696
|
+
var import_node_os8 = require("os");
|
|
7612
7697
|
var import_node_module2 = require("module");
|
|
7613
7698
|
var import_meta2 = {};
|
|
7614
7699
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
7615
7700
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
7616
7701
|
var ServiceManager = class {
|
|
7617
|
-
os = (0,
|
|
7702
|
+
os = (0, import_node_os8.platform)();
|
|
7618
7703
|
/**
|
|
7619
7704
|
* Get the path to the service file.
|
|
7620
7705
|
*/
|
|
7621
7706
|
getServicePath() {
|
|
7622
7707
|
if (this.os === "darwin") {
|
|
7623
|
-
return (0,
|
|
7708
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
7624
7709
|
} else {
|
|
7625
|
-
return (0,
|
|
7710
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
7626
7711
|
}
|
|
7627
7712
|
}
|
|
7628
7713
|
/**
|
|
@@ -7656,40 +7741,40 @@ var ServiceManager = class {
|
|
|
7656
7741
|
try {
|
|
7657
7742
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7658
7743
|
const resolved = req.resolve("@agenticmail/api");
|
|
7659
|
-
if ((0,
|
|
7744
|
+
if ((0, import_node_fs8.existsSync)(resolved)) return resolved;
|
|
7660
7745
|
} catch {
|
|
7661
7746
|
}
|
|
7662
7747
|
const parentPackages = [
|
|
7663
|
-
(0,
|
|
7748
|
+
(0, import_node_path10.join)("@agenticmail", "cli"),
|
|
7664
7749
|
// current scoped package
|
|
7665
7750
|
"agenticmail"
|
|
7666
7751
|
// legacy unscoped package
|
|
7667
7752
|
];
|
|
7668
7753
|
const baseDirs = [
|
|
7669
7754
|
// user-local install
|
|
7670
|
-
(0,
|
|
7755
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules")
|
|
7671
7756
|
];
|
|
7672
7757
|
try {
|
|
7673
7758
|
const prefix = (0, import_node_child_process4.execSync)("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7674
|
-
baseDirs.push((0,
|
|
7675
|
-
baseDirs.push((0,
|
|
7759
|
+
baseDirs.push((0, import_node_path10.join)(prefix, "lib", "node_modules"));
|
|
7760
|
+
baseDirs.push((0, import_node_path10.join)(prefix, "node_modules"));
|
|
7676
7761
|
} catch {
|
|
7677
7762
|
}
|
|
7678
7763
|
baseDirs.push("/opt/homebrew/lib/node_modules");
|
|
7679
7764
|
baseDirs.push("/usr/local/lib/node_modules");
|
|
7680
7765
|
for (const base of baseDirs) {
|
|
7681
|
-
const sibling = (0,
|
|
7682
|
-
if ((0,
|
|
7766
|
+
const sibling = (0, import_node_path10.join)(base, "@agenticmail", "api", "dist", "index.js");
|
|
7767
|
+
if ((0, import_node_fs8.existsSync)(sibling)) return sibling;
|
|
7683
7768
|
for (const parent of parentPackages) {
|
|
7684
|
-
const nested = (0,
|
|
7685
|
-
if ((0,
|
|
7769
|
+
const nested = (0, import_node_path10.join)(base, parent, "node_modules", "@agenticmail", "api", "dist", "index.js");
|
|
7770
|
+
if ((0, import_node_fs8.existsSync)(nested)) return nested;
|
|
7686
7771
|
}
|
|
7687
7772
|
}
|
|
7688
|
-
const dataDir = (0,
|
|
7689
|
-
const entryCache = (0,
|
|
7690
|
-
if ((0,
|
|
7691
|
-
const cached = (0,
|
|
7692
|
-
if (cached && (0,
|
|
7773
|
+
const dataDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7774
|
+
const entryCache = (0, import_node_path10.join)(dataDir, "api-entry.path");
|
|
7775
|
+
if ((0, import_node_fs8.existsSync)(entryCache)) {
|
|
7776
|
+
const cached = (0, import_node_fs8.readFileSync)(entryCache, "utf-8").trim();
|
|
7777
|
+
if (cached && (0, import_node_fs8.existsSync)(cached)) return cached;
|
|
7693
7778
|
}
|
|
7694
7779
|
throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
|
|
7695
7780
|
}
|
|
@@ -7697,9 +7782,9 @@ var ServiceManager = class {
|
|
|
7697
7782
|
* Cache the API entry path so the service can find it later.
|
|
7698
7783
|
*/
|
|
7699
7784
|
cacheApiEntryPath(entryPath) {
|
|
7700
|
-
const dataDir = (0,
|
|
7701
|
-
if (!(0,
|
|
7702
|
-
(0,
|
|
7785
|
+
const dataDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7786
|
+
if (!(0, import_node_fs8.existsSync)(dataDir)) (0, import_node_fs8.mkdirSync)(dataDir, { recursive: true });
|
|
7787
|
+
(0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(dataDir, "api-entry.path"), entryPath);
|
|
7703
7788
|
}
|
|
7704
7789
|
/**
|
|
7705
7790
|
* Get the current package version.
|
|
@@ -7712,36 +7797,36 @@ var ServiceManager = class {
|
|
|
7712
7797
|
try {
|
|
7713
7798
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7714
7799
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
7715
|
-
if ((0,
|
|
7716
|
-
const pkg = JSON.parse((0,
|
|
7800
|
+
if ((0, import_node_fs8.existsSync)(pkgJson)) {
|
|
7801
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(pkgJson, "utf-8"));
|
|
7717
7802
|
if (pkg.version) return pkg.version;
|
|
7718
7803
|
}
|
|
7719
7804
|
} catch {
|
|
7720
7805
|
}
|
|
7721
7806
|
try {
|
|
7722
7807
|
const apiEntry = this.getApiEntryPath();
|
|
7723
|
-
const apiPkg = (0,
|
|
7724
|
-
if ((0,
|
|
7725
|
-
const pkg = JSON.parse((0,
|
|
7808
|
+
const apiPkg = (0, import_node_path10.join)(apiEntry, "..", "..", "package.json");
|
|
7809
|
+
if ((0, import_node_fs8.existsSync)(apiPkg)) {
|
|
7810
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(apiPkg, "utf-8"));
|
|
7726
7811
|
if (pkg.version) return pkg.version;
|
|
7727
7812
|
}
|
|
7728
7813
|
} catch {
|
|
7729
7814
|
}
|
|
7730
7815
|
const candidates = [
|
|
7731
|
-
(0,
|
|
7732
|
-
(0,
|
|
7733
|
-
(0,
|
|
7816
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules", "@agenticmail", "cli", "package.json"),
|
|
7817
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules", "agenticmail", "package.json"),
|
|
7818
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "package-version.json")
|
|
7734
7819
|
];
|
|
7735
7820
|
try {
|
|
7736
7821
|
const prefix = (0, import_node_child_process4.execSync)("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7737
|
-
candidates.push((0,
|
|
7738
|
-
candidates.push((0,
|
|
7822
|
+
candidates.push((0, import_node_path10.join)(prefix, "lib", "node_modules", "@agenticmail", "cli", "package.json"));
|
|
7823
|
+
candidates.push((0, import_node_path10.join)(prefix, "lib", "node_modules", "agenticmail", "package.json"));
|
|
7739
7824
|
} catch {
|
|
7740
7825
|
}
|
|
7741
7826
|
for (const p of candidates) {
|
|
7742
7827
|
try {
|
|
7743
|
-
if ((0,
|
|
7744
|
-
const pkg = JSON.parse((0,
|
|
7828
|
+
if ((0, import_node_fs8.existsSync)(p)) {
|
|
7829
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(p, "utf-8"));
|
|
7745
7830
|
if (pkg.version) return pkg.version;
|
|
7746
7831
|
}
|
|
7747
7832
|
} catch {
|
|
@@ -7754,9 +7839,9 @@ var ServiceManager = class {
|
|
|
7754
7839
|
* This ensures AgenticMail doesn't fail on boot when Docker is still loading.
|
|
7755
7840
|
*/
|
|
7756
7841
|
generateStartScript(nodePath, apiEntry) {
|
|
7757
|
-
const scriptPath = (0,
|
|
7758
|
-
const scriptDir = (0,
|
|
7759
|
-
if (!(0,
|
|
7842
|
+
const scriptPath = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin", "start-server.sh");
|
|
7843
|
+
const scriptDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin");
|
|
7844
|
+
if (!(0, import_node_fs8.existsSync)(scriptDir)) (0, import_node_fs8.mkdirSync)(scriptDir, { recursive: true });
|
|
7760
7845
|
const script = [
|
|
7761
7846
|
"#!/bin/bash",
|
|
7762
7847
|
"# AgenticMail auto-start script",
|
|
@@ -7807,7 +7892,7 @@ var ServiceManager = class {
|
|
|
7807
7892
|
`log "Starting API server: ${nodePath} ${apiEntry}"`,
|
|
7808
7893
|
`exec "${nodePath}" "${apiEntry}"`
|
|
7809
7894
|
].join("\n") + "\n";
|
|
7810
|
-
(0,
|
|
7895
|
+
(0, import_node_fs8.writeFileSync)(scriptPath, script, { mode: 493 });
|
|
7811
7896
|
return scriptPath;
|
|
7812
7897
|
}
|
|
7813
7898
|
/**
|
|
@@ -7820,9 +7905,9 @@ var ServiceManager = class {
|
|
|
7820
7905
|
* - Service version tracking in env vars
|
|
7821
7906
|
*/
|
|
7822
7907
|
generatePlist(nodePath, apiEntry, configPath) {
|
|
7823
|
-
const config = JSON.parse((0,
|
|
7824
|
-
const logDir = (0,
|
|
7825
|
-
if (!(0,
|
|
7908
|
+
const config = JSON.parse((0, import_node_fs8.readFileSync)(configPath, "utf-8"));
|
|
7909
|
+
const logDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "logs");
|
|
7910
|
+
if (!(0, import_node_fs8.existsSync)(logDir)) (0, import_node_fs8.mkdirSync)(logDir, { recursive: true });
|
|
7826
7911
|
const version = this.getVersion();
|
|
7827
7912
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7828
7913
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -7843,9 +7928,9 @@ var ServiceManager = class {
|
|
|
7843
7928
|
<key>EnvironmentVariables</key>
|
|
7844
7929
|
<dict>
|
|
7845
7930
|
<key>HOME</key>
|
|
7846
|
-
<string>${(0,
|
|
7931
|
+
<string>${(0, import_node_os8.homedir)()}</string>
|
|
7847
7932
|
<key>AGENTICMAIL_DATA_DIR</key>
|
|
7848
|
-
<string>${config.dataDir || (0,
|
|
7933
|
+
<string>${config.dataDir || (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail")}</string>
|
|
7849
7934
|
<key>PATH</key>
|
|
7850
7935
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
7851
7936
|
<key>AGENTICMAIL_SERVICE_VERSION</key>
|
|
@@ -7898,8 +7983,8 @@ var ServiceManager = class {
|
|
|
7898
7983
|
* - Proper dependency ordering
|
|
7899
7984
|
*/
|
|
7900
7985
|
generateSystemdUnit(nodePath, apiEntry, configPath) {
|
|
7901
|
-
const config = JSON.parse((0,
|
|
7902
|
-
const dataDir = config.dataDir || (0,
|
|
7986
|
+
const config = JSON.parse((0, import_node_fs8.readFileSync)(configPath, "utf-8"));
|
|
7987
|
+
const dataDir = config.dataDir || (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7903
7988
|
const version = this.getVersion();
|
|
7904
7989
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7905
7990
|
return `[Unit]
|
|
@@ -7916,7 +8001,7 @@ Restart=always
|
|
|
7916
8001
|
RestartSec=15
|
|
7917
8002
|
TimeoutStartSec=660
|
|
7918
8003
|
LimitNOFILE=8192
|
|
7919
|
-
Environment=HOME=${(0,
|
|
8004
|
+
Environment=HOME=${(0, import_node_os8.homedir)()}
|
|
7920
8005
|
Environment=AGENTICMAIL_DATA_DIR=${dataDir}
|
|
7921
8006
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
|
|
7922
8007
|
Environment=AGENTICMAIL_SERVICE_VERSION=${version}
|
|
@@ -7929,8 +8014,8 @@ WantedBy=default.target
|
|
|
7929
8014
|
* Install the auto-start service.
|
|
7930
8015
|
*/
|
|
7931
8016
|
install() {
|
|
7932
|
-
const configPath = (0,
|
|
7933
|
-
if (!(0,
|
|
8017
|
+
const configPath = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "config.json");
|
|
8018
|
+
if (!(0, import_node_fs8.existsSync)(configPath)) {
|
|
7934
8019
|
return { installed: false, message: "Config not found. Run agenticmail setup first." };
|
|
7935
8020
|
}
|
|
7936
8021
|
const nodePath = this.getNodePath();
|
|
@@ -7942,17 +8027,17 @@ WantedBy=default.target
|
|
|
7942
8027
|
}
|
|
7943
8028
|
const servicePath = this.getServicePath();
|
|
7944
8029
|
if (this.os === "darwin") {
|
|
7945
|
-
const
|
|
7946
|
-
if (!(0,
|
|
7947
|
-
if ((0,
|
|
8030
|
+
const dir2 = (0, import_node_path10.join)((0, import_node_os8.homedir)(), "Library", "LaunchAgents");
|
|
8031
|
+
if (!(0, import_node_fs8.existsSync)(dir2)) (0, import_node_fs8.mkdirSync)(dir2, { recursive: true });
|
|
8032
|
+
if ((0, import_node_fs8.existsSync)(servicePath)) {
|
|
7948
8033
|
try {
|
|
7949
8034
|
(0, import_node_child_process4.execFileSync)("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7950
8035
|
} catch {
|
|
7951
8036
|
}
|
|
7952
8037
|
}
|
|
7953
8038
|
const plist = this.generatePlist(nodePath, apiEntry, configPath);
|
|
7954
|
-
(0,
|
|
7955
|
-
(0,
|
|
8039
|
+
(0, import_node_fs8.writeFileSync)(servicePath, plist);
|
|
8040
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7956
8041
|
try {
|
|
7957
8042
|
(0, import_node_child_process4.execFileSync)("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7958
8043
|
} catch (err) {
|
|
@@ -7960,11 +8045,11 @@ WantedBy=default.target
|
|
|
7960
8045
|
}
|
|
7961
8046
|
return { installed: true, message: `Service installed at ${servicePath}` };
|
|
7962
8047
|
} else if (this.os === "linux") {
|
|
7963
|
-
const
|
|
7964
|
-
if (!(0,
|
|
8048
|
+
const dir2 = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".config", "systemd", "user");
|
|
8049
|
+
if (!(0, import_node_fs8.existsSync)(dir2)) (0, import_node_fs8.mkdirSync)(dir2, { recursive: true });
|
|
7965
8050
|
const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
|
|
7966
|
-
(0,
|
|
7967
|
-
(0,
|
|
8051
|
+
(0, import_node_fs8.writeFileSync)(servicePath, unit);
|
|
8052
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7968
8053
|
try {
|
|
7969
8054
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
|
|
7970
8055
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "enable", SYSTEMD_UNIT], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -7986,7 +8071,7 @@ WantedBy=default.target
|
|
|
7986
8071
|
*/
|
|
7987
8072
|
uninstall() {
|
|
7988
8073
|
const servicePath = this.getServicePath();
|
|
7989
|
-
if (!(0,
|
|
8074
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) {
|
|
7990
8075
|
return { removed: false, message: "Service is not installed." };
|
|
7991
8076
|
}
|
|
7992
8077
|
if (this.os === "darwin") {
|
|
@@ -7995,7 +8080,7 @@ WantedBy=default.target
|
|
|
7995
8080
|
} catch {
|
|
7996
8081
|
}
|
|
7997
8082
|
try {
|
|
7998
|
-
(0,
|
|
8083
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
7999
8084
|
} catch {
|
|
8000
8085
|
}
|
|
8001
8086
|
return { removed: true, message: "Service removed." };
|
|
@@ -8006,7 +8091,7 @@ WantedBy=default.target
|
|
|
8006
8091
|
} catch {
|
|
8007
8092
|
}
|
|
8008
8093
|
try {
|
|
8009
|
-
(0,
|
|
8094
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
8010
8095
|
} catch {
|
|
8011
8096
|
}
|
|
8012
8097
|
try {
|
|
@@ -8024,7 +8109,7 @@ WantedBy=default.target
|
|
|
8024
8109
|
status() {
|
|
8025
8110
|
const servicePath = this.getServicePath();
|
|
8026
8111
|
const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
|
|
8027
|
-
const installed = (0,
|
|
8112
|
+
const installed = (0, import_node_fs8.existsSync)(servicePath);
|
|
8028
8113
|
let running = false;
|
|
8029
8114
|
if (installed) {
|
|
8030
8115
|
if (this.os === "darwin") {
|
|
@@ -8079,34 +8164,34 @@ WantedBy=default.target
|
|
|
8079
8164
|
needsRepair() {
|
|
8080
8165
|
if (this.os !== "darwin" && this.os !== "linux") return null;
|
|
8081
8166
|
const servicePath = this.getServicePath();
|
|
8082
|
-
if (!(0,
|
|
8167
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) return null;
|
|
8083
8168
|
let serviceContent = "";
|
|
8084
8169
|
try {
|
|
8085
|
-
serviceContent = (0,
|
|
8170
|
+
serviceContent = (0, import_node_fs8.readFileSync)(servicePath, "utf-8");
|
|
8086
8171
|
} catch {
|
|
8087
8172
|
return { reason: "Service file unreadable" };
|
|
8088
8173
|
}
|
|
8089
|
-
const startScript = (0,
|
|
8174
|
+
const startScript = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin", "start-server.sh");
|
|
8090
8175
|
if (serviceContent.includes(startScript)) {
|
|
8091
|
-
if (!(0,
|
|
8176
|
+
if (!(0, import_node_fs8.existsSync)(startScript)) {
|
|
8092
8177
|
return { reason: "start-server.sh is missing" };
|
|
8093
8178
|
}
|
|
8094
8179
|
let scriptContent = "";
|
|
8095
8180
|
try {
|
|
8096
|
-
scriptContent = (0,
|
|
8181
|
+
scriptContent = (0, import_node_fs8.readFileSync)(startScript, "utf-8");
|
|
8097
8182
|
} catch {
|
|
8098
8183
|
return { reason: "start-server.sh unreadable" };
|
|
8099
8184
|
}
|
|
8100
8185
|
const apiPathMatch = scriptContent.match(/(\/[^"\s]+@agenticmail\/api\/dist\/index\.js)/);
|
|
8101
8186
|
if (apiPathMatch) {
|
|
8102
8187
|
const referenced = apiPathMatch[1];
|
|
8103
|
-
if (!(0,
|
|
8188
|
+
if (!(0, import_node_fs8.existsSync)(referenced)) {
|
|
8104
8189
|
return { reason: `start-server.sh references missing path: ${referenced}` };
|
|
8105
8190
|
}
|
|
8106
8191
|
}
|
|
8107
8192
|
if (/node_modules\/agenticmail\/(?!.*@agenticmail\/cli)/.test(scriptContent)) {
|
|
8108
8193
|
const stale = /(\S*node_modules\/agenticmail\/\S*)/.exec(scriptContent)?.[1];
|
|
8109
|
-
if (stale && !(0,
|
|
8194
|
+
if (stale && !(0, import_node_fs8.existsSync)(stale)) {
|
|
8110
8195
|
return { reason: `start-server.sh references legacy unscoped path: ${stale}` };
|
|
8111
8196
|
}
|
|
8112
8197
|
}
|
|
@@ -8119,11 +8204,11 @@ WantedBy=default.target
|
|
|
8119
8204
|
return { reason: `Service version drift (current CLI is v${currentVersion})` };
|
|
8120
8205
|
}
|
|
8121
8206
|
}
|
|
8122
|
-
const entryCache = (0,
|
|
8123
|
-
if ((0,
|
|
8207
|
+
const entryCache = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "api-entry.path");
|
|
8208
|
+
if ((0, import_node_fs8.existsSync)(entryCache)) {
|
|
8124
8209
|
try {
|
|
8125
|
-
const cached = (0,
|
|
8126
|
-
if (cached && !(0,
|
|
8210
|
+
const cached = (0, import_node_fs8.readFileSync)(entryCache, "utf-8").trim();
|
|
8211
|
+
if (cached && !(0, import_node_fs8.existsSync)(cached)) {
|
|
8127
8212
|
return { reason: `Cached API entry path no longer exists: ${cached}` };
|
|
8128
8213
|
}
|
|
8129
8214
|
} catch {
|
|
@@ -8162,8 +8247,8 @@ var SetupManager = class {
|
|
|
8162
8247
|
async ensureStalwart(composePath) {
|
|
8163
8248
|
const status = await this.checker.checkStalwart();
|
|
8164
8249
|
if (status.installed) return;
|
|
8165
|
-
const
|
|
8166
|
-
await this.installer.startStalwart(
|
|
8250
|
+
const path2 = composePath ?? this.getComposePath();
|
|
8251
|
+
await this.installer.startStalwart(path2);
|
|
8167
8252
|
}
|
|
8168
8253
|
async ensureCloudflared() {
|
|
8169
8254
|
return this.installer.installCloudflared();
|
|
@@ -8174,13 +8259,13 @@ var SetupManager = class {
|
|
|
8174
8259
|
* falls back to monorepo location.
|
|
8175
8260
|
*/
|
|
8176
8261
|
getComposePath() {
|
|
8177
|
-
const standalonePath = (0,
|
|
8178
|
-
if ((0,
|
|
8262
|
+
const standalonePath = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail", "docker-compose.yml");
|
|
8263
|
+
if ((0, import_node_fs9.existsSync)(standalonePath)) return standalonePath;
|
|
8179
8264
|
const cwd = process.cwd();
|
|
8180
|
-
const candidates = [cwd, (0,
|
|
8181
|
-
for (const
|
|
8182
|
-
const p = (0,
|
|
8183
|
-
if ((0,
|
|
8265
|
+
const candidates = [cwd, (0, import_node_path11.join)(cwd, "..")];
|
|
8266
|
+
for (const dir2 of candidates) {
|
|
8267
|
+
const p = (0, import_node_path11.join)(dir2, "docker-compose.yml");
|
|
8268
|
+
if ((0, import_node_fs9.existsSync)(p)) return p;
|
|
8184
8269
|
}
|
|
8185
8270
|
return standalonePath;
|
|
8186
8271
|
}
|
|
@@ -8190,19 +8275,19 @@ var SetupManager = class {
|
|
|
8190
8275
|
* Always regenerates Docker files to keep passwords in sync.
|
|
8191
8276
|
*/
|
|
8192
8277
|
initConfig() {
|
|
8193
|
-
const dataDir = (0,
|
|
8194
|
-
const configPath = (0,
|
|
8195
|
-
const envPath = (0,
|
|
8196
|
-
if ((0,
|
|
8278
|
+
const dataDir = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail");
|
|
8279
|
+
const configPath = (0, import_node_path11.join)(dataDir, "config.json");
|
|
8280
|
+
const envPath = (0, import_node_path11.join)(dataDir, ".env");
|
|
8281
|
+
if ((0, import_node_fs9.existsSync)(configPath)) {
|
|
8197
8282
|
try {
|
|
8198
|
-
const existing = JSON.parse((0,
|
|
8283
|
+
const existing = JSON.parse((0, import_node_fs9.readFileSync)(configPath, "utf-8"));
|
|
8199
8284
|
this.generateDockerFiles(existing);
|
|
8200
8285
|
return { configPath, envPath, config: existing, isNew: false };
|
|
8201
8286
|
} catch {
|
|
8202
8287
|
}
|
|
8203
8288
|
}
|
|
8204
|
-
if (!(0,
|
|
8205
|
-
(0,
|
|
8289
|
+
if (!(0, import_node_fs9.existsSync)(dataDir)) {
|
|
8290
|
+
(0, import_node_fs9.mkdirSync)(dataDir, { recursive: true });
|
|
8206
8291
|
}
|
|
8207
8292
|
const masterKey = `mk_${(0, import_node_crypto3.randomBytes)(24).toString("hex")}`;
|
|
8208
8293
|
const stalwartPassword = (0, import_node_crypto3.randomBytes)(16).toString("hex");
|
|
@@ -8218,8 +8303,8 @@ var SetupManager = class {
|
|
|
8218
8303
|
api: { port: 3829, host: "127.0.0.1" },
|
|
8219
8304
|
dataDir
|
|
8220
8305
|
};
|
|
8221
|
-
(0,
|
|
8222
|
-
(0,
|
|
8306
|
+
(0, import_node_fs9.writeFileSync)(configPath, JSON.stringify(config, null, 2));
|
|
8307
|
+
(0, import_node_fs9.chmodSync)(configPath, 384);
|
|
8223
8308
|
const envContent = `# Auto-generated by agenticmail setup
|
|
8224
8309
|
STALWART_ADMIN_USER=admin
|
|
8225
8310
|
STALWART_ADMIN_PASSWORD=${stalwartPassword}
|
|
@@ -8234,8 +8319,8 @@ SMTP_PORT=587
|
|
|
8234
8319
|
IMAP_HOST=localhost
|
|
8235
8320
|
IMAP_PORT=143
|
|
8236
8321
|
`;
|
|
8237
|
-
(0,
|
|
8238
|
-
(0,
|
|
8322
|
+
(0, import_node_fs9.writeFileSync)(envPath, envContent);
|
|
8323
|
+
(0, import_node_fs9.chmodSync)(envPath, 384);
|
|
8239
8324
|
this.generateDockerFiles(config);
|
|
8240
8325
|
return { configPath, envPath, config, isNew: true };
|
|
8241
8326
|
}
|
|
@@ -8244,13 +8329,13 @@ IMAP_PORT=143
|
|
|
8244
8329
|
* with the correct admin password from config.
|
|
8245
8330
|
*/
|
|
8246
8331
|
generateDockerFiles(config) {
|
|
8247
|
-
const dataDir = config.dataDir || (0,
|
|
8248
|
-
if (!(0,
|
|
8249
|
-
(0,
|
|
8332
|
+
const dataDir = config.dataDir || (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail");
|
|
8333
|
+
if (!(0, import_node_fs9.existsSync)(dataDir)) {
|
|
8334
|
+
(0, import_node_fs9.mkdirSync)(dataDir, { recursive: true });
|
|
8250
8335
|
}
|
|
8251
8336
|
const password = config.stalwart?.adminPassword || "changeme";
|
|
8252
|
-
const composePath = (0,
|
|
8253
|
-
(0,
|
|
8337
|
+
const composePath = (0, import_node_path11.join)(dataDir, "docker-compose.yml");
|
|
8338
|
+
(0, import_node_fs9.writeFileSync)(composePath, `services:
|
|
8254
8339
|
stalwart:
|
|
8255
8340
|
# Pinned to v0.15.5 \u2014 Stalwart 0.16+ moved its config to JSON
|
|
8256
8341
|
# at /etc/stalwart/config.json (hardcoded into the container
|
|
@@ -8279,9 +8364,9 @@ IMAP_PORT=143
|
|
|
8279
8364
|
volumes:
|
|
8280
8365
|
stalwart-data:
|
|
8281
8366
|
`);
|
|
8282
|
-
(0,
|
|
8283
|
-
const tomlPath = (0,
|
|
8284
|
-
(0,
|
|
8367
|
+
(0, import_node_fs9.chmodSync)(composePath, 384);
|
|
8368
|
+
const tomlPath = (0, import_node_path11.join)(dataDir, "stalwart.toml");
|
|
8369
|
+
(0, import_node_fs9.writeFileSync)(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
|
|
8285
8370
|
|
|
8286
8371
|
[server]
|
|
8287
8372
|
hostname = "localhost"
|
|
@@ -8331,14 +8416,14 @@ enable = true
|
|
|
8331
8416
|
user = "admin"
|
|
8332
8417
|
secret = "${password}"
|
|
8333
8418
|
`);
|
|
8334
|
-
(0,
|
|
8419
|
+
(0, import_node_fs9.chmodSync)(tomlPath, 384);
|
|
8335
8420
|
}
|
|
8336
8421
|
/**
|
|
8337
8422
|
* Check if config has already been initialized.
|
|
8338
8423
|
*/
|
|
8339
8424
|
isInitialized() {
|
|
8340
|
-
const configPath = (0,
|
|
8341
|
-
return (0,
|
|
8425
|
+
const configPath = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail", "config.json");
|
|
8426
|
+
return (0, import_node_fs9.existsSync)(configPath);
|
|
8342
8427
|
}
|
|
8343
8428
|
};
|
|
8344
8429
|
|
|
@@ -8376,10 +8461,10 @@ function threadIdFor(input) {
|
|
|
8376
8461
|
}
|
|
8377
8462
|
|
|
8378
8463
|
// src/threading/thread-cache.ts
|
|
8379
|
-
var
|
|
8380
|
-
var
|
|
8381
|
-
var
|
|
8382
|
-
var CACHE_DIR_DEFAULT = (0,
|
|
8464
|
+
var import_node_fs10 = require("fs");
|
|
8465
|
+
var import_node_os10 = require("os");
|
|
8466
|
+
var import_node_path12 = require("path");
|
|
8467
|
+
var CACHE_DIR_DEFAULT = (0, import_node_path12.join)((0, import_node_os10.homedir)(), ".agenticmail", "thread-cache");
|
|
8383
8468
|
var DEFAULT_K_MESSAGES = 10;
|
|
8384
8469
|
var DEFAULT_LRU_CAP = 5e3;
|
|
8385
8470
|
var PREVIEW_MAX_CHARS = 240;
|
|
@@ -8392,22 +8477,22 @@ var ThreadCache = class {
|
|
|
8392
8477
|
this.k = opts.k ?? DEFAULT_K_MESSAGES;
|
|
8393
8478
|
this.lruCap = opts.lruCap ?? DEFAULT_LRU_CAP;
|
|
8394
8479
|
try {
|
|
8395
|
-
(0,
|
|
8480
|
+
(0, import_node_fs10.mkdirSync)(this.dir, { recursive: true });
|
|
8396
8481
|
} catch {
|
|
8397
8482
|
}
|
|
8398
8483
|
}
|
|
8399
8484
|
pathFor(threadId) {
|
|
8400
|
-
return (0,
|
|
8485
|
+
return (0, import_node_path12.join)(this.dir, `${threadId}.json`);
|
|
8401
8486
|
}
|
|
8402
8487
|
read(threadId) {
|
|
8403
8488
|
const p = this.pathFor(threadId);
|
|
8404
|
-
if (!(0,
|
|
8489
|
+
if (!(0, import_node_fs10.existsSync)(p)) return null;
|
|
8405
8490
|
try {
|
|
8406
|
-
const raw = (0,
|
|
8491
|
+
const raw = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
8407
8492
|
return JSON.parse(raw);
|
|
8408
8493
|
} catch {
|
|
8409
8494
|
try {
|
|
8410
|
-
(0,
|
|
8495
|
+
(0, import_node_fs10.rmSync)(p, { force: true });
|
|
8411
8496
|
} catch {
|
|
8412
8497
|
}
|
|
8413
8498
|
return null;
|
|
@@ -8448,7 +8533,7 @@ var ThreadCache = class {
|
|
|
8448
8533
|
/** Permanently remove a thread's cache (called on [FINAL] / [DONE] / [CLOSED] / [WRAP]). */
|
|
8449
8534
|
delete(threadId) {
|
|
8450
8535
|
try {
|
|
8451
|
-
(0,
|
|
8536
|
+
(0, import_node_fs10.rmSync)(this.pathFor(threadId), { force: true });
|
|
8452
8537
|
} catch {
|
|
8453
8538
|
}
|
|
8454
8539
|
}
|
|
@@ -8468,8 +8553,8 @@ var ThreadCache = class {
|
|
|
8468
8553
|
writeAtomic(threadId, entry) {
|
|
8469
8554
|
const p = this.pathFor(threadId);
|
|
8470
8555
|
const tmp = `${p}.tmp`;
|
|
8471
|
-
(0,
|
|
8472
|
-
(0,
|
|
8556
|
+
(0, import_node_fs10.writeFileSync)(tmp, JSON.stringify(entry), "utf-8");
|
|
8557
|
+
(0, import_node_fs10.renameSync)(tmp, p);
|
|
8473
8558
|
}
|
|
8474
8559
|
/**
|
|
8475
8560
|
* Best-effort LRU eviction. Runs at most every 256 writes (we
|
|
@@ -8481,15 +8566,15 @@ var ThreadCache = class {
|
|
|
8481
8566
|
if (Math.random() > 1 / 256) return;
|
|
8482
8567
|
let files;
|
|
8483
8568
|
try {
|
|
8484
|
-
files = (0,
|
|
8569
|
+
files = (0, import_node_fs10.readdirSync)(this.dir).filter((f) => f.endsWith(".json"));
|
|
8485
8570
|
} catch {
|
|
8486
8571
|
return;
|
|
8487
8572
|
}
|
|
8488
8573
|
if (files.length <= this.lruCap) return;
|
|
8489
8574
|
const stats = files.map((f) => {
|
|
8490
|
-
const p = (0,
|
|
8575
|
+
const p = (0, import_node_path12.join)(this.dir, f);
|
|
8491
8576
|
try {
|
|
8492
|
-
return { p, mtime: (0,
|
|
8577
|
+
return { p, mtime: (0, import_node_fs10.statSync)(p).mtimeMs };
|
|
8493
8578
|
} catch {
|
|
8494
8579
|
return { p, mtime: 0 };
|
|
8495
8580
|
}
|
|
@@ -8498,7 +8583,7 @@ var ThreadCache = class {
|
|
|
8498
8583
|
const dropCount = Math.max(1, Math.floor(this.lruCap * 0.1));
|
|
8499
8584
|
for (let i = 0; i < dropCount; i++) {
|
|
8500
8585
|
try {
|
|
8501
|
-
(0,
|
|
8586
|
+
(0, import_node_fs10.rmSync)(stats[i].p, { force: true });
|
|
8502
8587
|
} catch {
|
|
8503
8588
|
}
|
|
8504
8589
|
}
|
|
@@ -8517,30 +8602,30 @@ function dedupAndCap(messages, k) {
|
|
|
8517
8602
|
}
|
|
8518
8603
|
|
|
8519
8604
|
// src/threading/agent-memory.ts
|
|
8520
|
-
var
|
|
8521
|
-
var
|
|
8522
|
-
var
|
|
8523
|
-
var MEMORY_DIR_DEFAULT = (0,
|
|
8605
|
+
var import_node_fs11 = require("fs");
|
|
8606
|
+
var import_node_os11 = require("os");
|
|
8607
|
+
var import_node_path13 = require("path");
|
|
8608
|
+
var MEMORY_DIR_DEFAULT = (0, import_node_path13.join)((0, import_node_os11.homedir)(), ".agenticmail", "agent-memory");
|
|
8524
8609
|
var AgentMemoryStore = class {
|
|
8525
8610
|
dir;
|
|
8526
8611
|
constructor(opts = {}) {
|
|
8527
8612
|
this.dir = opts.memoryDir ?? MEMORY_DIR_DEFAULT;
|
|
8528
8613
|
try {
|
|
8529
|
-
(0,
|
|
8614
|
+
(0, import_node_fs11.mkdirSync)(this.dir, { recursive: true });
|
|
8530
8615
|
} catch {
|
|
8531
8616
|
}
|
|
8532
8617
|
}
|
|
8533
8618
|
dirFor(agentId) {
|
|
8534
|
-
return (0,
|
|
8619
|
+
return (0, import_node_path13.join)(this.dir, sanitizeId(agentId));
|
|
8535
8620
|
}
|
|
8536
8621
|
pathFor(agentId, threadId) {
|
|
8537
|
-
return (0,
|
|
8622
|
+
return (0, import_node_path13.join)(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
|
|
8538
8623
|
}
|
|
8539
8624
|
read(agentId, threadId) {
|
|
8540
8625
|
const p = this.pathFor(agentId, threadId);
|
|
8541
|
-
if (!(0,
|
|
8626
|
+
if (!(0, import_node_fs11.existsSync)(p)) return null;
|
|
8542
8627
|
try {
|
|
8543
|
-
const raw = (0,
|
|
8628
|
+
const raw = (0, import_node_fs11.readFileSync)(p, "utf-8");
|
|
8544
8629
|
const parsed = parse(raw);
|
|
8545
8630
|
return { ...parsed, raw };
|
|
8546
8631
|
} catch {
|
|
@@ -8550,18 +8635,18 @@ var AgentMemoryStore = class {
|
|
|
8550
8635
|
write(agentId, threadId, fields) {
|
|
8551
8636
|
const agentDir = this.dirFor(agentId);
|
|
8552
8637
|
try {
|
|
8553
|
-
(0,
|
|
8638
|
+
(0, import_node_fs11.mkdirSync)(agentDir, { recursive: true });
|
|
8554
8639
|
} catch {
|
|
8555
8640
|
}
|
|
8556
8641
|
const body = render({ ...fields, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
8557
8642
|
const p = this.pathFor(agentId, threadId);
|
|
8558
8643
|
const tmp = `${p}.tmp`;
|
|
8559
|
-
(0,
|
|
8560
|
-
(0,
|
|
8644
|
+
(0, import_node_fs11.writeFileSync)(tmp, body, "utf-8");
|
|
8645
|
+
(0, import_node_fs11.renameSync)(tmp, p);
|
|
8561
8646
|
}
|
|
8562
8647
|
delete(agentId, threadId) {
|
|
8563
8648
|
try {
|
|
8564
|
-
(0,
|
|
8649
|
+
(0, import_node_fs11.rmSync)(this.pathFor(agentId, threadId), { force: true });
|
|
8565
8650
|
} catch {
|
|
8566
8651
|
}
|
|
8567
8652
|
}
|
|
@@ -8665,6 +8750,7 @@ function parse(raw) {
|
|
|
8665
8750
|
flushTelemetry,
|
|
8666
8751
|
forgetHostSession,
|
|
8667
8752
|
getDatabase,
|
|
8753
|
+
getOperatorEmail,
|
|
8668
8754
|
hostSessionStoragePath,
|
|
8669
8755
|
isInternalEmail,
|
|
8670
8756
|
isSessionFresh,
|
|
@@ -8673,6 +8759,7 @@ function parse(raw) {
|
|
|
8673
8759
|
normalizeAddress,
|
|
8674
8760
|
normalizePhoneNumber,
|
|
8675
8761
|
normalizeSubject,
|
|
8762
|
+
operatorPrefsStoragePath,
|
|
8676
8763
|
parseEmail,
|
|
8677
8764
|
parseGoogleVoiceSms,
|
|
8678
8765
|
recordToolCall,
|
|
@@ -8685,6 +8772,7 @@ function parse(raw) {
|
|
|
8685
8772
|
saveHostSession,
|
|
8686
8773
|
scanOutboundEmail,
|
|
8687
8774
|
scoreEmail,
|
|
8775
|
+
setOperatorEmail,
|
|
8688
8776
|
setTelemetryVersion,
|
|
8689
8777
|
startRelayBridge,
|
|
8690
8778
|
threadIdFor,
|