@agenticmail/core 0.9.5 → 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 +375 -205
- package/dist/index.d.cts +192 -1
- package/dist/index.d.ts +192 -1
- package/dist/index.js +356 -195
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -716,6 +716,7 @@ __export(index_exports, {
|
|
|
716
716
|
CloudflareClient: () => CloudflareClient,
|
|
717
717
|
DEFAULT_AGENT_NAME: () => DEFAULT_AGENT_NAME,
|
|
718
718
|
DEFAULT_AGENT_ROLE: () => DEFAULT_AGENT_ROLE,
|
|
719
|
+
DEFAULT_SESSION_MAX_AGE_MS: () => DEFAULT_SESSION_MAX_AGE_MS,
|
|
719
720
|
DNSConfigurator: () => DNSConfigurator,
|
|
720
721
|
DependencyChecker: () => DependencyChecker,
|
|
721
722
|
DependencyInstaller: () => DependencyInstaller,
|
|
@@ -752,12 +753,18 @@ __export(index_exports, {
|
|
|
752
753
|
ensureDataDir: () => ensureDataDir,
|
|
753
754
|
extractVerificationCode: () => extractVerificationCode,
|
|
754
755
|
flushTelemetry: () => flushTelemetry,
|
|
756
|
+
forgetHostSession: () => forgetHostSession,
|
|
755
757
|
getDatabase: () => getDatabase,
|
|
758
|
+
getOperatorEmail: () => getOperatorEmail,
|
|
759
|
+
hostSessionStoragePath: () => hostSessionStoragePath,
|
|
756
760
|
isInternalEmail: () => isInternalEmail,
|
|
761
|
+
isSessionFresh: () => isSessionFresh,
|
|
757
762
|
isValidPhoneNumber: () => isValidPhoneNumber,
|
|
763
|
+
loadHostSession: () => loadHostSession,
|
|
758
764
|
normalizeAddress: () => normalizeAddress,
|
|
759
765
|
normalizePhoneNumber: () => normalizePhoneNumber,
|
|
760
766
|
normalizeSubject: () => normalizeSubject,
|
|
767
|
+
operatorPrefsStoragePath: () => operatorPrefsStoragePath,
|
|
761
768
|
parseEmail: () => parseEmail,
|
|
762
769
|
parseGoogleVoiceSms: () => parseGoogleVoiceSms,
|
|
763
770
|
recordToolCall: () => recordToolCall,
|
|
@@ -767,8 +774,10 @@ __export(index_exports, {
|
|
|
767
774
|
safeJoin: () => safeJoin,
|
|
768
775
|
sanitizeEmail: () => sanitizeEmail,
|
|
769
776
|
saveConfig: () => saveConfig,
|
|
777
|
+
saveHostSession: () => saveHostSession,
|
|
770
778
|
scanOutboundEmail: () => scanOutboundEmail,
|
|
771
779
|
scoreEmail: () => scoreEmail,
|
|
780
|
+
setOperatorEmail: () => setOperatorEmail,
|
|
772
781
|
setTelemetryVersion: () => setTelemetryVersion,
|
|
773
782
|
startRelayBridge: () => startRelayBridge,
|
|
774
783
|
threadIdFor: () => threadIdFor,
|
|
@@ -1159,8 +1168,8 @@ var MailReceiver = class {
|
|
|
1159
1168
|
}));
|
|
1160
1169
|
}
|
|
1161
1170
|
/** Create a new IMAP folder */
|
|
1162
|
-
async createFolder(
|
|
1163
|
-
await this.client.mailboxCreate(
|
|
1171
|
+
async createFolder(path2) {
|
|
1172
|
+
await this.client.mailboxCreate(path2);
|
|
1164
1173
|
}
|
|
1165
1174
|
/** Batch mark multiple messages as seen */
|
|
1166
1175
|
async batchMarkSeen(uids, mailbox = "INBOX") {
|
|
@@ -1700,8 +1709,8 @@ var StalwartAdmin = class {
|
|
|
1700
1709
|
}
|
|
1701
1710
|
baseUrl;
|
|
1702
1711
|
authHeader;
|
|
1703
|
-
async request(method,
|
|
1704
|
-
const url = `${this.baseUrl}/api${
|
|
1712
|
+
async request(method, path2, body) {
|
|
1713
|
+
const url = `${this.baseUrl}/api${path2}`;
|
|
1705
1714
|
const response = await fetch(url, {
|
|
1706
1715
|
method,
|
|
1707
1716
|
headers: {
|
|
@@ -1862,14 +1871,14 @@ var StalwartAdmin = class {
|
|
|
1862
1871
|
if (!isValidDomain(domain)) {
|
|
1863
1872
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
1864
1873
|
}
|
|
1865
|
-
const { readFileSync:
|
|
1866
|
-
const { homedir:
|
|
1867
|
-
const { join:
|
|
1868
|
-
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");
|
|
1869
1878
|
try {
|
|
1870
|
-
let config =
|
|
1879
|
+
let config = readFileSync9(configPath, "utf-8");
|
|
1871
1880
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
1872
|
-
|
|
1881
|
+
writeFileSync10(configPath, config);
|
|
1873
1882
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
1874
1883
|
} catch (err) {
|
|
1875
1884
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -1878,15 +1887,15 @@ var StalwartAdmin = class {
|
|
|
1878
1887
|
// --- DKIM ---
|
|
1879
1888
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
1880
1889
|
get configPath() {
|
|
1881
|
-
const { homedir:
|
|
1882
|
-
const { join:
|
|
1883
|
-
return
|
|
1890
|
+
const { homedir: homedir13 } = require("os");
|
|
1891
|
+
const { join: join15 } = require("path");
|
|
1892
|
+
return join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
1884
1893
|
}
|
|
1885
1894
|
/** Path to host-side DKIM key directory */
|
|
1886
1895
|
get dkimDir() {
|
|
1887
|
-
const { homedir:
|
|
1888
|
-
const { join:
|
|
1889
|
-
return
|
|
1896
|
+
const { homedir: homedir13 } = require("os");
|
|
1897
|
+
const { join: join15 } = require("path");
|
|
1898
|
+
return join15(homedir13(), ".agenticmail");
|
|
1890
1899
|
}
|
|
1891
1900
|
/**
|
|
1892
1901
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -1987,12 +1996,12 @@ var StalwartAdmin = class {
|
|
|
1987
1996
|
* This bypasses the need for a PTR record on the sending IP.
|
|
1988
1997
|
*/
|
|
1989
1998
|
async configureOutboundRelay(config) {
|
|
1990
|
-
const { readFileSync:
|
|
1991
|
-
const { homedir:
|
|
1992
|
-
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");
|
|
1993
2002
|
const routeName = config.routeName ?? "gmail";
|
|
1994
|
-
const tomlPath =
|
|
1995
|
-
let toml =
|
|
2003
|
+
const tomlPath = join15(homedir13(), ".agenticmail", "stalwart.toml");
|
|
2004
|
+
let toml = readFileSync9(tomlPath, "utf-8");
|
|
1996
2005
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
1997
2006
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
1998
2007
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -2012,7 +2021,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
2012
2021
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
2013
2022
|
{ else = "'${safeRouteName}'" } ]
|
|
2014
2023
|
`;
|
|
2015
|
-
|
|
2024
|
+
writeFileSync10(tomlPath, toml, "utf-8");
|
|
2016
2025
|
await this.restartContainer();
|
|
2017
2026
|
}
|
|
2018
2027
|
};
|
|
@@ -2395,11 +2404,11 @@ var AgentDeletionService = class {
|
|
|
2395
2404
|
};
|
|
2396
2405
|
}
|
|
2397
2406
|
saveToFile(report) {
|
|
2398
|
-
const
|
|
2399
|
-
(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 });
|
|
2400
2409
|
const timestamp = report.deletedAt.replace(/[:.]/g, "-");
|
|
2401
2410
|
const filename = `${report.agent.name}_${timestamp}.json`;
|
|
2402
|
-
const filePath = (0, import_node_path2.join)(
|
|
2411
|
+
const filePath = (0, import_node_path2.join)(dir2, filename);
|
|
2403
2412
|
(0, import_node_fs2.writeFileSync)(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
2404
2413
|
return filePath;
|
|
2405
2414
|
}
|
|
@@ -4690,8 +4699,8 @@ var CloudflareClient = class {
|
|
|
4690
4699
|
return resp.result;
|
|
4691
4700
|
}
|
|
4692
4701
|
// --- Internal ---
|
|
4693
|
-
async request(method,
|
|
4694
|
-
const url = `${CF_API_BASE}${
|
|
4702
|
+
async request(method, path2, body) {
|
|
4703
|
+
const url = `${CF_API_BASE}${path2}`;
|
|
4695
4704
|
const response = await fetch(url, {
|
|
4696
4705
|
method,
|
|
4697
4706
|
headers: {
|
|
@@ -5013,9 +5022,9 @@ var TunnelManager = class {
|
|
|
5013
5022
|
throw new Error(`Failed to download cloudflared: ${response.statusText}`);
|
|
5014
5023
|
}
|
|
5015
5024
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
5016
|
-
const { writeFile:
|
|
5025
|
+
const { writeFile: writeFile4, rename: rename2 } = await import("fs/promises");
|
|
5017
5026
|
const tmpPath = this.binPath + ".tmp";
|
|
5018
|
-
await
|
|
5027
|
+
await writeFile4(tmpPath, buffer);
|
|
5019
5028
|
await (0, import_promises.chmod)(tmpPath, 493);
|
|
5020
5029
|
await rename2(tmpPath, this.binPath);
|
|
5021
5030
|
return this.binPath;
|
|
@@ -5308,6 +5317,33 @@ var SmsManager = class {
|
|
|
5308
5317
|
meta.sms = config;
|
|
5309
5318
|
this.db.prepare("UPDATE agents SET metadata = ?, updated_at = datetime('now') WHERE id = ?").run(JSON.stringify(meta), agentId);
|
|
5310
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
|
+
}
|
|
5311
5347
|
/** Remove SMS config from agent metadata */
|
|
5312
5348
|
removeSmsConfig(agentId) {
|
|
5313
5349
|
const row = this.db.prepare("SELECT metadata FROM agents WHERE id = ?").get(agentId);
|
|
@@ -5923,12 +5959,12 @@ var GatewayManager = class {
|
|
|
5923
5959
|
zone = await this.cfClient.createZone(domain);
|
|
5924
5960
|
}
|
|
5925
5961
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
5926
|
-
const { homedir:
|
|
5927
|
-
const backupDir = (0, import_node_path4.join)(
|
|
5962
|
+
const { homedir: homedir13 } = await import("os");
|
|
5963
|
+
const backupDir = (0, import_node_path4.join)(homedir13(), ".agenticmail");
|
|
5928
5964
|
const backupPath = (0, import_node_path4.join)(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
5929
|
-
const { writeFileSync:
|
|
5930
|
-
|
|
5931
|
-
|
|
5965
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync11 } = await import("fs");
|
|
5966
|
+
mkdirSync11(backupDir, { recursive: true });
|
|
5967
|
+
writeFileSync10(backupPath, JSON.stringify({
|
|
5932
5968
|
domain,
|
|
5933
5969
|
zoneId: zone.id,
|
|
5934
5970
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6689,8 +6725,8 @@ function isDisabled() {
|
|
|
6689
6725
|
function getInstallId() {
|
|
6690
6726
|
if (installId) return installId;
|
|
6691
6727
|
try {
|
|
6692
|
-
const
|
|
6693
|
-
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");
|
|
6694
6730
|
if ((0, import_fs.existsSync)(idFile)) {
|
|
6695
6731
|
const id = (0, import_fs.readFileSync)(idFile, "utf8").trim();
|
|
6696
6732
|
if (id && id.length > 10) {
|
|
@@ -6699,7 +6735,7 @@ function getInstallId() {
|
|
|
6699
6735
|
}
|
|
6700
6736
|
}
|
|
6701
6737
|
installId = (0, import_crypto.randomUUID)();
|
|
6702
|
-
if (!(0, import_fs.existsSync)(
|
|
6738
|
+
if (!(0, import_fs.existsSync)(dir2)) (0, import_fs.mkdirSync)(dir2, { recursive: true });
|
|
6703
6739
|
(0, import_fs.writeFileSync)(idFile, installId, "utf8");
|
|
6704
6740
|
return installId;
|
|
6705
6741
|
} catch {
|
|
@@ -6870,6 +6906,131 @@ function redactObject(input, _depth = 0) {
|
|
|
6870
6906
|
return out;
|
|
6871
6907
|
}
|
|
6872
6908
|
|
|
6909
|
+
// src/operator-prefs.ts
|
|
6910
|
+
var import_node_fs4 = require("fs");
|
|
6911
|
+
var import_node_os4 = require("os");
|
|
6912
|
+
var import_node_path6 = require("path");
|
|
6913
|
+
function dir() {
|
|
6914
|
+
return (0, import_node_path6.join)((0, import_node_os4.homedir)(), ".agenticmail");
|
|
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
|
+
}
|
|
6971
|
+
function storagePath() {
|
|
6972
|
+
return (0, import_node_path7.join)(storageDir(), "host-sessions.json");
|
|
6973
|
+
}
|
|
6974
|
+
var DEFAULT_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
6975
|
+
function readFile2() {
|
|
6976
|
+
const p = storagePath();
|
|
6977
|
+
if (!(0, import_node_fs5.existsSync)(p)) return { version: 1, sessions: {} };
|
|
6978
|
+
try {
|
|
6979
|
+
const raw = (0, import_node_fs5.readFileSync)(p, "utf-8");
|
|
6980
|
+
if (!raw.trim()) return { version: 1, sessions: {} };
|
|
6981
|
+
const parsed = JSON.parse(raw);
|
|
6982
|
+
return {
|
|
6983
|
+
version: 1,
|
|
6984
|
+
sessions: parsed.sessions && typeof parsed.sessions === "object" ? parsed.sessions : {}
|
|
6985
|
+
};
|
|
6986
|
+
} catch {
|
|
6987
|
+
return { version: 1, sessions: {} };
|
|
6988
|
+
}
|
|
6989
|
+
}
|
|
6990
|
+
function writeFile2(shape) {
|
|
6991
|
+
const dir2 = storageDir();
|
|
6992
|
+
const p = storagePath();
|
|
6993
|
+
if (!(0, import_node_fs5.existsSync)(dir2)) (0, import_node_fs5.mkdirSync)(dir2, { recursive: true });
|
|
6994
|
+
const tmp = `${p}.agenticmail-tmp-${process.pid}`;
|
|
6995
|
+
(0, import_node_fs5.writeFileSync)(tmp, JSON.stringify(shape, null, 2), "utf-8");
|
|
6996
|
+
(0, import_node_fs5.renameSync)(tmp, p);
|
|
6997
|
+
}
|
|
6998
|
+
function saveHostSession(host, session) {
|
|
6999
|
+
if (!session.sessionId) return;
|
|
7000
|
+
try {
|
|
7001
|
+
const shape = readFile2();
|
|
7002
|
+
shape.sessions[host] = {
|
|
7003
|
+
...session,
|
|
7004
|
+
lastSeenMs: Date.now()
|
|
7005
|
+
};
|
|
7006
|
+
writeFile2(shape);
|
|
7007
|
+
} catch {
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
function loadHostSession(host, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
7011
|
+
const shape = readFile2();
|
|
7012
|
+
const record = shape.sessions[host];
|
|
7013
|
+
if (!record) return null;
|
|
7014
|
+
if (!isSessionFresh(record, maxAgeMs)) return null;
|
|
7015
|
+
return record;
|
|
7016
|
+
}
|
|
7017
|
+
function isSessionFresh(session, maxAgeMs = DEFAULT_SESSION_MAX_AGE_MS) {
|
|
7018
|
+
if (!session || !Number.isFinite(session.lastSeenMs)) return false;
|
|
7019
|
+
return Date.now() - session.lastSeenMs <= maxAgeMs;
|
|
7020
|
+
}
|
|
7021
|
+
function forgetHostSession(host) {
|
|
7022
|
+
try {
|
|
7023
|
+
const shape = readFile2();
|
|
7024
|
+
if (!shape.sessions[host]) return;
|
|
7025
|
+
delete shape.sessions[host];
|
|
7026
|
+
writeFile2(shape);
|
|
7027
|
+
} catch {
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
function hostSessionStoragePath() {
|
|
7031
|
+
return storagePath();
|
|
7032
|
+
}
|
|
7033
|
+
|
|
6873
7034
|
// src/util/safe-url.ts
|
|
6874
7035
|
var UnsafeApiUrlError = class extends Error {
|
|
6875
7036
|
constructor(raw, reason) {
|
|
@@ -6912,21 +7073,21 @@ function validateApiUrl(raw) {
|
|
|
6912
7073
|
return parsed.origin;
|
|
6913
7074
|
}
|
|
6914
7075
|
function buildApiUrl(baseOrigin, pathAndQuery) {
|
|
6915
|
-
const
|
|
6916
|
-
return new URL(
|
|
7076
|
+
const path2 = pathAndQuery.startsWith("/") ? pathAndQuery : `/${pathAndQuery}`;
|
|
7077
|
+
return new URL(path2, baseOrigin + "/").toString();
|
|
6917
7078
|
}
|
|
6918
7079
|
|
|
6919
7080
|
// src/setup/index.ts
|
|
6920
7081
|
var import_node_crypto3 = require("crypto");
|
|
6921
|
-
var
|
|
6922
|
-
var
|
|
6923
|
-
var
|
|
7082
|
+
var import_node_fs9 = require("fs");
|
|
7083
|
+
var import_node_path11 = require("path");
|
|
7084
|
+
var import_node_os9 = require("os");
|
|
6924
7085
|
|
|
6925
7086
|
// src/setup/deps.ts
|
|
6926
7087
|
var import_node_child_process2 = require("child_process");
|
|
6927
|
-
var
|
|
6928
|
-
var
|
|
6929
|
-
var
|
|
7088
|
+
var import_node_fs6 = require("fs");
|
|
7089
|
+
var import_node_path8 = require("path");
|
|
7090
|
+
var import_node_os6 = require("os");
|
|
6930
7091
|
var DependencyChecker = class {
|
|
6931
7092
|
async checkAll() {
|
|
6932
7093
|
return Promise.all([
|
|
@@ -6976,8 +7137,8 @@ var DependencyChecker = class {
|
|
|
6976
7137
|
}
|
|
6977
7138
|
}
|
|
6978
7139
|
async checkCloudflared() {
|
|
6979
|
-
const binPath = (0,
|
|
6980
|
-
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)) {
|
|
6981
7142
|
let version;
|
|
6982
7143
|
try {
|
|
6983
7144
|
const output = (0, import_node_child_process2.execFileSync)(binPath, ["--version"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -6999,10 +7160,10 @@ var DependencyChecker = class {
|
|
|
6999
7160
|
|
|
7000
7161
|
// src/setup/installer.ts
|
|
7001
7162
|
var import_node_child_process3 = require("child_process");
|
|
7002
|
-
var
|
|
7163
|
+
var import_node_fs7 = require("fs");
|
|
7003
7164
|
var import_promises2 = require("fs/promises");
|
|
7004
|
-
var
|
|
7005
|
-
var
|
|
7165
|
+
var import_node_path9 = require("path");
|
|
7166
|
+
var import_node_os7 = require("os");
|
|
7006
7167
|
function runShellWithRollingOutput(cmd, opts = {}) {
|
|
7007
7168
|
const maxLines = opts.maxLines ?? 20;
|
|
7008
7169
|
const timeout = opts.timeout ?? 3e5;
|
|
@@ -7112,7 +7273,7 @@ var DependencyInstaller = class {
|
|
|
7112
7273
|
*/
|
|
7113
7274
|
async installDocker() {
|
|
7114
7275
|
if (this.isDockerReady()) return;
|
|
7115
|
-
const os = (0,
|
|
7276
|
+
const os = (0, import_node_os7.platform)();
|
|
7116
7277
|
if (os === "darwin") {
|
|
7117
7278
|
await this.installDockerMac();
|
|
7118
7279
|
} else if (os === "linux") {
|
|
@@ -7178,15 +7339,15 @@ var DependencyInstaller = class {
|
|
|
7178
7339
|
try {
|
|
7179
7340
|
const composeBin = (0, import_node_child_process3.execFileSync)("which", ["docker-compose"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7180
7341
|
if (!composeBin) return;
|
|
7181
|
-
const pluginDir = (0,
|
|
7182
|
-
const pluginPath = (0,
|
|
7183
|
-
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;
|
|
7184
7345
|
try {
|
|
7185
|
-
(0,
|
|
7346
|
+
(0, import_node_fs7.mkdirSync)(pluginDir, { recursive: true });
|
|
7186
7347
|
} catch {
|
|
7187
7348
|
}
|
|
7188
7349
|
try {
|
|
7189
|
-
(0,
|
|
7350
|
+
(0, import_node_fs7.symlinkSync)(composeBin, pluginPath);
|
|
7190
7351
|
} catch {
|
|
7191
7352
|
}
|
|
7192
7353
|
} catch {
|
|
@@ -7245,9 +7406,9 @@ var DependencyInstaller = class {
|
|
|
7245
7406
|
return;
|
|
7246
7407
|
}
|
|
7247
7408
|
this.onProgress("__progress__:5:Installing Docker Engine...");
|
|
7248
|
-
const tmpDir = (0,
|
|
7409
|
+
const tmpDir = (0, import_node_path9.join)((0, import_node_os7.homedir)(), ".agenticmail", "tmp");
|
|
7249
7410
|
await (0, import_promises2.mkdir)(tmpDir, { recursive: true });
|
|
7250
|
-
const scriptPath = (0,
|
|
7411
|
+
const scriptPath = (0, import_node_path9.join)(tmpDir, "install-docker.sh");
|
|
7251
7412
|
const dlResult = await runShellWithRollingOutput(
|
|
7252
7413
|
`curl -fsSL https://get.docker.com -o "${scriptPath}" && sudo sh "${scriptPath}"`,
|
|
7253
7414
|
{ timeout: 3e5 }
|
|
@@ -7315,8 +7476,8 @@ var DependencyInstaller = class {
|
|
|
7315
7476
|
}
|
|
7316
7477
|
try {
|
|
7317
7478
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7318
|
-
const dockerExe = (0,
|
|
7319
|
-
if ((0,
|
|
7479
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7480
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7320
7481
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7321
7482
|
}
|
|
7322
7483
|
} catch {
|
|
@@ -7366,8 +7527,8 @@ var DependencyInstaller = class {
|
|
|
7366
7527
|
this.onProgress("__progress__:70:Docker Desktop installed. Starting...");
|
|
7367
7528
|
try {
|
|
7368
7529
|
const programFiles = process.env["ProgramFiles"] || "C:\\Program Files";
|
|
7369
|
-
const dockerExe = (0,
|
|
7370
|
-
if ((0,
|
|
7530
|
+
const dockerExe = (0, import_node_path9.join)(programFiles, "Docker", "Docker", "Docker Desktop.exe");
|
|
7531
|
+
if ((0, import_node_fs7.existsSync)(dockerExe)) {
|
|
7371
7532
|
(0, import_node_child_process3.execSync)(`start "" "${dockerExe}"`, { timeout: 1e4, stdio: "ignore", shell: "cmd.exe" });
|
|
7372
7533
|
}
|
|
7373
7534
|
} catch {
|
|
@@ -7404,12 +7565,12 @@ var DependencyInstaller = class {
|
|
|
7404
7565
|
* Start the Stalwart mail server Docker container.
|
|
7405
7566
|
*/
|
|
7406
7567
|
async startStalwart(composePath) {
|
|
7407
|
-
if (!(0,
|
|
7568
|
+
if (!(0, import_node_fs7.existsSync)(composePath)) {
|
|
7408
7569
|
throw new Error(`docker-compose.yml not found at: ${composePath}`);
|
|
7409
7570
|
}
|
|
7410
7571
|
if (!this.isDockerReady()) {
|
|
7411
7572
|
this.onProgress("Starting Docker...");
|
|
7412
|
-
const os = (0,
|
|
7573
|
+
const os = (0, import_node_os7.platform)();
|
|
7413
7574
|
if (os === "darwin") {
|
|
7414
7575
|
await this.startColima();
|
|
7415
7576
|
} else if (os === "win32") {
|
|
@@ -7427,7 +7588,7 @@ var DependencyInstaller = class {
|
|
|
7427
7588
|
}
|
|
7428
7589
|
}
|
|
7429
7590
|
this.onProgress("__progress__:10:Pulling mail server image...");
|
|
7430
|
-
if ((0,
|
|
7591
|
+
if ((0, import_node_os7.platform)() === "darwin") this.linkComposePlugin();
|
|
7431
7592
|
let composeResult = await runSilent("docker", ["compose", "-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
7432
7593
|
if (composeResult.exitCode !== 0 && hasCommand("docker-compose")) {
|
|
7433
7594
|
composeResult = await runSilent("docker-compose", ["-f", composePath, "up", "-d"], { timeout: 12e4 });
|
|
@@ -7462,22 +7623,22 @@ var DependencyInstaller = class {
|
|
|
7462
7623
|
* Returns the path to the installed binary.
|
|
7463
7624
|
*/
|
|
7464
7625
|
async installCloudflared() {
|
|
7465
|
-
const os = (0,
|
|
7466
|
-
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");
|
|
7467
7628
|
const binName = os === "win32" ? "cloudflared.exe" : "cloudflared";
|
|
7468
|
-
const binPath = (0,
|
|
7469
|
-
if ((0,
|
|
7629
|
+
const binPath = (0, import_node_path9.join)(binDir, binName);
|
|
7630
|
+
if ((0, import_node_fs7.existsSync)(binPath)) {
|
|
7470
7631
|
return binPath;
|
|
7471
7632
|
}
|
|
7472
7633
|
try {
|
|
7473
7634
|
const whichCmd = os === "win32" ? "where" : "which";
|
|
7474
7635
|
const sysPath = (0, import_node_child_process3.execFileSync)(whichCmd, ["cloudflared"], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n")[0];
|
|
7475
|
-
if (sysPath && (0,
|
|
7636
|
+
if (sysPath && (0, import_node_fs7.existsSync)(sysPath)) return sysPath;
|
|
7476
7637
|
} catch {
|
|
7477
7638
|
}
|
|
7478
7639
|
this.onProgress("Downloading cloudflared...");
|
|
7479
7640
|
await (0, import_promises2.mkdir)(binDir, { recursive: true });
|
|
7480
|
-
const cpu = (0,
|
|
7641
|
+
const cpu = (0, import_node_os7.arch)();
|
|
7481
7642
|
const archName = cpu === "arm64" ? "arm64" : "amd64";
|
|
7482
7643
|
let downloadUrl;
|
|
7483
7644
|
if (os === "darwin") {
|
|
@@ -7495,7 +7656,7 @@ var DependencyInstaller = class {
|
|
|
7495
7656
|
}
|
|
7496
7657
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7497
7658
|
if (os === "darwin") {
|
|
7498
|
-
const tgzPath = (0,
|
|
7659
|
+
const tgzPath = (0, import_node_path9.join)(binDir, "cloudflared.tgz");
|
|
7499
7660
|
await (0, import_promises2.writeFile)(tgzPath, buffer);
|
|
7500
7661
|
try {
|
|
7501
7662
|
(0, import_node_child_process3.execFileSync)("tar", ["-xzf", tgzPath, "-C", binDir, "cloudflared"], { timeout: 15e3, stdio: "ignore" });
|
|
@@ -7512,7 +7673,7 @@ var DependencyInstaller = class {
|
|
|
7512
7673
|
if (os !== "win32") await (0, import_promises2.chmod)(tmpPath, 493);
|
|
7513
7674
|
await (0, import_promises2.rename)(tmpPath, binPath);
|
|
7514
7675
|
}
|
|
7515
|
-
if (!(0,
|
|
7676
|
+
if (!(0, import_node_fs7.existsSync)(binPath)) {
|
|
7516
7677
|
throw new Error("cloudflared download succeeded but binary not found after extraction");
|
|
7517
7678
|
}
|
|
7518
7679
|
this.onProgress("cloudflared installed");
|
|
@@ -7530,23 +7691,23 @@ var DependencyInstaller = class {
|
|
|
7530
7691
|
|
|
7531
7692
|
// src/setup/service.ts
|
|
7532
7693
|
var import_node_child_process4 = require("child_process");
|
|
7533
|
-
var
|
|
7534
|
-
var
|
|
7535
|
-
var
|
|
7694
|
+
var import_node_fs8 = require("fs");
|
|
7695
|
+
var import_node_path10 = require("path");
|
|
7696
|
+
var import_node_os8 = require("os");
|
|
7536
7697
|
var import_node_module2 = require("module");
|
|
7537
7698
|
var import_meta2 = {};
|
|
7538
7699
|
var PLIST_LABEL = "com.agenticmail.server";
|
|
7539
7700
|
var SYSTEMD_UNIT = "agenticmail.service";
|
|
7540
7701
|
var ServiceManager = class {
|
|
7541
|
-
os = (0,
|
|
7702
|
+
os = (0, import_node_os8.platform)();
|
|
7542
7703
|
/**
|
|
7543
7704
|
* Get the path to the service file.
|
|
7544
7705
|
*/
|
|
7545
7706
|
getServicePath() {
|
|
7546
7707
|
if (this.os === "darwin") {
|
|
7547
|
-
return (0,
|
|
7708
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
7548
7709
|
} else {
|
|
7549
|
-
return (0,
|
|
7710
|
+
return (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
7550
7711
|
}
|
|
7551
7712
|
}
|
|
7552
7713
|
/**
|
|
@@ -7580,40 +7741,40 @@ var ServiceManager = class {
|
|
|
7580
7741
|
try {
|
|
7581
7742
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7582
7743
|
const resolved = req.resolve("@agenticmail/api");
|
|
7583
|
-
if ((0,
|
|
7744
|
+
if ((0, import_node_fs8.existsSync)(resolved)) return resolved;
|
|
7584
7745
|
} catch {
|
|
7585
7746
|
}
|
|
7586
7747
|
const parentPackages = [
|
|
7587
|
-
(0,
|
|
7748
|
+
(0, import_node_path10.join)("@agenticmail", "cli"),
|
|
7588
7749
|
// current scoped package
|
|
7589
7750
|
"agenticmail"
|
|
7590
7751
|
// legacy unscoped package
|
|
7591
7752
|
];
|
|
7592
7753
|
const baseDirs = [
|
|
7593
7754
|
// user-local install
|
|
7594
|
-
(0,
|
|
7755
|
+
(0, import_node_path10.join)((0, import_node_os8.homedir)(), "node_modules")
|
|
7595
7756
|
];
|
|
7596
7757
|
try {
|
|
7597
7758
|
const prefix = (0, import_node_child_process4.execSync)("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7598
|
-
baseDirs.push((0,
|
|
7599
|
-
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"));
|
|
7600
7761
|
} catch {
|
|
7601
7762
|
}
|
|
7602
7763
|
baseDirs.push("/opt/homebrew/lib/node_modules");
|
|
7603
7764
|
baseDirs.push("/usr/local/lib/node_modules");
|
|
7604
7765
|
for (const base of baseDirs) {
|
|
7605
|
-
const sibling = (0,
|
|
7606
|
-
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;
|
|
7607
7768
|
for (const parent of parentPackages) {
|
|
7608
|
-
const nested = (0,
|
|
7609
|
-
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;
|
|
7610
7771
|
}
|
|
7611
7772
|
}
|
|
7612
|
-
const dataDir = (0,
|
|
7613
|
-
const entryCache = (0,
|
|
7614
|
-
if ((0,
|
|
7615
|
-
const cached = (0,
|
|
7616
|
-
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;
|
|
7617
7778
|
}
|
|
7618
7779
|
throw new Error("Could not find @agenticmail/api entry point. Run `agenticmail start` first to populate the cache.");
|
|
7619
7780
|
}
|
|
@@ -7621,9 +7782,9 @@ var ServiceManager = class {
|
|
|
7621
7782
|
* Cache the API entry path so the service can find it later.
|
|
7622
7783
|
*/
|
|
7623
7784
|
cacheApiEntryPath(entryPath) {
|
|
7624
|
-
const dataDir = (0,
|
|
7625
|
-
if (!(0,
|
|
7626
|
-
(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);
|
|
7627
7788
|
}
|
|
7628
7789
|
/**
|
|
7629
7790
|
* Get the current package version.
|
|
@@ -7636,36 +7797,36 @@ var ServiceManager = class {
|
|
|
7636
7797
|
try {
|
|
7637
7798
|
const req = (0, import_node_module2.createRequire)(import_meta2.url);
|
|
7638
7799
|
const pkgJson = req.resolve("@agenticmail/cli/package.json");
|
|
7639
|
-
if ((0,
|
|
7640
|
-
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"));
|
|
7641
7802
|
if (pkg.version) return pkg.version;
|
|
7642
7803
|
}
|
|
7643
7804
|
} catch {
|
|
7644
7805
|
}
|
|
7645
7806
|
try {
|
|
7646
7807
|
const apiEntry = this.getApiEntryPath();
|
|
7647
|
-
const apiPkg = (0,
|
|
7648
|
-
if ((0,
|
|
7649
|
-
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"));
|
|
7650
7811
|
if (pkg.version) return pkg.version;
|
|
7651
7812
|
}
|
|
7652
7813
|
} catch {
|
|
7653
7814
|
}
|
|
7654
7815
|
const candidates = [
|
|
7655
|
-
(0,
|
|
7656
|
-
(0,
|
|
7657
|
-
(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")
|
|
7658
7819
|
];
|
|
7659
7820
|
try {
|
|
7660
7821
|
const prefix = (0, import_node_child_process4.execSync)("npm prefix -g", { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
7661
|
-
candidates.push((0,
|
|
7662
|
-
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"));
|
|
7663
7824
|
} catch {
|
|
7664
7825
|
}
|
|
7665
7826
|
for (const p of candidates) {
|
|
7666
7827
|
try {
|
|
7667
|
-
if ((0,
|
|
7668
|
-
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"));
|
|
7669
7830
|
if (pkg.version) return pkg.version;
|
|
7670
7831
|
}
|
|
7671
7832
|
} catch {
|
|
@@ -7678,9 +7839,9 @@ var ServiceManager = class {
|
|
|
7678
7839
|
* This ensures AgenticMail doesn't fail on boot when Docker is still loading.
|
|
7679
7840
|
*/
|
|
7680
7841
|
generateStartScript(nodePath, apiEntry) {
|
|
7681
|
-
const scriptPath = (0,
|
|
7682
|
-
const scriptDir = (0,
|
|
7683
|
-
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 });
|
|
7684
7845
|
const script = [
|
|
7685
7846
|
"#!/bin/bash",
|
|
7686
7847
|
"# AgenticMail auto-start script",
|
|
@@ -7731,7 +7892,7 @@ var ServiceManager = class {
|
|
|
7731
7892
|
`log "Starting API server: ${nodePath} ${apiEntry}"`,
|
|
7732
7893
|
`exec "${nodePath}" "${apiEntry}"`
|
|
7733
7894
|
].join("\n") + "\n";
|
|
7734
|
-
(0,
|
|
7895
|
+
(0, import_node_fs8.writeFileSync)(scriptPath, script, { mode: 493 });
|
|
7735
7896
|
return scriptPath;
|
|
7736
7897
|
}
|
|
7737
7898
|
/**
|
|
@@ -7744,9 +7905,9 @@ var ServiceManager = class {
|
|
|
7744
7905
|
* - Service version tracking in env vars
|
|
7745
7906
|
*/
|
|
7746
7907
|
generatePlist(nodePath, apiEntry, configPath) {
|
|
7747
|
-
const config = JSON.parse((0,
|
|
7748
|
-
const logDir = (0,
|
|
7749
|
-
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 });
|
|
7750
7911
|
const version = this.getVersion();
|
|
7751
7912
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7752
7913
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -7767,9 +7928,9 @@ var ServiceManager = class {
|
|
|
7767
7928
|
<key>EnvironmentVariables</key>
|
|
7768
7929
|
<dict>
|
|
7769
7930
|
<key>HOME</key>
|
|
7770
|
-
<string>${(0,
|
|
7931
|
+
<string>${(0, import_node_os8.homedir)()}</string>
|
|
7771
7932
|
<key>AGENTICMAIL_DATA_DIR</key>
|
|
7772
|
-
<string>${config.dataDir || (0,
|
|
7933
|
+
<string>${config.dataDir || (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail")}</string>
|
|
7773
7934
|
<key>PATH</key>
|
|
7774
7935
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
7775
7936
|
<key>AGENTICMAIL_SERVICE_VERSION</key>
|
|
@@ -7822,8 +7983,8 @@ var ServiceManager = class {
|
|
|
7822
7983
|
* - Proper dependency ordering
|
|
7823
7984
|
*/
|
|
7824
7985
|
generateSystemdUnit(nodePath, apiEntry, configPath) {
|
|
7825
|
-
const config = JSON.parse((0,
|
|
7826
|
-
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");
|
|
7827
7988
|
const version = this.getVersion();
|
|
7828
7989
|
const startScript = this.generateStartScript(nodePath, apiEntry);
|
|
7829
7990
|
return `[Unit]
|
|
@@ -7840,7 +8001,7 @@ Restart=always
|
|
|
7840
8001
|
RestartSec=15
|
|
7841
8002
|
TimeoutStartSec=660
|
|
7842
8003
|
LimitNOFILE=8192
|
|
7843
|
-
Environment=HOME=${(0,
|
|
8004
|
+
Environment=HOME=${(0, import_node_os8.homedir)()}
|
|
7844
8005
|
Environment=AGENTICMAIL_DATA_DIR=${dataDir}
|
|
7845
8006
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
|
|
7846
8007
|
Environment=AGENTICMAIL_SERVICE_VERSION=${version}
|
|
@@ -7853,8 +8014,8 @@ WantedBy=default.target
|
|
|
7853
8014
|
* Install the auto-start service.
|
|
7854
8015
|
*/
|
|
7855
8016
|
install() {
|
|
7856
|
-
const configPath = (0,
|
|
7857
|
-
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)) {
|
|
7858
8019
|
return { installed: false, message: "Config not found. Run agenticmail setup first." };
|
|
7859
8020
|
}
|
|
7860
8021
|
const nodePath = this.getNodePath();
|
|
@@ -7866,17 +8027,17 @@ WantedBy=default.target
|
|
|
7866
8027
|
}
|
|
7867
8028
|
const servicePath = this.getServicePath();
|
|
7868
8029
|
if (this.os === "darwin") {
|
|
7869
|
-
const
|
|
7870
|
-
if (!(0,
|
|
7871
|
-
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)) {
|
|
7872
8033
|
try {
|
|
7873
8034
|
(0, import_node_child_process4.execFileSync)("launchctl", ["unload", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7874
8035
|
} catch {
|
|
7875
8036
|
}
|
|
7876
8037
|
}
|
|
7877
8038
|
const plist = this.generatePlist(nodePath, apiEntry, configPath);
|
|
7878
|
-
(0,
|
|
7879
|
-
(0,
|
|
8039
|
+
(0, import_node_fs8.writeFileSync)(servicePath, plist);
|
|
8040
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7880
8041
|
try {
|
|
7881
8042
|
(0, import_node_child_process4.execFileSync)("launchctl", ["load", servicePath], { timeout: 1e4, stdio: "ignore" });
|
|
7882
8043
|
} catch (err) {
|
|
@@ -7884,11 +8045,11 @@ WantedBy=default.target
|
|
|
7884
8045
|
}
|
|
7885
8046
|
return { installed: true, message: `Service installed at ${servicePath}` };
|
|
7886
8047
|
} else if (this.os === "linux") {
|
|
7887
|
-
const
|
|
7888
|
-
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 });
|
|
7889
8050
|
const unit = this.generateSystemdUnit(nodePath, apiEntry, configPath);
|
|
7890
|
-
(0,
|
|
7891
|
-
(0,
|
|
8051
|
+
(0, import_node_fs8.writeFileSync)(servicePath, unit);
|
|
8052
|
+
(0, import_node_fs8.chmodSync)(servicePath, 384);
|
|
7892
8053
|
try {
|
|
7893
8054
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "daemon-reload"], { timeout: 1e4, stdio: "ignore" });
|
|
7894
8055
|
(0, import_node_child_process4.execFileSync)("systemctl", ["--user", "enable", SYSTEMD_UNIT], { timeout: 1e4, stdio: "ignore" });
|
|
@@ -7910,7 +8071,7 @@ WantedBy=default.target
|
|
|
7910
8071
|
*/
|
|
7911
8072
|
uninstall() {
|
|
7912
8073
|
const servicePath = this.getServicePath();
|
|
7913
|
-
if (!(0,
|
|
8074
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) {
|
|
7914
8075
|
return { removed: false, message: "Service is not installed." };
|
|
7915
8076
|
}
|
|
7916
8077
|
if (this.os === "darwin") {
|
|
@@ -7919,7 +8080,7 @@ WantedBy=default.target
|
|
|
7919
8080
|
} catch {
|
|
7920
8081
|
}
|
|
7921
8082
|
try {
|
|
7922
|
-
(0,
|
|
8083
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
7923
8084
|
} catch {
|
|
7924
8085
|
}
|
|
7925
8086
|
return { removed: true, message: "Service removed." };
|
|
@@ -7930,7 +8091,7 @@ WantedBy=default.target
|
|
|
7930
8091
|
} catch {
|
|
7931
8092
|
}
|
|
7932
8093
|
try {
|
|
7933
|
-
(0,
|
|
8094
|
+
(0, import_node_fs8.unlinkSync)(servicePath);
|
|
7934
8095
|
} catch {
|
|
7935
8096
|
}
|
|
7936
8097
|
try {
|
|
@@ -7948,7 +8109,7 @@ WantedBy=default.target
|
|
|
7948
8109
|
status() {
|
|
7949
8110
|
const servicePath = this.getServicePath();
|
|
7950
8111
|
const plat = this.os === "darwin" ? "launchd" : this.os === "linux" ? "systemd" : "unsupported";
|
|
7951
|
-
const installed = (0,
|
|
8112
|
+
const installed = (0, import_node_fs8.existsSync)(servicePath);
|
|
7952
8113
|
let running = false;
|
|
7953
8114
|
if (installed) {
|
|
7954
8115
|
if (this.os === "darwin") {
|
|
@@ -8003,34 +8164,34 @@ WantedBy=default.target
|
|
|
8003
8164
|
needsRepair() {
|
|
8004
8165
|
if (this.os !== "darwin" && this.os !== "linux") return null;
|
|
8005
8166
|
const servicePath = this.getServicePath();
|
|
8006
|
-
if (!(0,
|
|
8167
|
+
if (!(0, import_node_fs8.existsSync)(servicePath)) return null;
|
|
8007
8168
|
let serviceContent = "";
|
|
8008
8169
|
try {
|
|
8009
|
-
serviceContent = (0,
|
|
8170
|
+
serviceContent = (0, import_node_fs8.readFileSync)(servicePath, "utf-8");
|
|
8010
8171
|
} catch {
|
|
8011
8172
|
return { reason: "Service file unreadable" };
|
|
8012
8173
|
}
|
|
8013
|
-
const startScript = (0,
|
|
8174
|
+
const startScript = (0, import_node_path10.join)((0, import_node_os8.homedir)(), ".agenticmail", "bin", "start-server.sh");
|
|
8014
8175
|
if (serviceContent.includes(startScript)) {
|
|
8015
|
-
if (!(0,
|
|
8176
|
+
if (!(0, import_node_fs8.existsSync)(startScript)) {
|
|
8016
8177
|
return { reason: "start-server.sh is missing" };
|
|
8017
8178
|
}
|
|
8018
8179
|
let scriptContent = "";
|
|
8019
8180
|
try {
|
|
8020
|
-
scriptContent = (0,
|
|
8181
|
+
scriptContent = (0, import_node_fs8.readFileSync)(startScript, "utf-8");
|
|
8021
8182
|
} catch {
|
|
8022
8183
|
return { reason: "start-server.sh unreadable" };
|
|
8023
8184
|
}
|
|
8024
8185
|
const apiPathMatch = scriptContent.match(/(\/[^"\s]+@agenticmail\/api\/dist\/index\.js)/);
|
|
8025
8186
|
if (apiPathMatch) {
|
|
8026
8187
|
const referenced = apiPathMatch[1];
|
|
8027
|
-
if (!(0,
|
|
8188
|
+
if (!(0, import_node_fs8.existsSync)(referenced)) {
|
|
8028
8189
|
return { reason: `start-server.sh references missing path: ${referenced}` };
|
|
8029
8190
|
}
|
|
8030
8191
|
}
|
|
8031
8192
|
if (/node_modules\/agenticmail\/(?!.*@agenticmail\/cli)/.test(scriptContent)) {
|
|
8032
8193
|
const stale = /(\S*node_modules\/agenticmail\/\S*)/.exec(scriptContent)?.[1];
|
|
8033
|
-
if (stale && !(0,
|
|
8194
|
+
if (stale && !(0, import_node_fs8.existsSync)(stale)) {
|
|
8034
8195
|
return { reason: `start-server.sh references legacy unscoped path: ${stale}` };
|
|
8035
8196
|
}
|
|
8036
8197
|
}
|
|
@@ -8043,11 +8204,11 @@ WantedBy=default.target
|
|
|
8043
8204
|
return { reason: `Service version drift (current CLI is v${currentVersion})` };
|
|
8044
8205
|
}
|
|
8045
8206
|
}
|
|
8046
|
-
const entryCache = (0,
|
|
8047
|
-
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)) {
|
|
8048
8209
|
try {
|
|
8049
|
-
const cached = (0,
|
|
8050
|
-
if (cached && !(0,
|
|
8210
|
+
const cached = (0, import_node_fs8.readFileSync)(entryCache, "utf-8").trim();
|
|
8211
|
+
if (cached && !(0, import_node_fs8.existsSync)(cached)) {
|
|
8051
8212
|
return { reason: `Cached API entry path no longer exists: ${cached}` };
|
|
8052
8213
|
}
|
|
8053
8214
|
} catch {
|
|
@@ -8086,8 +8247,8 @@ var SetupManager = class {
|
|
|
8086
8247
|
async ensureStalwart(composePath) {
|
|
8087
8248
|
const status = await this.checker.checkStalwart();
|
|
8088
8249
|
if (status.installed) return;
|
|
8089
|
-
const
|
|
8090
|
-
await this.installer.startStalwart(
|
|
8250
|
+
const path2 = composePath ?? this.getComposePath();
|
|
8251
|
+
await this.installer.startStalwart(path2);
|
|
8091
8252
|
}
|
|
8092
8253
|
async ensureCloudflared() {
|
|
8093
8254
|
return this.installer.installCloudflared();
|
|
@@ -8098,13 +8259,13 @@ var SetupManager = class {
|
|
|
8098
8259
|
* falls back to monorepo location.
|
|
8099
8260
|
*/
|
|
8100
8261
|
getComposePath() {
|
|
8101
|
-
const standalonePath = (0,
|
|
8102
|
-
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;
|
|
8103
8264
|
const cwd = process.cwd();
|
|
8104
|
-
const candidates = [cwd, (0,
|
|
8105
|
-
for (const
|
|
8106
|
-
const p = (0,
|
|
8107
|
-
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;
|
|
8108
8269
|
}
|
|
8109
8270
|
return standalonePath;
|
|
8110
8271
|
}
|
|
@@ -8114,19 +8275,19 @@ var SetupManager = class {
|
|
|
8114
8275
|
* Always regenerates Docker files to keep passwords in sync.
|
|
8115
8276
|
*/
|
|
8116
8277
|
initConfig() {
|
|
8117
|
-
const dataDir = (0,
|
|
8118
|
-
const configPath = (0,
|
|
8119
|
-
const envPath = (0,
|
|
8120
|
-
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)) {
|
|
8121
8282
|
try {
|
|
8122
|
-
const existing = JSON.parse((0,
|
|
8283
|
+
const existing = JSON.parse((0, import_node_fs9.readFileSync)(configPath, "utf-8"));
|
|
8123
8284
|
this.generateDockerFiles(existing);
|
|
8124
8285
|
return { configPath, envPath, config: existing, isNew: false };
|
|
8125
8286
|
} catch {
|
|
8126
8287
|
}
|
|
8127
8288
|
}
|
|
8128
|
-
if (!(0,
|
|
8129
|
-
(0,
|
|
8289
|
+
if (!(0, import_node_fs9.existsSync)(dataDir)) {
|
|
8290
|
+
(0, import_node_fs9.mkdirSync)(dataDir, { recursive: true });
|
|
8130
8291
|
}
|
|
8131
8292
|
const masterKey = `mk_${(0, import_node_crypto3.randomBytes)(24).toString("hex")}`;
|
|
8132
8293
|
const stalwartPassword = (0, import_node_crypto3.randomBytes)(16).toString("hex");
|
|
@@ -8142,8 +8303,8 @@ var SetupManager = class {
|
|
|
8142
8303
|
api: { port: 3829, host: "127.0.0.1" },
|
|
8143
8304
|
dataDir
|
|
8144
8305
|
};
|
|
8145
|
-
(0,
|
|
8146
|
-
(0,
|
|
8306
|
+
(0, import_node_fs9.writeFileSync)(configPath, JSON.stringify(config, null, 2));
|
|
8307
|
+
(0, import_node_fs9.chmodSync)(configPath, 384);
|
|
8147
8308
|
const envContent = `# Auto-generated by agenticmail setup
|
|
8148
8309
|
STALWART_ADMIN_USER=admin
|
|
8149
8310
|
STALWART_ADMIN_PASSWORD=${stalwartPassword}
|
|
@@ -8158,8 +8319,8 @@ SMTP_PORT=587
|
|
|
8158
8319
|
IMAP_HOST=localhost
|
|
8159
8320
|
IMAP_PORT=143
|
|
8160
8321
|
`;
|
|
8161
|
-
(0,
|
|
8162
|
-
(0,
|
|
8322
|
+
(0, import_node_fs9.writeFileSync)(envPath, envContent);
|
|
8323
|
+
(0, import_node_fs9.chmodSync)(envPath, 384);
|
|
8163
8324
|
this.generateDockerFiles(config);
|
|
8164
8325
|
return { configPath, envPath, config, isNew: true };
|
|
8165
8326
|
}
|
|
@@ -8168,13 +8329,13 @@ IMAP_PORT=143
|
|
|
8168
8329
|
* with the correct admin password from config.
|
|
8169
8330
|
*/
|
|
8170
8331
|
generateDockerFiles(config) {
|
|
8171
|
-
const dataDir = config.dataDir || (0,
|
|
8172
|
-
if (!(0,
|
|
8173
|
-
(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 });
|
|
8174
8335
|
}
|
|
8175
8336
|
const password = config.stalwart?.adminPassword || "changeme";
|
|
8176
|
-
const composePath = (0,
|
|
8177
|
-
(0,
|
|
8337
|
+
const composePath = (0, import_node_path11.join)(dataDir, "docker-compose.yml");
|
|
8338
|
+
(0, import_node_fs9.writeFileSync)(composePath, `services:
|
|
8178
8339
|
stalwart:
|
|
8179
8340
|
# Pinned to v0.15.5 \u2014 Stalwart 0.16+ moved its config to JSON
|
|
8180
8341
|
# at /etc/stalwart/config.json (hardcoded into the container
|
|
@@ -8203,9 +8364,9 @@ IMAP_PORT=143
|
|
|
8203
8364
|
volumes:
|
|
8204
8365
|
stalwart-data:
|
|
8205
8366
|
`);
|
|
8206
|
-
(0,
|
|
8207
|
-
const tomlPath = (0,
|
|
8208
|
-
(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
|
|
8209
8370
|
|
|
8210
8371
|
[server]
|
|
8211
8372
|
hostname = "localhost"
|
|
@@ -8255,14 +8416,14 @@ enable = true
|
|
|
8255
8416
|
user = "admin"
|
|
8256
8417
|
secret = "${password}"
|
|
8257
8418
|
`);
|
|
8258
|
-
(0,
|
|
8419
|
+
(0, import_node_fs9.chmodSync)(tomlPath, 384);
|
|
8259
8420
|
}
|
|
8260
8421
|
/**
|
|
8261
8422
|
* Check if config has already been initialized.
|
|
8262
8423
|
*/
|
|
8263
8424
|
isInitialized() {
|
|
8264
|
-
const configPath = (0,
|
|
8265
|
-
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);
|
|
8266
8427
|
}
|
|
8267
8428
|
};
|
|
8268
8429
|
|
|
@@ -8300,10 +8461,10 @@ function threadIdFor(input) {
|
|
|
8300
8461
|
}
|
|
8301
8462
|
|
|
8302
8463
|
// src/threading/thread-cache.ts
|
|
8303
|
-
var
|
|
8304
|
-
var
|
|
8305
|
-
var
|
|
8306
|
-
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");
|
|
8307
8468
|
var DEFAULT_K_MESSAGES = 10;
|
|
8308
8469
|
var DEFAULT_LRU_CAP = 5e3;
|
|
8309
8470
|
var PREVIEW_MAX_CHARS = 240;
|
|
@@ -8316,22 +8477,22 @@ var ThreadCache = class {
|
|
|
8316
8477
|
this.k = opts.k ?? DEFAULT_K_MESSAGES;
|
|
8317
8478
|
this.lruCap = opts.lruCap ?? DEFAULT_LRU_CAP;
|
|
8318
8479
|
try {
|
|
8319
|
-
(0,
|
|
8480
|
+
(0, import_node_fs10.mkdirSync)(this.dir, { recursive: true });
|
|
8320
8481
|
} catch {
|
|
8321
8482
|
}
|
|
8322
8483
|
}
|
|
8323
8484
|
pathFor(threadId) {
|
|
8324
|
-
return (0,
|
|
8485
|
+
return (0, import_node_path12.join)(this.dir, `${threadId}.json`);
|
|
8325
8486
|
}
|
|
8326
8487
|
read(threadId) {
|
|
8327
8488
|
const p = this.pathFor(threadId);
|
|
8328
|
-
if (!(0,
|
|
8489
|
+
if (!(0, import_node_fs10.existsSync)(p)) return null;
|
|
8329
8490
|
try {
|
|
8330
|
-
const raw = (0,
|
|
8491
|
+
const raw = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
8331
8492
|
return JSON.parse(raw);
|
|
8332
8493
|
} catch {
|
|
8333
8494
|
try {
|
|
8334
|
-
(0,
|
|
8495
|
+
(0, import_node_fs10.rmSync)(p, { force: true });
|
|
8335
8496
|
} catch {
|
|
8336
8497
|
}
|
|
8337
8498
|
return null;
|
|
@@ -8372,7 +8533,7 @@ var ThreadCache = class {
|
|
|
8372
8533
|
/** Permanently remove a thread's cache (called on [FINAL] / [DONE] / [CLOSED] / [WRAP]). */
|
|
8373
8534
|
delete(threadId) {
|
|
8374
8535
|
try {
|
|
8375
|
-
(0,
|
|
8536
|
+
(0, import_node_fs10.rmSync)(this.pathFor(threadId), { force: true });
|
|
8376
8537
|
} catch {
|
|
8377
8538
|
}
|
|
8378
8539
|
}
|
|
@@ -8392,8 +8553,8 @@ var ThreadCache = class {
|
|
|
8392
8553
|
writeAtomic(threadId, entry) {
|
|
8393
8554
|
const p = this.pathFor(threadId);
|
|
8394
8555
|
const tmp = `${p}.tmp`;
|
|
8395
|
-
(0,
|
|
8396
|
-
(0,
|
|
8556
|
+
(0, import_node_fs10.writeFileSync)(tmp, JSON.stringify(entry), "utf-8");
|
|
8557
|
+
(0, import_node_fs10.renameSync)(tmp, p);
|
|
8397
8558
|
}
|
|
8398
8559
|
/**
|
|
8399
8560
|
* Best-effort LRU eviction. Runs at most every 256 writes (we
|
|
@@ -8405,15 +8566,15 @@ var ThreadCache = class {
|
|
|
8405
8566
|
if (Math.random() > 1 / 256) return;
|
|
8406
8567
|
let files;
|
|
8407
8568
|
try {
|
|
8408
|
-
files = (0,
|
|
8569
|
+
files = (0, import_node_fs10.readdirSync)(this.dir).filter((f) => f.endsWith(".json"));
|
|
8409
8570
|
} catch {
|
|
8410
8571
|
return;
|
|
8411
8572
|
}
|
|
8412
8573
|
if (files.length <= this.lruCap) return;
|
|
8413
8574
|
const stats = files.map((f) => {
|
|
8414
|
-
const p = (0,
|
|
8575
|
+
const p = (0, import_node_path12.join)(this.dir, f);
|
|
8415
8576
|
try {
|
|
8416
|
-
return { p, mtime: (0,
|
|
8577
|
+
return { p, mtime: (0, import_node_fs10.statSync)(p).mtimeMs };
|
|
8417
8578
|
} catch {
|
|
8418
8579
|
return { p, mtime: 0 };
|
|
8419
8580
|
}
|
|
@@ -8422,7 +8583,7 @@ var ThreadCache = class {
|
|
|
8422
8583
|
const dropCount = Math.max(1, Math.floor(this.lruCap * 0.1));
|
|
8423
8584
|
for (let i = 0; i < dropCount; i++) {
|
|
8424
8585
|
try {
|
|
8425
|
-
(0,
|
|
8586
|
+
(0, import_node_fs10.rmSync)(stats[i].p, { force: true });
|
|
8426
8587
|
} catch {
|
|
8427
8588
|
}
|
|
8428
8589
|
}
|
|
@@ -8441,30 +8602,30 @@ function dedupAndCap(messages, k) {
|
|
|
8441
8602
|
}
|
|
8442
8603
|
|
|
8443
8604
|
// src/threading/agent-memory.ts
|
|
8444
|
-
var
|
|
8445
|
-
var
|
|
8446
|
-
var
|
|
8447
|
-
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");
|
|
8448
8609
|
var AgentMemoryStore = class {
|
|
8449
8610
|
dir;
|
|
8450
8611
|
constructor(opts = {}) {
|
|
8451
8612
|
this.dir = opts.memoryDir ?? MEMORY_DIR_DEFAULT;
|
|
8452
8613
|
try {
|
|
8453
|
-
(0,
|
|
8614
|
+
(0, import_node_fs11.mkdirSync)(this.dir, { recursive: true });
|
|
8454
8615
|
} catch {
|
|
8455
8616
|
}
|
|
8456
8617
|
}
|
|
8457
8618
|
dirFor(agentId) {
|
|
8458
|
-
return (0,
|
|
8619
|
+
return (0, import_node_path13.join)(this.dir, sanitizeId(agentId));
|
|
8459
8620
|
}
|
|
8460
8621
|
pathFor(agentId, threadId) {
|
|
8461
|
-
return (0,
|
|
8622
|
+
return (0, import_node_path13.join)(this.dirFor(agentId), `${sanitizeId(threadId)}.md`);
|
|
8462
8623
|
}
|
|
8463
8624
|
read(agentId, threadId) {
|
|
8464
8625
|
const p = this.pathFor(agentId, threadId);
|
|
8465
|
-
if (!(0,
|
|
8626
|
+
if (!(0, import_node_fs11.existsSync)(p)) return null;
|
|
8466
8627
|
try {
|
|
8467
|
-
const raw = (0,
|
|
8628
|
+
const raw = (0, import_node_fs11.readFileSync)(p, "utf-8");
|
|
8468
8629
|
const parsed = parse(raw);
|
|
8469
8630
|
return { ...parsed, raw };
|
|
8470
8631
|
} catch {
|
|
@@ -8474,18 +8635,18 @@ var AgentMemoryStore = class {
|
|
|
8474
8635
|
write(agentId, threadId, fields) {
|
|
8475
8636
|
const agentDir = this.dirFor(agentId);
|
|
8476
8637
|
try {
|
|
8477
|
-
(0,
|
|
8638
|
+
(0, import_node_fs11.mkdirSync)(agentDir, { recursive: true });
|
|
8478
8639
|
} catch {
|
|
8479
8640
|
}
|
|
8480
8641
|
const body = render({ ...fields, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
8481
8642
|
const p = this.pathFor(agentId, threadId);
|
|
8482
8643
|
const tmp = `${p}.tmp`;
|
|
8483
|
-
(0,
|
|
8484
|
-
(0,
|
|
8644
|
+
(0, import_node_fs11.writeFileSync)(tmp, body, "utf-8");
|
|
8645
|
+
(0, import_node_fs11.renameSync)(tmp, p);
|
|
8485
8646
|
}
|
|
8486
8647
|
delete(agentId, threadId) {
|
|
8487
8648
|
try {
|
|
8488
|
-
(0,
|
|
8649
|
+
(0, import_node_fs11.rmSync)(this.pathFor(agentId, threadId), { force: true });
|
|
8489
8650
|
} catch {
|
|
8490
8651
|
}
|
|
8491
8652
|
}
|
|
@@ -8550,6 +8711,7 @@ function parse(raw) {
|
|
|
8550
8711
|
CloudflareClient,
|
|
8551
8712
|
DEFAULT_AGENT_NAME,
|
|
8552
8713
|
DEFAULT_AGENT_ROLE,
|
|
8714
|
+
DEFAULT_SESSION_MAX_AGE_MS,
|
|
8553
8715
|
DNSConfigurator,
|
|
8554
8716
|
DependencyChecker,
|
|
8555
8717
|
DependencyInstaller,
|
|
@@ -8586,12 +8748,18 @@ function parse(raw) {
|
|
|
8586
8748
|
ensureDataDir,
|
|
8587
8749
|
extractVerificationCode,
|
|
8588
8750
|
flushTelemetry,
|
|
8751
|
+
forgetHostSession,
|
|
8589
8752
|
getDatabase,
|
|
8753
|
+
getOperatorEmail,
|
|
8754
|
+
hostSessionStoragePath,
|
|
8590
8755
|
isInternalEmail,
|
|
8756
|
+
isSessionFresh,
|
|
8591
8757
|
isValidPhoneNumber,
|
|
8758
|
+
loadHostSession,
|
|
8592
8759
|
normalizeAddress,
|
|
8593
8760
|
normalizePhoneNumber,
|
|
8594
8761
|
normalizeSubject,
|
|
8762
|
+
operatorPrefsStoragePath,
|
|
8595
8763
|
parseEmail,
|
|
8596
8764
|
parseGoogleVoiceSms,
|
|
8597
8765
|
recordToolCall,
|
|
@@ -8601,8 +8769,10 @@ function parse(raw) {
|
|
|
8601
8769
|
safeJoin,
|
|
8602
8770
|
sanitizeEmail,
|
|
8603
8771
|
saveConfig,
|
|
8772
|
+
saveHostSession,
|
|
8604
8773
|
scanOutboundEmail,
|
|
8605
8774
|
scoreEmail,
|
|
8775
|
+
setOperatorEmail,
|
|
8606
8776
|
setTelemetryVersion,
|
|
8607
8777
|
startRelayBridge,
|
|
8608
8778
|
threadIdFor,
|