@agenticmail/core 0.9.6 → 0.9.8
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/README.md +12 -0
- package/dist/index.cjs +318 -222
- package/dist/index.d.cts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +305 -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,
|
|
@@ -966,6 +969,14 @@ var MailReceiver = class {
|
|
|
966
969
|
name: a.name,
|
|
967
970
|
address: a.address ?? ""
|
|
968
971
|
})),
|
|
972
|
+
cc: (env.cc ?? []).map((a) => ({
|
|
973
|
+
name: a.name,
|
|
974
|
+
address: a.address ?? ""
|
|
975
|
+
})),
|
|
976
|
+
bcc: (env.bcc ?? []).map((a) => ({
|
|
977
|
+
name: a.name,
|
|
978
|
+
address: a.address ?? ""
|
|
979
|
+
})),
|
|
969
980
|
date: env.date ?? /* @__PURE__ */ new Date(),
|
|
970
981
|
flags: msg.flags ?? /* @__PURE__ */ new Set(),
|
|
971
982
|
size: msg.size ?? 0
|
|
@@ -1165,8 +1176,8 @@ var MailReceiver = class {
|
|
|
1165
1176
|
}));
|
|
1166
1177
|
}
|
|
1167
1178
|
/** Create a new IMAP folder */
|
|
1168
|
-
async createFolder(
|
|
1169
|
-
await this.client.mailboxCreate(
|
|
1179
|
+
async createFolder(path2) {
|
|
1180
|
+
await this.client.mailboxCreate(path2);
|
|
1170
1181
|
}
|
|
1171
1182
|
/** Batch mark multiple messages as seen */
|
|
1172
1183
|
async batchMarkSeen(uids, mailbox = "INBOX") {
|
|
@@ -1706,8 +1717,8 @@ var StalwartAdmin = class {
|
|
|
1706
1717
|
}
|
|
1707
1718
|
baseUrl;
|
|
1708
1719
|
authHeader;
|
|
1709
|
-
async request(method,
|
|
1710
|
-
const url = `${this.baseUrl}/api${
|
|
1720
|
+
async request(method, path2, body) {
|
|
1721
|
+
const url = `${this.baseUrl}/api${path2}`;
|
|
1711
1722
|
const response = await fetch(url, {
|
|
1712
1723
|
method,
|
|
1713
1724
|
headers: {
|
|
@@ -1868,14 +1879,14 @@ var StalwartAdmin = class {
|
|
|
1868
1879
|
if (!isValidDomain(domain)) {
|
|
1869
1880
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
1870
1881
|
}
|
|
1871
|
-
const { readFileSync:
|
|
1872
|
-
const { homedir:
|
|
1873
|
-
const { join:
|
|
1874
|
-
const configPath =
|
|
1882
|
+
const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
|
|
1883
|
+
const { homedir: homedir13 } = await import("os");
|
|
1884
|
+
const { join: join15 } = await import("path");
|
|
1885
|
+
const configPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
1875
1886
|
try {
|
|
1876
|
-
let config =
|
|
1887
|
+
let config = readFileSync9(configPath, "utf-8");
|
|
1877
1888
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
1878
|
-
|
|
1889
|
+
writeFileSync10(configPath, config);
|
|
1879
1890
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
1880
1891
|
} catch (err) {
|
|
1881
1892
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -1884,15 +1895,15 @@ var StalwartAdmin = class {
|
|
|
1884
1895
|
// --- DKIM ---
|
|
1885
1896
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
1886
1897
|
get configPath() {
|
|
1887
|
-
const { homedir:
|
|
1888
|
-
const { join:
|
|
1889
|
-
return
|
|
1898
|
+
const { homedir: homedir13 } = require("os");
|
|
1899
|
+
const { join: join15 } = require("path");
|
|
1900
|
+
return join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
1890
1901
|
}
|
|
1891
1902
|
/** Path to host-side DKIM key directory */
|
|
1892
1903
|
get dkimDir() {
|
|
1893
|
-
const { homedir:
|
|
1894
|
-
const { join:
|
|
1895
|
-
return
|
|
1904
|
+
const { homedir: homedir13 } = require("os");
|
|
1905
|
+
const { join: join15 } = require("path");
|
|
1906
|
+
return join15(homedir13(), ".agenticmail");
|
|
1896
1907
|
}
|
|
1897
1908
|
/**
|
|
1898
1909
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -1993,12 +2004,12 @@ var StalwartAdmin = class {
|
|
|
1993
2004
|
* This bypasses the need for a PTR record on the sending IP.
|
|
1994
2005
|
*/
|
|
1995
2006
|
async configureOutboundRelay(config) {
|
|
1996
|
-
const { readFileSync:
|
|
1997
|
-
const { homedir:
|
|
1998
|
-
const { join:
|
|
2007
|
+
const { readFileSync: readFileSync9, writeFileSync: writeFileSync10 } = await import("fs");
|
|
2008
|
+
const { homedir: homedir13 } = await import("os");
|
|
2009
|
+
const { join: join15 } = await import("path");
|
|
1999
2010
|
const routeName = config.routeName ?? "gmail";
|
|
2000
|
-
const tomlPath =
|
|
2001
|
-
let toml =
|
|
2011
|
+
const tomlPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
2012
|
+
let toml = readFileSync9(tomlPath, "utf-8");
|
|
2002
2013
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
2003
2014
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
2004
2015
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -2018,7 +2029,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
2018
2029
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
2019
2030
|
{ else = "'${safeRouteName}'" } ]
|
|
2020
2031
|
`;
|
|
2021
|
-
|
|
2032
|
+
writeFileSync10(tomlPath, toml, "utf-8");
|
|
2022
2033
|
await this.restartContainer();
|
|
2023
2034
|
}
|
|
2024
2035
|
};
|
|
@@ -2401,11 +2412,11 @@ var AgentDeletionService = class {
|
|
|
2401
2412
|
};
|
|
2402
2413
|
}
|
|
2403
2414
|
saveToFile(report) {
|
|
2404
|
-
const
|
|
2405
|
-
(0, import_node_fs2.mkdirSync)(
|
|
2415
|
+
const dir2 = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".agenticmail", "deletions");
|
|
2416
|
+
(0, import_node_fs2.mkdirSync)(dir2, { recursive: true });
|
|
2406
2417
|
const timestamp = report.deletedAt.replace(/[:.]/g, "-");
|
|
2407
2418
|
const filename = `${report.agent.name}_${timestamp}.json`;
|
|
2408
|
-
const filePath = (0, import_node_path2.join)(
|
|
2419
|
+
const filePath = (0, import_node_path2.join)(dir2, filename);
|
|
2409
2420
|
(0, import_node_fs2.writeFileSync)(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
2410
2421
|
return filePath;
|
|
2411
2422
|
}
|
|
@@ -4696,8 +4707,8 @@ var CloudflareClient = class {
|
|
|
4696
4707
|
return resp.result;
|
|
4697
4708
|
}
|
|
4698
4709
|
// --- Internal ---
|
|
4699
|
-
async request(method,
|
|
4700
|
-
const url = `${CF_API_BASE}${
|
|
4710
|
+
async request(method, path2, body) {
|
|
4711
|
+
const url = `${CF_API_BASE}${path2}`;
|
|
4701
4712
|
const response = await fetch(url, {
|
|
4702
4713
|
method,
|
|
4703
4714
|
headers: {
|
|
@@ -5019,9 +5030,9 @@ var TunnelManager = class {
|
|
|
5019
5030
|
throw new Error(`Failed to download cloudflared: ${response.statusText}`);
|
|
5020
5031
|
}
|
|
5021
5032
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
5022
|
-
const { writeFile:
|
|
5033
|
+
const { writeFile: writeFile4, rename: rename2 } = await import("fs/promises");
|
|
5023
5034
|
const tmpPath = this.binPath + ".tmp";
|
|
5024
|
-
await
|
|
5035
|
+
await writeFile4(tmpPath, buffer);
|
|
5025
5036
|
await (0, import_promises.chmod)(tmpPath, 493);
|
|
5026
5037
|
await rename2(tmpPath, this.binPath);
|
|
5027
5038
|
return this.binPath;
|
|
@@ -5314,6 +5325,33 @@ var SmsManager = class {
|
|
|
5314
5325
|
meta.sms = config;
|
|
5315
5326
|
this.db.prepare("UPDATE agents SET metadata = ?, updated_at = datetime('now') WHERE id = ?").run(JSON.stringify(meta), agentId);
|
|
5316
5327
|
}
|
|
5328
|
+
/**
|
|
5329
|
+
* Resolve the operator's "where do I get pinged" address from an
|
|
5330
|
+
* agent's SMS config. Used by the dispatcher's bridge-escalation
|
|
5331
|
+
* path: when sub-agents mail a bridge with no fresh host session
|
|
5332
|
+
* available, we email the operator a digest at this address. Their
|
|
5333
|
+
* phone's Gmail push notification surfaces it within seconds —
|
|
5334
|
+
* effectively a free, programmatic alert channel.
|
|
5335
|
+
*
|
|
5336
|
+
* Returns the configured `forwardingEmail` (the same Gmail Google
|
|
5337
|
+
* Voice forwards inbound SMS to, which the operator already has
|
|
5338
|
+
* push notifications enabled for) when SMS is configured AND
|
|
5339
|
+
* enabled. Returns null otherwise — caller falls through to a
|
|
5340
|
+
* silent log + system event.
|
|
5341
|
+
*
|
|
5342
|
+
* Why we don't try real-SMS delivery yet: Google Voice's
|
|
5343
|
+
* `<number>@txt.voice.google.com` email-to-SMS gateway was
|
|
5344
|
+
* deprecated by Google years ago. A future `carrier` field on
|
|
5345
|
+
* SmsConfig (Verizon vtext.com / AT&T txt.att.net / etc) will let
|
|
5346
|
+
* the operator opt into actual SMS, but that's a follow-up — the
|
|
5347
|
+
* email path already gets the operator a phone notification.
|
|
5348
|
+
*/
|
|
5349
|
+
getAlertEmail(agentId) {
|
|
5350
|
+
const cfg = this.getSmsConfig(agentId);
|
|
5351
|
+
if (!cfg || !cfg.enabled) return null;
|
|
5352
|
+
if (typeof cfg.forwardingEmail !== "string" || !cfg.forwardingEmail.includes("@")) return null;
|
|
5353
|
+
return cfg.forwardingEmail;
|
|
5354
|
+
}
|
|
5317
5355
|
/** Remove SMS config from agent metadata */
|
|
5318
5356
|
removeSmsConfig(agentId) {
|
|
5319
5357
|
const row = this.db.prepare("SELECT metadata FROM agents WHERE id = ?").get(agentId);
|
|
@@ -5929,12 +5967,12 @@ var GatewayManager = class {
|
|
|
5929
5967
|
zone = await this.cfClient.createZone(domain);
|
|
5930
5968
|
}
|
|
5931
5969
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
5932
|
-
const { homedir:
|
|
5933
|
-
const backupDir = (0, import_node_path4.join)(
|
|
5970
|
+
const { homedir: homedir13 } = await import("os");
|
|
5971
|
+
const backupDir = (0, import_node_path4.join)(homedir13(), ".agenticmail");
|
|
5934
5972
|
const backupPath = (0, import_node_path4.join)(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
5935
|
-
const { writeFileSync:
|
|
5936
|
-
|
|
5937
|
-
|
|
5973
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync11 } = await import("fs");
|
|
5974
|
+
mkdirSync11(backupDir, { recursive: true });
|
|
5975
|
+
writeFileSync10(backupPath, JSON.stringify({
|
|
5938
5976
|
domain,
|
|
5939
5977
|
zoneId: zone.id,
|
|
5940
5978
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6695,8 +6733,8 @@ function isDisabled() {
|
|
|
6695
6733
|
function getInstallId() {
|
|
6696
6734
|
if (installId) return installId;
|
|
6697
6735
|
try {
|
|
6698
|
-
const
|
|
6699
|
-
const idFile = (0, import_path.join)(
|
|
6736
|
+
const dir2 = (0, import_path.join)((0, import_os.homedir)(), ".agenticmail");
|
|
6737
|
+
const idFile = (0, import_path.join)(dir2, ".telemetry-id");
|
|
6700
6738
|
if ((0, import_fs.existsSync)(idFile)) {
|
|
6701
6739
|
const id = (0, import_fs.readFileSync)(idFile, "utf8").trim();
|
|
6702
6740
|
if (id && id.length > 10) {
|
|
@@ -6705,7 +6743,7 @@ function getInstallId() {
|
|
|
6705
6743
|
}
|
|
6706
6744
|
}
|
|
6707
6745
|
installId = (0, import_crypto.randomUUID)();
|
|
6708
|
-
if (!(0, import_fs.existsSync)(
|
|
6746
|
+
if (!(0, import_fs.existsSync)(dir2)) (0, import_fs.mkdirSync)(dir2, { recursive: true });
|
|
6709
6747
|
(0, import_fs.writeFileSync)(idFile, installId, "utf8");
|
|
6710
6748
|
return installId;
|
|
6711
6749
|
} catch {
|
|
@@ -6876,22 +6914,77 @@ function redactObject(input, _depth = 0) {
|
|
|
6876
6914
|
return out;
|
|
6877
6915
|
}
|
|
6878
6916
|
|
|
6879
|
-
// src/
|
|
6917
|
+
// src/operator-prefs.ts
|
|
6880
6918
|
var import_node_fs4 = require("fs");
|
|
6881
|
-
var import_node_path6 = require("path");
|
|
6882
6919
|
var import_node_os4 = require("os");
|
|
6883
|
-
|
|
6920
|
+
var import_node_path6 = require("path");
|
|
6921
|
+
function dir() {
|
|
6884
6922
|
return (0, import_node_path6.join)((0, import_node_os4.homedir)(), ".agenticmail");
|
|
6885
6923
|
}
|
|
6924
|
+
function path() {
|
|
6925
|
+
return (0, import_node_path6.join)(dir(), "operator-prefs.json");
|
|
6926
|
+
}
|
|
6927
|
+
function readFile() {
|
|
6928
|
+
if (!(0, import_node_fs4.existsSync)(path())) return { version: 1 };
|
|
6929
|
+
try {
|
|
6930
|
+
const raw = (0, import_node_fs4.readFileSync)(path(), "utf-8");
|
|
6931
|
+
if (!raw.trim()) return { version: 1 };
|
|
6932
|
+
const parsed = JSON.parse(raw);
|
|
6933
|
+
return { version: 1, operatorEmail: typeof parsed.operatorEmail === "string" ? parsed.operatorEmail : void 0 };
|
|
6934
|
+
} catch {
|
|
6935
|
+
return { version: 1 };
|
|
6936
|
+
}
|
|
6937
|
+
}
|
|
6938
|
+
function writeFile(shape) {
|
|
6939
|
+
const d = dir();
|
|
6940
|
+
const p = path();
|
|
6941
|
+
if (!(0, import_node_fs4.existsSync)(d)) (0, import_node_fs4.mkdirSync)(d, { recursive: true });
|
|
6942
|
+
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6943
|
+
(0, import_node_fs4.writeFileSync)(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
6944
|
+
(0, import_node_fs4.renameSync)(tmp, p);
|
|
6945
|
+
}
|
|
6946
|
+
function getOperatorEmail() {
|
|
6947
|
+
const shape = readFile();
|
|
6948
|
+
const email = shape.operatorEmail;
|
|
6949
|
+
if (typeof email !== "string") return null;
|
|
6950
|
+
const trimmed = email.trim();
|
|
6951
|
+
return trimmed.length > 0 && trimmed.includes("@") ? trimmed : null;
|
|
6952
|
+
}
|
|
6953
|
+
function setOperatorEmail(email) {
|
|
6954
|
+
const shape = readFile();
|
|
6955
|
+
if (!email || !email.trim()) {
|
|
6956
|
+
delete shape.operatorEmail;
|
|
6957
|
+
writeFile(shape);
|
|
6958
|
+
return null;
|
|
6959
|
+
}
|
|
6960
|
+
const trimmed = email.trim();
|
|
6961
|
+
if (!trimmed.includes("@")) {
|
|
6962
|
+
throw new Error("operator email must contain an @");
|
|
6963
|
+
}
|
|
6964
|
+
shape.operatorEmail = trimmed;
|
|
6965
|
+
writeFile(shape);
|
|
6966
|
+
return trimmed;
|
|
6967
|
+
}
|
|
6968
|
+
function operatorPrefsStoragePath() {
|
|
6969
|
+
return path();
|
|
6970
|
+
}
|
|
6971
|
+
|
|
6972
|
+
// src/host-sessions.ts
|
|
6973
|
+
var import_node_fs5 = require("fs");
|
|
6974
|
+
var import_node_path7 = require("path");
|
|
6975
|
+
var import_node_os5 = require("os");
|
|
6976
|
+
function storageDir() {
|
|
6977
|
+
return (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".agenticmail");
|
|
6978
|
+
}
|
|
6886
6979
|
function storagePath() {
|
|
6887
|
-
return (0,
|
|
6980
|
+
return (0, import_node_path7.join)(storageDir(), "host-sessions.json");
|
|
6888
6981
|
}
|
|
6889
6982
|
var DEFAULT_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
6890
|
-
function
|
|
6983
|
+
function readFile2() {
|
|
6891
6984
|
const p = storagePath();
|
|
6892
|
-
if (!(0,
|
|
6985
|
+
if (!(0, import_node_fs5.existsSync)(p)) return { version: 1, sessions: {} };
|
|
6893
6986
|
try {
|
|
6894
|
-
const raw = (0,
|
|
6987
|
+
const raw = (0, import_node_fs5.readFileSync)(p, "utf-8");
|
|
6895
6988
|
if (!raw.trim()) return { version: 1, sessions: {} };
|
|
6896
6989
|
const parsed = JSON.parse(raw);
|
|
6897
6990
|
return {
|
|
@@ -6902,28 +6995,28 @@ function readFile() {
|
|
|
6902
6995
|
return { version: 1, sessions: {} };
|
|
6903
6996
|
}
|
|
6904
6997
|
}
|
|
6905
|
-
function
|
|
6906
|
-
const
|
|
6998
|
+
function writeFile2(shape) {
|
|
6999
|
+
const dir2 = storageDir();
|
|
6907
7000
|
const p = storagePath();
|
|
6908
|
-
if (!(0,
|
|
7001
|
+
if (!(0, import_node_fs5.existsSync)(dir2)) (0, import_node_fs5.mkdirSync)(dir2, { recursive: true });
|
|
6909
7002
|
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6910
|
-
(0,
|
|
6911
|
-
(0,
|
|
7003
|
+
(0, import_node_fs5.writeFileSync)(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
7004
|
+
(0, import_node_fs5.renameSync)(tmp, p);
|
|
6912
7005
|
}
|
|
6913
7006
|
function saveHostSession(host, session) {
|
|
6914
7007
|
if (!session.sessionId) return;
|
|
6915
7008
|
try {
|
|
6916
|
-
const shape =
|
|
7009
|
+
const shape = readFile2();
|
|
6917
7010
|
shape.sessions[host] = {
|
|
6918
7011
|
...session,
|
|
6919
7012
|
lastSeenMs: Date.now()
|
|
6920
7013
|
};
|
|
6921
|
-
|
|
7014
|
+
writeFile2(shape);
|
|
6922
7015
|
} catch {
|
|
6923
7016
|
}
|
|
6924
7017
|
}
|
|
6925
7018
|
function loadHostSession(host, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
6926
|
-
const shape =
|
|
7019
|
+
const shape = readFile2();
|
|
6927
7020
|
const record = shape.sessions[host];
|
|
6928
7021
|
if (!record) return null;
|
|
6929
7022
|
if (!isSessionFresh(record, maxAgeMs)) return null;
|
|
@@ -6935,10 +7028,10 @@ function isSessionFresh(session, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
|
6935
7028
|
}
|
|
6936
7029
|
function forgetHostSession(host) {
|
|
6937
7030
|
try {
|
|
6938
|
-
const shape =
|
|
7031
|
+
const shape = readFile2();
|
|
6939
7032
|
if (!shape.sessions[host]) return;
|
|
6940
7033
|
delete shape.sessions[host];
|
|
6941
|
-
|
|
7034
|
+
writeFile2(shape);
|
|
6942
7035
|
} catch {
|
|
6943
7036
|
}
|
|
6944
7037
|
}
|
|
@@ -6988,21 +7081,21 @@ function validateApiUrl(raw) {
|
|
|
6988
7081
|
return parsed.origin;
|
|
6989
7082
|
}
|
|
6990
7083
|
function buildApiUrl(baseOrigin, pathAndQuery) {
|
|
6991
|
-
const
|
|
6992
|
-
return new URL(
|
|
7084
|
+
const path2 = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
|
|
7085
|
+
return new URL(path2, baseOrigin + "/").toString();
|
|
6993
7086
|
}
|
|
6994
7087
|
|
|
6995
7088
|
// src/setup/index.ts
|
|
6996
7089
|
var import_node_crypto3 = require("crypto");
|
|
6997
|
-
var
|
|
6998
|
-
var
|
|
6999
|
-
var
|
|
7090
|
+
var import_node_fs9 = require("fs");
|
|
7091
|
+
var import_node_path11 = require("path");
|
|
7092
|
+
var import_node_os9 = require("os");
|
|
7000
7093
|
|
|
7001
7094
|
// src/setup/deps.ts
|
|
7002
7095
|
var import_node_child_process2 = require("child_process");
|
|
7003
|
-
var
|
|
7004
|
-
var
|
|
7005
|
-
var
|
|
7096
|
+
var import_node_fs6 = require("fs");
|
|
7097
|
+
var import_node_path8 = require("path");
|
|
7098
|
+
var import_node_os6 = require("os");
|
|
7006
7099
|
var DependencyChecker = class {
|
|
7007
7100
|
async checkAll() {
|
|
7008
7101
|
return Promise.all([
|
|
@@ -7052,8 +7145,8 @@ var DependencyChecker = class {
|
|
|
7052
7145
|
}
|
|
7053
7146
|
}
|
|
7054
7147
|
async checkCloudflared() {
|
|
7055
|
-
const binPath = (0,
|
|
7056
|
-
if ((0,
|
|
7148
|
+
const binPath = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".agenticmail", "bin", "cloudflared");
|
|
7149
|
+
if ((0, import_node_fs6.existsSync)(binPath)) {
|
|
7057
7150
|
let version;
|
|
7058
7151
|
try {
|
|
7059
7152
|
const output = (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -7075,10 +7168,10 @@ var DependencyChecker = class {
|
|
|
7075
7168
|
|
|
7076
7169
|
// src/setup/installer.ts
|
|
7077
7170
|
var import_node_child_process3 = require("child_process");
|
|
7078
|
-
var
|
|
7171
|
+
var import_node_fs7 = require("fs");
|
|
7079
7172
|
var import_promises2 = require("fs/promises");
|
|
7080
|
-
var
|
|
7081
|
-
var
|
|
7173
|
+
var import_node_path9 = require("path");
|
|
7174
|
+
var import_node_os7 = require("os");
|
|
7082
7175
|
function runShellWithRollingOutput(cmd, opts = {}) {
|
|
7083
7176
|
const maxLines = opts.maxLines ?? 20;
|
|
7084
7177
|
const timeout = opts.timeout ?? 3e5;
|
|
@@ -7188,7 +7281,7 @@ var DependencyInstaller = class {
|
|
|
7188
7281
|
*/
|
|
7189
7282
|
async installDocker() {
|
|
7190
7283
|
if (this.isDockerReady()) return;
|
|
7191
|
-
const os = (0,
|
|
7284
|
+
const os = (0, import_node_os7.platform)();
|
|
7192
7285
|
if (os === "darwin") {
|
|
7193
7286
|
await this.installDockerMac();
|
|
7194
7287
|
} else if (os === "linux") {
|
|
@@ -7254,15 +7347,15 @@ var DependencyInstaller = class {
|
|
|
7254
7347
|
try {
|
|
7255
7348
|
const composeBin = (0, import_node_child_process3.execFileSync)("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7256
7349
|
if (!composeBin) return;
|
|
7257
|
-
const pluginDir = (0,
|
|
7258
|
-
const pluginPath = (0,
|
|
7259
|
-
if ((0,
|
|
7350
|
+
const pluginDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".docker", "cli-plugins");
|
|
7351
|
+
const pluginPath = (0, import_node_path9.join)(pluginDir, "docker-compose");
|
|
7352
|
+
if ((0, import_node_fs7.existsSync)(pluginPath)) return;
|
|
7260
7353
|
try {
|
|
7261
|
-
(0,
|
|
7354
|
+
(0, import_node_fs7.mkdirSync)(pluginDir, { recursive: true });
|
|
7262
7355
|
} catch {
|
|
7263
7356
|
}
|
|
7264
7357
|
try {
|
|
7265
|
-
(0,
|
|
7358
|
+
(0, import_node_fs7.symlinkSync)(composeBin, pluginPath);
|
|
7266
7359
|
} catch {
|
|
7267
7360
|
}
|
|
7268
7361
|
} catch {
|
|
@@ -7321,9 +7414,9 @@ var DependencyInstaller = class {
|
|
|
7321
7414
|
return;
|
|
7322
7415
|
}
|
|
7323
7416
|
this.onProgress("__progress__:5:Installing Docker Engine...");
|
|
7324
|
-
const tmpDir = (0,
|
|
7417
|
+
const tmpDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".agenticmail", "tmp");
|
|
7325
7418
|
await (0, import_promises2.mkdir)(tmpDir, { recursive: true });
|
|
7326
|
-
const scriptPath = (0,
|
|
7419
|
+
const scriptPath = (0, import_node_path9.join)(tmpDir, "install-docker.sh");
|
|
7327
7420
|
const dlResult = await runShellWithRollingOutput(
|
|
7328
7421
|
`curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
|
|
7329
7422
|
{ timeout: 3e5 }
|
|
@@ -7391,8 +7484,8 @@ var DependencyInstaller = class {
|
|
|
7391
7484
|
}
|
|
7392
7485
|
try {
|
|
7393
7486
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7394
|
-
const dockerExe = (0,
|
|
7395
|
-
if ((0,
|
|
7487
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7488
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7396
7489
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7397
7490
|
}
|
|
7398
7491
|
} catch {
|
|
@@ -7442,8 +7535,8 @@ var DependencyInstaller = class {
|
|
|
7442
7535
|
this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
|
|
7443
7536
|
try {
|
|
7444
7537
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7445
|
-
const dockerExe = (0,
|
|
7446
|
-
if ((0,
|
|
7538
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7539
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7447
7540
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7448
7541
|
}
|
|
7449
7542
|
} catch {
|
|
@@ -7480,12 +7573,12 @@ var DependencyInstaller = class {
|
|
|
7480
7573
|
* Start the Stalwart mail server Docker container.
|
|
7481
7574
|
*/
|
|
7482
7575
|
async startStalwart(composePath) {
|
|
7483
|
-
if (!(0,
|
|
7576
|
+
if (!(0, import_node_fs7.existsSync)(composePath)) {
|
|
7484
7577
|
throw new Error(`docker-compose.yml not found at: ${composePath}`);
|
|
7485
7578
|
}
|
|
7486
7579
|
if (!this.isDockerReady()) {
|
|
7487
7580
|
this.onProgress("Starting Docker...");
|
|
7488
|
-
const os = (0,
|
|
7581
|
+
const os = (0, import_node_os7.platform)();
|
|
7489
7582
|
if (os === "darwin") {
|
|
7490
7583
|
await this.startColima();
|
|
7491
7584
|
} else if (os === "win32") {
|
|
@@ -7503,7 +7596,7 @@ var DependencyInstaller = class {
|
|
|
7503
7596
|
}
|
|
7504
7597
|
}
|
|
7505
7598
|
this.onProgress("__progress__:10:Pulling mail server image...");
|
|
7506
|
-
if ((0,
|
|
7599
|
+
if ((0, import_node_os7.platform)() === "darwin") this.linkComposePlugin();
|
|
7507
7600
|
let composeResult = await runSilent("docker", ["compose", "-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
7508
7601
|
if (composeResult.exitCode !== 0 && hasCommand("docker-compose")) {
|
|
7509
7602
|
composeResult = await runSilent("docker-compose", ["-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
@@ -7538,22 +7631,22 @@ var DependencyInstaller = class {
|
|
|
7538
7631
|
* Returns the path to the installed binary.
|
|
7539
7632
|
*/
|
|
7540
7633
|
async installCloudflared() {
|
|
7541
|
-
const os = (0,
|
|
7542
|
-
const binDir = (0,
|
|
7634
|
+
const os = (0, import_node_os7.platform)();
|
|
7635
|
+
const binDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".agenticmail", "bin");
|
|
7543
7636
|
const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
7544
|
-
const binPath = (0,
|
|
7545
|
-
if ((0,
|
|
7637
|
+
const binPath = (0, import_node_path9.join)(binDir, binName);
|
|
7638
|
+
if ((0, import_node_fs7.existsSync)(binPath)) {
|
|
7546
7639
|
return binPath;
|
|
7547
7640
|
}
|
|
7548
7641
|
try {
|
|
7549
7642
|
const whichCmd = os === "win32" ? "where" : "which";
|
|
7550
7643
|
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,
|
|
7644
|
+
if (sysPath && (0, import_node_fs7.existsSync)(sysPath)) return sysPath;
|
|
7552
7645
|
} catch {
|
|
7553
7646
|
}
|
|
7554
7647
|
this.onProgress("Downloading cloudflared...");
|
|
7555
7648
|
await (0, import_promises2.mkdir)(binDir, { recursive: true });
|
|
7556
|
-
const cpu = (0,
|
|
7649
|
+
const cpu = (0, import_node_os7.arch)();
|
|
7557
7650
|
const archName = cpu === "arm64" ? "arm64" : "amd64";
|
|
7558
7651
|
let downloadUrl;
|
|
7559
7652
|
if (os === "darwin") {
|
|
@@ -7571,7 +7664,7 @@ var DependencyInstaller = class {
|
|
|
7571
7664
|
}
|
|
7572
7665
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7573
7666
|
if (os === "darwin") {
|
|
7574
|
-
const tgzPath = (0,
|
|
7667
|
+
const tgzPath = (0, import_node_path9.join)(binDir, "cloudflared.tgz");
|
|
7575
7668
|
await (0, import_promises2.writeFile)(tgzPath, buffer);
|
|
7576
7669
|
try {
|
|
7577
7670
|
(0, import_node_child_process3.execFileSync)("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
|
|
@@ -7588,7 +7681,7 @@ var DependencyInstaller = class {
|
|
|
7588
7681
|
if (os !== "win32") await (0, import_promises2.chmod)(tmpPath, 493);
|
|
7589
7682
|
await (0, import_promises2.rename)(tmpPath, binPath);
|
|
7590
7683
|
}
|
|
7591
|
-
if (!(0,
|
|
7684
|
+
if (!(0, import_node_fs7.existsSync)(binPath)) {
|
|
7592
7685
|
throw new Error("cloudflared download succeeded but binary not found after extraction");
|
|
7593
7686
|
}
|
|
7594
7687
|
this.onProgress("cloudflared installed");
|
|
@@ -7606,23 +7699,23 @@ var DependencyInstaller = class {
|
|
|
7606
7699
|
|
|
7607
7700
|
// src/setup/service.ts
|
|
7608
7701
|
var import_node_child_process4 = require("child_process");
|
|
7609
|
-
var
|
|
7610
|
-
var
|
|
7611
|
-
var
|
|
7702
|
+
var import_node_fs8 = require("fs");
|
|
7703
|
+
var import_node_path10 = require("path");
|
|
7704
|
+
var import_node_os8 = require("os");
|
|
7612
7705
|
var import_node_module2 = require("module");
|
|
7613
7706
|
var import_meta2 = {};
|
|
7614
7707
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
7615
7708
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
7616
7709
|
var ServiceManager = class {
|
|
7617
|
-
os = (0,
|
|
7710
|
+
os = (0, import_node_os8.platform)();
|
|
7618
7711
|
/**
|
|
7619
7712
|
* Get the path to the service file.
|
|
7620
7713
|
*/
|
|
7621
7714
|
getServicePath() {
|
|
7622
7715
|
if (this.os === "darwin") {
|
|
7623
|
-
return (0,
|
|
7716
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
7624
7717
|
} else {
|
|
7625
|
-
return (0,
|
|
7718
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
7626
7719
|
}
|
|
7627
7720
|
}
|
|
7628
7721
|
/**
|
|
@@ -7656,40 +7749,40 @@ var ServiceManager = class {
|
|
|
7656
7749
|
try {
|
|
7657
7750
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7658
7751
|
const resolved = req.resolve("@agenticmail/api");
|
|
7659
|
-
if ((0,
|
|
7752
|
+
if ((0, import_node_fs8.existsSync)(resolved)) return resolved;
|
|
7660
7753
|
} catch {
|
|
7661
7754
|
}
|
|
7662
7755
|
const parentPackages = [
|
|
7663
|
-
(0,
|
|
7756
|
+
(0, import_node_path10.join)("@agenticmail", "cli"),
|
|
7664
7757
|
// current scoped package
|
|
7665
7758
|
"agenticmail"
|
|
7666
7759
|
// legacy unscoped package
|
|
7667
7760
|
];
|
|
7668
7761
|
const baseDirs = [
|
|
7669
7762
|
// user-local install
|
|
7670
|
-
(0,
|
|
7763
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules")
|
|
7671
7764
|
];
|
|
7672
7765
|
try {
|
|
7673
7766
|
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,
|
|
7767
|
+
baseDirs.push((0, import_node_path10.join)(prefix, "lib", "node_modules"));
|
|
7768
|
+
baseDirs.push((0, import_node_path10.join)(prefix, "node_modules"));
|
|
7676
7769
|
} catch {
|
|
7677
7770
|
}
|
|
7678
7771
|
baseDirs.push("/opt/homebrew/lib/node_modules");
|
|
7679
7772
|
baseDirs.push("/usr/local/lib/node_modules");
|
|
7680
7773
|
for (const base of baseDirs) {
|
|
7681
|
-
const sibling = (0,
|
|
7682
|
-
if ((0,
|
|
7774
|
+
const sibling = (0, import_node_path10.join)(base, "@agenticmail", "api", "dist", "index.js");
|
|
7775
|
+
if ((0, import_node_fs8.existsSync)(sibling)) return sibling;
|
|
7683
7776
|
for (const parent of parentPackages) {
|
|
7684
|
-
const nested = (0,
|
|
7685
|
-
if ((0,
|
|
7777
|
+
const nested = (0, import_node_path10.join)(base, parent, "node_modules", "@agenticmail", "api", "dist", "index.js");
|
|
7778
|
+
if ((0, import_node_fs8.existsSync)(nested)) return nested;
|
|
7686
7779
|
}
|
|
7687
7780
|
}
|
|
7688
|
-
const dataDir = (0,
|
|
7689
|
-
const entryCache = (0,
|
|
7690
|
-
if ((0,
|
|
7691
|
-
const cached = (0,
|
|
7692
|
-
if (cached && (0,
|
|
7781
|
+
const dataDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7782
|
+
const entryCache = (0, import_node_path10.join)(dataDir, "api-entry.path");
|
|
7783
|
+
if ((0, import_node_fs8.existsSync)(entryCache)) {
|
|
7784
|
+
const cached = (0, import_node_fs8.readFileSync)(entryCache, "utf-8").trim();
|
|
7785
|
+
if (cached && (0, import_node_fs8.existsSync)(cached)) return cached;
|
|
7693
7786
|
}
|
|
7694
7787
|
throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
|
|
7695
7788
|
}
|
|
@@ -7697,9 +7790,9 @@ var ServiceManager = class {
|
|
|
7697
7790
|
* Cache the API entry path so the service can find it later.
|
|
7698
7791
|
*/
|
|
7699
7792
|
cacheApiEntryPath(entryPath) {
|
|
7700
|
-
const dataDir = (0,
|
|
7701
|
-
if (!(0,
|
|
7702
|
-
(0,
|
|
7793
|
+
const dataDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7794
|
+
if (!(0, import_node_fs8.existsSync)(dataDir)) (0, import_node_fs8.mkdirSync)(dataDir, { recursive: true });
|
|
7795
|
+
(0, import_node_fs8.writeFileSync)((0, import_node_path10.join)(dataDir, "api-entry.path"), entryPath);
|
|
7703
7796
|
}
|
|
7704
7797
|
/**
|
|
7705
7798
|
* Get the current package version.
|
|
@@ -7712,36 +7805,36 @@ var ServiceManager = class {
|
|
|
7712
7805
|
try {
|
|
7713
7806
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7714
7807
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
7715
|
-
if ((0,
|
|
7716
|
-
const pkg = JSON.parse((0,
|
|
7808
|
+
if ((0, import_node_fs8.existsSync)(pkgJson)) {
|
|
7809
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(pkgJson, "utf-8"));
|
|
7717
7810
|
if (pkg.version) return pkg.version;
|
|
7718
7811
|
}
|
|
7719
7812
|
} catch {
|
|
7720
7813
|
}
|
|
7721
7814
|
try {
|
|
7722
7815
|
const apiEntry = this.getApiEntryPath();
|
|
7723
|
-
const apiPkg = (0,
|
|
7724
|
-
if ((0,
|
|
7725
|
-
const pkg = JSON.parse((0,
|
|
7816
|
+
const apiPkg = (0, import_node_path10.join)(apiEntry, "..", "..", "package.json");
|
|
7817
|
+
if ((0, import_node_fs8.existsSync)(apiPkg)) {
|
|
7818
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(apiPkg, "utf-8"));
|
|
7726
7819
|
if (pkg.version) return pkg.version;
|
|
7727
7820
|
}
|
|
7728
7821
|
} catch {
|
|
7729
7822
|
}
|
|
7730
7823
|
const candidates = [
|
|
7731
|
-
(0,
|
|
7732
|
-
(0,
|
|
7733
|
-
(0,
|
|
7824
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules", "@agenticmail", "cli", "package.json"),
|
|
7825
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules", "agenticmail", "package.json"),
|
|
7826
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "package-version.json")
|
|
7734
7827
|
];
|
|
7735
7828
|
try {
|
|
7736
7829
|
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,
|
|
7830
|
+
candidates.push((0, import_node_path10.join)(prefix, "lib", "node_modules", "@agenticmail", "cli", "package.json"));
|
|
7831
|
+
candidates.push((0, import_node_path10.join)(prefix, "lib", "node_modules", "agenticmail", "package.json"));
|
|
7739
7832
|
} catch {
|
|
7740
7833
|
}
|
|
7741
7834
|
for (const p of candidates) {
|
|
7742
7835
|
try {
|
|
7743
|
-
if ((0,
|
|
7744
|
-
const pkg = JSON.parse((0,
|
|
7836
|
+
if ((0, import_node_fs8.existsSync)(p)) {
|
|
7837
|
+
const pkg = JSON.parse((0, import_node_fs8.readFileSync)(p, "utf-8"));
|
|
7745
7838
|
if (pkg.version) return pkg.version;
|
|
7746
7839
|
}
|
|
7747
7840
|
} catch {
|
|
@@ -7754,9 +7847,9 @@ var ServiceManager = class {
|
|
|
7754
7847
|
* This ensures AgenticMail doesn't fail on boot when Docker is still loading.
|
|
7755
7848
|
*/
|
|
7756
7849
|
generateStartScript(nodePath, apiEntry) {
|
|
7757
|
-
const scriptPath = (0,
|
|
7758
|
-
const scriptDir = (0,
|
|
7759
|
-
if (!(0,
|
|
7850
|
+
const scriptPath = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin", "start-server.sh");
|
|
7851
|
+
const scriptDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin");
|
|
7852
|
+
if (!(0, import_node_fs8.existsSync)(scriptDir)) (0, import_node_fs8.mkdirSync)(scriptDir, { recursive: true });
|
|
7760
7853
|
const script = [
|
|
7761
7854
|
"#!/bin/bash",
|
|
7762
7855
|
"# AgenticMail auto-start script",
|
|
@@ -7807,7 +7900,7 @@ var ServiceManager = class {
|
|
|
7807
7900
|
`log "Starting API server: ${nodePath} ${apiEntry}"`,
|
|
7808
7901
|
`exec "${nodePath}" "${apiEntry}"`
|
|
7809
7902
|
].join("\n") + "\n";
|
|
7810
|
-
(0,
|
|
7903
|
+
(0, import_node_fs8.writeFileSync)(scriptPath, script, { mode: 493 });
|
|
7811
7904
|
return scriptPath;
|
|
7812
7905
|
}
|
|
7813
7906
|
/**
|
|
@@ -7820,9 +7913,9 @@ var ServiceManager = class {
|
|
|
7820
7913
|
* - Service version tracking in env vars
|
|
7821
7914
|
*/
|
|
7822
7915
|
generatePlist(nodePath, apiEntry, configPath) {
|
|
7823
|
-
const config = JSON.parse((0,
|
|
7824
|
-
const logDir = (0,
|
|
7825
|
-
if (!(0,
|
|
7916
|
+
const config = JSON.parse((0, import_node_fs8.readFileSync)(configPath, "utf-8"));
|
|
7917
|
+
const logDir = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "logs");
|
|
7918
|
+
if (!(0, import_node_fs8.existsSync)(logDir)) (0, import_node_fs8.mkdirSync)(logDir, { recursive: true });
|
|
7826
7919
|
const version = this.getVersion();
|
|
7827
7920
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7828
7921
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -7843,9 +7936,9 @@ var ServiceManager = class {
|
|
|
7843
7936
|
<key>EnvironmentVariables</key>
|
|
7844
7937
|
<dict>
|
|
7845
7938
|
<key>HOME</key>
|
|
7846
|
-
<string>${(0,
|
|
7939
|
+
<string>${(0, import_node_os8.homedir)()}</string>
|
|
7847
7940
|
<key>AGENTICMAIL_DATA_DIR</key>
|
|
7848
|
-
<string>${config.dataDir || (0,
|
|
7941
|
+
<string>${config.dataDir || (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail")}</string>
|
|
7849
7942
|
<key>PATH</key>
|
|
7850
7943
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
7851
7944
|
<key>AGENTICMAIL_SERVICE_VERSION</key>
|
|
@@ -7898,8 +7991,8 @@ var ServiceManager = class {
|
|
|
7898
7991
|
* - Proper dependency ordering
|
|
7899
7992
|
*/
|
|
7900
7993
|
generateSystemdUnit(nodePath, apiEntry, configPath) {
|
|
7901
|
-
const config = JSON.parse((0,
|
|
7902
|
-
const dataDir = config.dataDir || (0,
|
|
7994
|
+
const config = JSON.parse((0, import_node_fs8.readFileSync)(configPath, "utf-8"));
|
|
7995
|
+
const dataDir = config.dataDir || (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail");
|
|
7903
7996
|
const version = this.getVersion();
|
|
7904
7997
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7905
7998
|
return `[Unit]
|
|
@@ -7916,7 +8009,7 @@ Restart=always
|
|
|
7916
8009
|
RestartSec=15
|
|
7917
8010
|
TimeoutStartSec=660
|
|
7918
8011
|
LimitNOFILE=8192
|
|
7919
|
-
Environment=HOME=${(0,
|
|
8012
|
+
Environment=HOME=${(0, import_node_os8.homedir)()}
|
|
7920
8013
|
Environment=AGENTICMAIL_DATA_DIR=${dataDir}
|
|
7921
8014
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
|
|
7922
8015
|
Environment=AGENTICMAIL_SERVICE_VERSION=${version}
|
|
@@ -7929,8 +8022,8 @@ WantedBy=default.target
|
|
|
7929
8022
|
* Install the auto-start service.
|
|
7930
8023
|
*/
|
|
7931
8024
|
install() {
|
|
7932
|
-
const configPath = (0,
|
|
7933
|
-
if (!(0,
|
|
8025
|
+
const configPath = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "config.json");
|
|
8026
|
+
if (!(0, import_node_fs8.existsSync)(configPath)) {
|
|
7934
8027
|
return { installed: false, message: "Config not found. Run agenticmail setup first." };
|
|
7935
8028
|
}
|
|
7936
8029
|
const nodePath = this.getNodePath();
|
|
@@ -7942,17 +8035,17 @@ WantedBy=default.target
|
|
|
7942
8035
|
}
|
|
7943
8036
|
const servicePath = this.getServicePath();
|
|
7944
8037
|
if (this.os === "darwin") {
|
|
7945
|
-
const
|
|
7946
|
-
if (!(0,
|
|
7947
|
-
if ((0,
|
|
8038
|
+
const dir2 = (0, import_node_path10.join)((0, import_node_os8.homedir)(), "Library", "LaunchAgents");
|
|
8039
|
+
if (!(0, import_node_fs8.existsSync)(dir2)) (0, import_node_fs8.mkdirSync)(dir2, { recursive: true });
|
|
8040
|
+
if ((0, import_node_fs8.existsSync)(servicePath)) {
|
|
7948
8041
|
try {
|
|
7949
8042
|
(0, import_node_child_process4.execFileSync)("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7950
8043
|
} catch {
|
|
7951
8044
|
}
|
|
7952
8045
|
}
|
|
7953
8046
|
const plist = this.generatePlist(nodePath, apiEntry, configPath);
|
|
7954
|
-
(0,
|
|
7955
|
-
(0,
|
|
8047
|
+
(0, import_node_fs8.writeFileSync)(servicePath, plist);
|
|
8048
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7956
8049
|
try {
|
|
7957
8050
|
(0, import_node_child_process4.execFileSync)("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7958
8051
|
} catch (err) {
|
|
@@ -7960,11 +8053,11 @@ WantedBy=default.target
|
|
|
7960
8053
|
}
|
|
7961
8054
|
return { installed: true, message: `Service installed at ${servicePath}` };
|
|
7962
8055
|
} else if (this.os === "linux") {
|
|
7963
|
-
const
|
|
7964
|
-
if (!(0,
|
|
8056
|
+
const dir2 = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".config", "systemd", "user");
|
|
8057
|
+
if (!(0, import_node_fs8.existsSync)(dir2)) (0, import_node_fs8.mkdirSync)(dir2, { recursive: true });
|
|
7965
8058
|
const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
|
|
7966
|
-
(0,
|
|
7967
|
-
(0,
|
|
8059
|
+
(0, import_node_fs8.writeFileSync)(servicePath, unit);
|
|
8060
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7968
8061
|
try {
|
|
7969
8062
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
|
|
7970
8063
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "enable", SYSTEMD_UNIT], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -7986,7 +8079,7 @@ WantedBy=default.target
|
|
|
7986
8079
|
*/
|
|
7987
8080
|
uninstall() {
|
|
7988
8081
|
const servicePath = this.getServicePath();
|
|
7989
|
-
if (!(0,
|
|
8082
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) {
|
|
7990
8083
|
return { removed: false, message: "Service is not installed." };
|
|
7991
8084
|
}
|
|
7992
8085
|
if (this.os === "darwin") {
|
|
@@ -7995,7 +8088,7 @@ WantedBy=default.target
|
|
|
7995
8088
|
} catch {
|
|
7996
8089
|
}
|
|
7997
8090
|
try {
|
|
7998
|
-
(0,
|
|
8091
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
7999
8092
|
} catch {
|
|
8000
8093
|
}
|
|
8001
8094
|
return { removed: true, message: "Service removed." };
|
|
@@ -8006,7 +8099,7 @@ WantedBy=default.target
|
|
|
8006
8099
|
} catch {
|
|
8007
8100
|
}
|
|
8008
8101
|
try {
|
|
8009
|
-
(0,
|
|
8102
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
8010
8103
|
} catch {
|
|
8011
8104
|
}
|
|
8012
8105
|
try {
|
|
@@ -8024,7 +8117,7 @@ WantedBy=default.target
|
|
|
8024
8117
|
status() {
|
|
8025
8118
|
const servicePath = this.getServicePath();
|
|
8026
8119
|
const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
|
|
8027
|
-
const installed = (0,
|
|
8120
|
+
const installed = (0, import_node_fs8.existsSync)(servicePath);
|
|
8028
8121
|
let running = false;
|
|
8029
8122
|
if (installed) {
|
|
8030
8123
|
if (this.os === "darwin") {
|
|
@@ -8079,34 +8172,34 @@ WantedBy=default.target
|
|
|
8079
8172
|
needsRepair() {
|
|
8080
8173
|
if (this.os !== "darwin" && this.os !== "linux") return null;
|
|
8081
8174
|
const servicePath = this.getServicePath();
|
|
8082
|
-
if (!(0,
|
|
8175
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) return null;
|
|
8083
8176
|
let serviceContent = "";
|
|
8084
8177
|
try {
|
|
8085
|
-
serviceContent = (0,
|
|
8178
|
+
serviceContent = (0, import_node_fs8.readFileSync)(servicePath, "utf-8");
|
|
8086
8179
|
} catch {
|
|
8087
8180
|
return { reason: "Service file unreadable" };
|
|
8088
8181
|
}
|
|
8089
|
-
const startScript = (0,
|
|
8182
|
+
const startScript = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin", "start-server.sh");
|
|
8090
8183
|
if (serviceContent.includes(startScript)) {
|
|
8091
|
-
if (!(0,
|
|
8184
|
+
if (!(0, import_node_fs8.existsSync)(startScript)) {
|
|
8092
8185
|
return { reason: "start-server.sh is missing" };
|
|
8093
8186
|
}
|
|
8094
8187
|
let scriptContent = "";
|
|
8095
8188
|
try {
|
|
8096
|
-
scriptContent = (0,
|
|
8189
|
+
scriptContent = (0, import_node_fs8.readFileSync)(startScript, "utf-8");
|
|
8097
8190
|
} catch {
|
|
8098
8191
|
return { reason: "start-server.sh unreadable" };
|
|
8099
8192
|
}
|
|
8100
8193
|
const apiPathMatch = scriptContent.match(/(\/[^"\s]+@agenticmail\/api\/dist\/index\.js)/);
|
|
8101
8194
|
if (apiPathMatch) {
|
|
8102
8195
|
const referenced = apiPathMatch[1];
|
|
8103
|
-
if (!(0,
|
|
8196
|
+
if (!(0, import_node_fs8.existsSync)(referenced)) {
|
|
8104
8197
|
return { reason: `start-server.sh references missing path: ${referenced}` };
|
|
8105
8198
|
}
|
|
8106
8199
|
}
|
|
8107
8200
|
if (/node_modules\/agenticmail\/(?!.*@agenticmail\/cli)/.test(scriptContent)) {
|
|
8108
8201
|
const stale = /(\S*node_modules\/agenticmail\/\S*)/.exec(scriptContent)?.[1];
|
|
8109
|
-
if (stale && !(0,
|
|
8202
|
+
if (stale && !(0, import_node_fs8.existsSync)(stale)) {
|
|
8110
8203
|
return { reason: `start-server.sh references legacy unscoped path: ${stale}` };
|
|
8111
8204
|
}
|
|
8112
8205
|
}
|
|
@@ -8119,11 +8212,11 @@ WantedBy=default.target
|
|
|
8119
8212
|
return { reason: `Service version drift (current CLI is v${currentVersion})` };
|
|
8120
8213
|
}
|
|
8121
8214
|
}
|
|
8122
|
-
const entryCache = (0,
|
|
8123
|
-
if ((0,
|
|
8215
|
+
const entryCache = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "api-entry.path");
|
|
8216
|
+
if ((0, import_node_fs8.existsSync)(entryCache)) {
|
|
8124
8217
|
try {
|
|
8125
|
-
const cached = (0,
|
|
8126
|
-
if (cached && !(0,
|
|
8218
|
+
const cached = (0, import_node_fs8.readFileSync)(entryCache, "utf-8").trim();
|
|
8219
|
+
if (cached && !(0, import_node_fs8.existsSync)(cached)) {
|
|
8127
8220
|
return { reason: `Cached API entry path no longer exists: ${cached}` };
|
|
8128
8221
|
}
|
|
8129
8222
|
} catch {
|
|
@@ -8162,8 +8255,8 @@ var SetupManager = class {
|
|
|
8162
8255
|
async ensureStalwart(composePath) {
|
|
8163
8256
|
const status = await this.checker.checkStalwart();
|
|
8164
8257
|
if (status.installed) return;
|
|
8165
|
-
const
|
|
8166
|
-
await this.installer.startStalwart(
|
|
8258
|
+
const path2 = composePath ?? this.getComposePath();
|
|
8259
|
+
await this.installer.startStalwart(path2);
|
|
8167
8260
|
}
|
|
8168
8261
|
async ensureCloudflared() {
|
|
8169
8262
|
return this.installer.installCloudflared();
|
|
@@ -8174,13 +8267,13 @@ var SetupManager = class {
|
|
|
8174
8267
|
* falls back to monorepo location.
|
|
8175
8268
|
*/
|
|
8176
8269
|
getComposePath() {
|
|
8177
|
-
const standalonePath = (0,
|
|
8178
|
-
if ((0,
|
|
8270
|
+
const standalonePath = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail", "docker-compose.yml");
|
|
8271
|
+
if ((0, import_node_fs9.existsSync)(standalonePath)) return standalonePath;
|
|
8179
8272
|
const cwd = process.cwd();
|
|
8180
|
-
const candidates = [cwd, (0,
|
|
8181
|
-
for (const
|
|
8182
|
-
const p = (0,
|
|
8183
|
-
if ((0,
|
|
8273
|
+
const candidates = [cwd, (0, import_node_path11.join)(cwd, "..")];
|
|
8274
|
+
for (const dir2 of candidates) {
|
|
8275
|
+
const p = (0, import_node_path11.join)(dir2, "docker-compose.yml");
|
|
8276
|
+
if ((0, import_node_fs9.existsSync)(p)) return p;
|
|
8184
8277
|
}
|
|
8185
8278
|
return standalonePath;
|
|
8186
8279
|
}
|
|
@@ -8190,19 +8283,19 @@ var SetupManager = class {
|
|
|
8190
8283
|
* Always regenerates Docker files to keep passwords in sync.
|
|
8191
8284
|
*/
|
|
8192
8285
|
initConfig() {
|
|
8193
|
-
const dataDir = (0,
|
|
8194
|
-
const configPath = (0,
|
|
8195
|
-
const envPath = (0,
|
|
8196
|
-
if ((0,
|
|
8286
|
+
const dataDir = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail");
|
|
8287
|
+
const configPath = (0, import_node_path11.join)(dataDir, "config.json");
|
|
8288
|
+
const envPath = (0, import_node_path11.join)(dataDir, ".env");
|
|
8289
|
+
if ((0, import_node_fs9.existsSync)(configPath)) {
|
|
8197
8290
|
try {
|
|
8198
|
-
const existing = JSON.parse((0,
|
|
8291
|
+
const existing = JSON.parse((0, import_node_fs9.readFileSync)(configPath, "utf-8"));
|
|
8199
8292
|
this.generateDockerFiles(existing);
|
|
8200
8293
|
return { configPath, envPath, config: existing, isNew: false };
|
|
8201
8294
|
} catch {
|
|
8202
8295
|
}
|
|
8203
8296
|
}
|
|
8204
|
-
if (!(0,
|
|
8205
|
-
(0,
|
|
8297
|
+
if (!(0, import_node_fs9.existsSync)(dataDir)) {
|
|
8298
|
+
(0, import_node_fs9.mkdirSync)(dataDir, { recursive: true });
|
|
8206
8299
|
}
|
|
8207
8300
|
const masterKey = `mk_${(0, import_node_crypto3.randomBytes)(24).toString("hex")}`;
|
|
8208
8301
|
const stalwartPassword = (0, import_node_crypto3.randomBytes)(16).toString("hex");
|
|
@@ -8218,8 +8311,8 @@ var SetupManager = class {
|
|
|
8218
8311
|
api: { port: 3829, host: "127.0.0.1" },
|
|
8219
8312
|
dataDir
|
|
8220
8313
|
};
|
|
8221
|
-
(0,
|
|
8222
|
-
(0,
|
|
8314
|
+
(0, import_node_fs9.writeFileSync)(configPath, JSON.stringify(config, null, 2));
|
|
8315
|
+
(0, import_node_fs9.chmodSync)(configPath, 384);
|
|
8223
8316
|
const envContent = `# Auto-generated by agenticmail setup
|
|
8224
8317
|
STALWART_ADMIN_USER=admin
|
|
8225
8318
|
STALWART_ADMIN_PASSWORD=${stalwartPassword}
|
|
@@ -8234,8 +8327,8 @@ SMTP_PORT=587
|
|
|
8234
8327
|
IMAP_HOST=localhost
|
|
8235
8328
|
IMAP_PORT=143
|
|
8236
8329
|
`;
|
|
8237
|
-
(0,
|
|
8238
|
-
(0,
|
|
8330
|
+
(0, import_node_fs9.writeFileSync)(envPath, envContent);
|
|
8331
|
+
(0, import_node_fs9.chmodSync)(envPath, 384);
|
|
8239
8332
|
this.generateDockerFiles(config);
|
|
8240
8333
|
return { configPath, envPath, config, isNew: true };
|
|
8241
8334
|
}
|
|
@@ -8244,13 +8337,13 @@ IMAP_PORT=143
|
|
|
8244
8337
|
* with the correct admin password from config.
|
|
8245
8338
|
*/
|
|
8246
8339
|
generateDockerFiles(config) {
|
|
8247
|
-
const dataDir = config.dataDir || (0,
|
|
8248
|
-
if (!(0,
|
|
8249
|
-
(0,
|
|
8340
|
+
const dataDir = config.dataDir || (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail");
|
|
8341
|
+
if (!(0, import_node_fs9.existsSync)(dataDir)) {
|
|
8342
|
+
(0, import_node_fs9.mkdirSync)(dataDir, { recursive: true });
|
|
8250
8343
|
}
|
|
8251
8344
|
const password = config.stalwart?.adminPassword || "changeme";
|
|
8252
|
-
const composePath = (0,
|
|
8253
|
-
(0,
|
|
8345
|
+
const composePath = (0, import_node_path11.join)(dataDir, "docker-compose.yml");
|
|
8346
|
+
(0, import_node_fs9.writeFileSync)(composePath, `services:
|
|
8254
8347
|
stalwart:
|
|
8255
8348
|
# Pinned to v0.15.5 \u2014 Stalwart 0.16+ moved its config to JSON
|
|
8256
8349
|
# at /etc/stalwart/config.json (hardcoded into the container
|
|
@@ -8279,9 +8372,9 @@ IMAP_PORT=143
|
|
|
8279
8372
|
volumes:
|
|
8280
8373
|
stalwart-data:
|
|
8281
8374
|
`);
|
|
8282
|
-
(0,
|
|
8283
|
-
const tomlPath = (0,
|
|
8284
|
-
(0,
|
|
8375
|
+
(0, import_node_fs9.chmodSync)(composePath, 384);
|
|
8376
|
+
const tomlPath = (0, import_node_path11.join)(dataDir, "stalwart.toml");
|
|
8377
|
+
(0, import_node_fs9.writeFileSync)(tomlPath, `# Stalwart Mail Server \u2014 AgenticMail Configuration
|
|
8285
8378
|
|
|
8286
8379
|
[server]
|
|
8287
8380
|
hostname = "localhost"
|
|
@@ -8331,14 +8424,14 @@ enable = true
|
|
|
8331
8424
|
user = "admin"
|
|
8332
8425
|
secret = "${password}"
|
|
8333
8426
|
`);
|
|
8334
|
-
(0,
|
|
8427
|
+
(0, import_node_fs9.chmodSync)(tomlPath, 384);
|
|
8335
8428
|
}
|
|
8336
8429
|
/**
|
|
8337
8430
|
* Check if config has already been initialized.
|
|
8338
8431
|
*/
|
|
8339
8432
|
isInitialized() {
|
|
8340
|
-
const configPath = (0,
|
|
8341
|
-
return (0,
|
|
8433
|
+
const configPath = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".agenticmail", "config.json");
|
|
8434
|
+
return (0, import_node_fs9.existsSync)(configPath);
|
|
8342
8435
|
}
|
|
8343
8436
|
};
|
|
8344
8437
|
|
|
@@ -8376,10 +8469,10 @@ function threadIdFor(input) {
|
|
|
8376
8469
|
}
|
|
8377
8470
|
|
|
8378
8471
|
// src/threading/thread-cache.ts
|
|
8379
|
-
var
|
|
8380
|
-
var
|
|
8381
|
-
var
|
|
8382
|
-
var CACHE_DIR_DEFAULT = (0,
|
|
8472
|
+
var import_node_fs10 = require("fs");
|
|
8473
|
+
var import_node_os10 = require("os");
|
|
8474
|
+
var import_node_path12 = require("path");
|
|
8475
|
+
var CACHE_DIR_DEFAULT = (0, import_node_path12.join)((0, import_node_os10.homedir)(), ".agenticmail", "thread-cache");
|
|
8383
8476
|
var DEFAULT_K_MESSAGES = 10;
|
|
8384
8477
|
var DEFAULT_LRU_CAP = 5e3;
|
|
8385
8478
|
var PREVIEW_MAX_CHARS = 240;
|
|
@@ -8392,22 +8485,22 @@ var ThreadCache = class {
|
|
|
8392
8485
|
this.k = opts.k ?? DEFAULT_K_MESSAGES;
|
|
8393
8486
|
this.lruCap = opts.lruCap ?? DEFAULT_LRU_CAP;
|
|
8394
8487
|
try {
|
|
8395
|
-
(0,
|
|
8488
|
+
(0, import_node_fs10.mkdirSync)(this.dir, { recursive: true });
|
|
8396
8489
|
} catch {
|
|
8397
8490
|
}
|
|
8398
8491
|
}
|
|
8399
8492
|
pathFor(threadId) {
|
|
8400
|
-
return (0,
|
|
8493
|
+
return (0, import_node_path12.join)(this.dir, `${threadId}.json`);
|
|
8401
8494
|
}
|
|
8402
8495
|
read(threadId) {
|
|
8403
8496
|
const p = this.pathFor(threadId);
|
|
8404
|
-
if (!(0,
|
|
8497
|
+
if (!(0, import_node_fs10.existsSync)(p)) return null;
|
|
8405
8498
|
try {
|
|
8406
|
-
const raw = (0,
|
|
8499
|
+
const raw = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
8407
8500
|
return JSON.parse(raw);
|
|
8408
8501
|
} catch {
|
|
8409
8502
|
try {
|
|
8410
|
-
(0,
|
|
8503
|
+
(0, import_node_fs10.rmSync)(p, { force: true });
|
|
8411
8504
|
} catch {
|
|
8412
8505
|
}
|
|
8413
8506
|
return null;
|
|
@@ -8448,7 +8541,7 @@ var ThreadCache = class {
|
|
|
8448
8541
|
/** Permanently remove a thread's cache (called on [FINAL] / [DONE] / [CLOSED] / [WRAP]). */
|
|
8449
8542
|
delete(threadId) {
|
|
8450
8543
|
try {
|
|
8451
|
-
(0,
|
|
8544
|
+
(0, import_node_fs10.rmSync)(this.pathFor(threadId), { force: true });
|
|
8452
8545
|
} catch {
|
|
8453
8546
|
}
|
|
8454
8547
|
}
|
|
@@ -8468,8 +8561,8 @@ var ThreadCache = class {
|
|
|
8468
8561
|
writeAtomic(threadId, entry) {
|
|
8469
8562
|
const p = this.pathFor(threadId);
|
|
8470
8563
|
const tmp = `${p}.tmp`;
|
|
8471
|
-
(0,
|
|
8472
|
-
(0,
|
|
8564
|
+
(0, import_node_fs10.writeFileSync)(tmp, JSON.stringify(entry), "utf-8");
|
|
8565
|
+
(0, import_node_fs10.renameSync)(tmp, p);
|
|
8473
8566
|
}
|
|
8474
8567
|
/**
|
|
8475
8568
|
* Best-effort LRU eviction. Runs at most every 256 writes (we
|
|
@@ -8481,15 +8574,15 @@ var ThreadCache = class {
|
|
|
8481
8574
|
if (Math.random() > 1 / 256) return;
|
|
8482
8575
|
let files;
|
|
8483
8576
|
try {
|
|
8484
|
-
files = (0,
|
|
8577
|
+
files = (0, import_node_fs10.readdirSync)(this.dir).filter((f) => f.endsWith(".json"));
|
|
8485
8578
|
} catch {
|
|
8486
8579
|
return;
|
|
8487
8580
|
}
|
|
8488
8581
|
if (files.length <= this.lruCap) return;
|
|
8489
8582
|
const stats = files.map((f) => {
|
|
8490
|
-
const p = (0,
|
|
8583
|
+
const p = (0, import_node_path12.join)(this.dir, f);
|
|
8491
8584
|
try {
|
|
8492
|
-
return { p, mtime: (0,
|
|
8585
|
+
return { p, mtime: (0, import_node_fs10.statSync)(p).mtimeMs };
|
|
8493
8586
|
} catch {
|
|
8494
8587
|
return { p, mtime: 0 };
|
|
8495
8588
|
}
|
|
@@ -8498,7 +8591,7 @@ var ThreadCache = class {
|
|
|
8498
8591
|
const dropCount = Math.max(1, Math.floor(this.lruCap * 0.1));
|
|
8499
8592
|
for (let i = 0; i < dropCount; i++) {
|
|
8500
8593
|
try {
|
|
8501
|
-
(0,
|
|
8594
|
+
(0, import_node_fs10.rmSync)(stats[i].p, { force: true });
|
|
8502
8595
|
} catch {
|
|
8503
8596
|
}
|
|
8504
8597
|
}
|
|
@@ -8517,30 +8610,30 @@ function dedupAndCap(messages, k) {
|
|
|
8517
8610
|
}
|
|
8518
8611
|
|
|
8519
8612
|
// src/threading/agent-memory.ts
|
|
8520
|
-
var
|
|
8521
|
-
var
|
|
8522
|
-
var
|
|
8523
|
-
var MEMORY_DIR_DEFAULT = (0,
|
|
8613
|
+
var import_node_fs11 = require("fs");
|
|
8614
|
+
var import_node_os11 = require("os");
|
|
8615
|
+
var import_node_path13 = require("path");
|
|
8616
|
+
var MEMORY_DIR_DEFAULT = (0, import_node_path13.join)((0, import_node_os11.homedir)(), ".agenticmail", "agent-memory");
|
|
8524
8617
|
var AgentMemoryStore = class {
|
|
8525
8618
|
dir;
|
|
8526
8619
|
constructor(opts = {}) {
|
|
8527
8620
|
this.dir = opts.memoryDir ?? MEMORY_DIR_DEFAULT;
|
|
8528
8621
|
try {
|
|
8529
|
-
(0,
|
|
8622
|
+
(0, import_node_fs11.mkdirSync)(this.dir, { recursive: true });
|
|
8530
8623
|
} catch {
|
|
8531
8624
|
}
|
|
8532
8625
|
}
|
|
8533
8626
|
dirFor(agentId) {
|
|
8534
|
-
return (0,
|
|
8627
|
+
return (0, import_node_path13.join)(this.dir, sanitizeId(agentId));
|
|
8535
8628
|
}
|
|
8536
8629
|
pathFor(agentId, threadId) {
|
|
8537
|
-
return (0,
|
|
8630
|
+
return (0, import_node_path13.join)(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
|
|
8538
8631
|
}
|
|
8539
8632
|
read(agentId, threadId) {
|
|
8540
8633
|
const p = this.pathFor(agentId, threadId);
|
|
8541
|
-
if (!(0,
|
|
8634
|
+
if (!(0, import_node_fs11.existsSync)(p)) return null;
|
|
8542
8635
|
try {
|
|
8543
|
-
const raw = (0,
|
|
8636
|
+
const raw = (0, import_node_fs11.readFileSync)(p, "utf-8");
|
|
8544
8637
|
const parsed = parse(raw);
|
|
8545
8638
|
return { ...parsed, raw };
|
|
8546
8639
|
} catch {
|
|
@@ -8550,18 +8643,18 @@ var AgentMemoryStore = class {
|
|
|
8550
8643
|
write(agentId, threadId, fields) {
|
|
8551
8644
|
const agentDir = this.dirFor(agentId);
|
|
8552
8645
|
try {
|
|
8553
|
-
(0,
|
|
8646
|
+
(0, import_node_fs11.mkdirSync)(agentDir, { recursive: true });
|
|
8554
8647
|
} catch {
|
|
8555
8648
|
}
|
|
8556
8649
|
const body = render({ ...fields, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
8557
8650
|
const p = this.pathFor(agentId, threadId);
|
|
8558
8651
|
const tmp = `${p}.tmp`;
|
|
8559
|
-
(0,
|
|
8560
|
-
(0,
|
|
8652
|
+
(0, import_node_fs11.writeFileSync)(tmp, body, "utf-8");
|
|
8653
|
+
(0, import_node_fs11.renameSync)(tmp, p);
|
|
8561
8654
|
}
|
|
8562
8655
|
delete(agentId, threadId) {
|
|
8563
8656
|
try {
|
|
8564
|
-
(0,
|
|
8657
|
+
(0, import_node_fs11.rmSync)(this.pathFor(agentId, threadId), { force: true });
|
|
8565
8658
|
} catch {
|
|
8566
8659
|
}
|
|
8567
8660
|
}
|
|
@@ -8665,6 +8758,7 @@ function parse(raw) {
|
|
|
8665
8758
|
flushTelemetry,
|
|
8666
8759
|
forgetHostSession,
|
|
8667
8760
|
getDatabase,
|
|
8761
|
+
getOperatorEmail,
|
|
8668
8762
|
hostSessionStoragePath,
|
|
8669
8763
|
isInternalEmail,
|
|
8670
8764
|
isSessionFresh,
|
|
@@ -8673,6 +8767,7 @@ function parse(raw) {
|
|
|
8673
8767
|
normalizeAddress,
|
|
8674
8768
|
normalizePhoneNumber,
|
|
8675
8769
|
normalizeSubject,
|
|
8770
|
+
operatorPrefsStoragePath,
|
|
8676
8771
|
parseEmail,
|
|
8677
8772
|
parseGoogleVoiceSms,
|
|
8678
8773
|
recordToolCall,
|
|
@@ -8685,6 +8780,7 @@ function parse(raw) {
|
|
|
8685
8780
|
saveHostSession,
|
|
8686
8781
|
scanOutboundEmail,
|
|
8687
8782
|
scoreEmail,
|
|
8783
|
+
setOperatorEmail,
|
|
8688
8784
|
setTelemetryVersion,
|
|
8689
8785
|
startRelayBridge,
|
|
8690
8786
|
threadIdFor,
|