@agenticmail/api 0.7.4 → 0.7.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.js CHANGED
@@ -6,6 +6,9 @@ import { networkInterfaces } from "os";
6
6
  import express from "express";
7
7
  import cors from "cors";
8
8
  import rateLimit from "express-rate-limit";
9
+ import { fileURLToPath as fileURLToPath2 } from "url";
10
+ import { dirname as dirname2, join as join2 } from "path";
11
+ import { existsSync } from "fs";
9
12
  import {
10
13
  resolveConfig,
11
14
  getDatabase,
@@ -35,7 +38,7 @@ function safeEqual(a, b) {
35
38
  const hb = createHash("sha256").update(b).digest();
36
39
  return timingSafeEqual(ha, hb);
37
40
  }
38
- function createAuthMiddleware(masterKey, accountManager, db) {
41
+ function createAuthMiddleware(masterKey, accountManager2, db) {
39
42
  return async (req, res, next) => {
40
43
  const authHeader = req.headers.authorization;
41
44
  if (!authHeader?.startsWith("Bearer ")) {
@@ -53,7 +56,7 @@ function createAuthMiddleware(masterKey, accountManager, db) {
53
56
  return;
54
57
  }
55
58
  try {
56
- const agent = await accountManager.getByApiKey(token);
59
+ const agent = await accountManager2.getByApiKey(token);
57
60
  if (agent) {
58
61
  req.agent = agent;
59
62
  if (db) {
@@ -324,9 +327,9 @@ function sanitizeAgent(agent) {
324
327
  }
325
328
  return agent;
326
329
  }
327
- function createAccountRoutes(accountManager, db, config) {
330
+ function createAccountRoutes(accountManager2, db, config) {
328
331
  const router = Router3();
329
- const deletionService = new AgentDeletionService(db, accountManager, config);
332
+ const deletionService = new AgentDeletionService(db, accountManager2, config);
330
333
  router.post("/accounts", requireMaster, async (req, res, next) => {
331
334
  if (!req.body || typeof req.body !== "object") {
332
335
  res.status(400).json({ error: "Request body must be JSON" });
@@ -357,7 +360,7 @@ function createAccountRoutes(accountManager, db, config) {
357
360
  const cleanMeta = metadata ? Object.fromEntries(
358
361
  Object.entries(metadata).filter(([k]) => !k.startsWith("_"))
359
362
  ) : void 0;
360
- const agent = await accountManager.create({ name: accountName, domain, password: password || void 0, metadata: cleanMeta, role });
363
+ const agent = await accountManager2.create({ name: accountName, domain, password: password || void 0, metadata: cleanMeta, role });
361
364
  try {
362
365
  db.prepare("UPDATE agents SET last_activity_at = datetime('now') WHERE id = ?").run(agent.id);
363
366
  } catch {
@@ -389,7 +392,7 @@ function createAccountRoutes(accountManager, db, config) {
389
392
  });
390
393
  router.get("/accounts", requireMaster, async (_req, res, next) => {
391
394
  try {
392
- const agents = await accountManager.list();
395
+ const agents = await accountManager2.list();
393
396
  res.json({ agents: agents.map(sanitizeAgent) });
394
397
  } catch (err) {
395
398
  next(err);
@@ -397,7 +400,7 @@ function createAccountRoutes(accountManager, db, config) {
397
400
  });
398
401
  router.get("/accounts/directory", requireAuth, async (_req, res, next) => {
399
402
  try {
400
- const agents = await accountManager.list();
403
+ const agents = await accountManager2.list();
401
404
  const directory = agents.map((a) => ({ name: a.name, email: a.email, role: a.role }));
402
405
  res.json({ agents: directory });
403
406
  } catch (err) {
@@ -406,7 +409,7 @@ function createAccountRoutes(accountManager, db, config) {
406
409
  });
407
410
  router.get("/accounts/directory/:name", requireAuth, async (req, res, next) => {
408
411
  try {
409
- const agent = await accountManager.getByName(req.params.name);
412
+ const agent = await accountManager2.getByName(req.params.name);
410
413
  if (!agent) {
411
414
  res.status(404).json({ error: "Agent not found" });
412
415
  return;
@@ -471,7 +474,7 @@ function createAccountRoutes(accountManager, db, config) {
471
474
  const deleted = [];
472
475
  for (const row of rows) {
473
476
  try {
474
- await accountManager.delete(row.id);
477
+ await accountManager2.delete(row.id);
475
478
  deleted.push(row.name);
476
479
  } catch {
477
480
  }
@@ -483,7 +486,7 @@ function createAccountRoutes(accountManager, db, config) {
483
486
  });
484
487
  router.get("/accounts/:id", requireMaster, async (req, res, next) => {
485
488
  try {
486
- const agent = await accountManager.getById(req.params.id);
489
+ const agent = await accountManager2.getById(req.params.id);
487
490
  if (!agent) {
488
491
  res.status(404).json({ error: "Agent not found" });
489
492
  return;
@@ -501,7 +504,7 @@ function createAccountRoutes(accountManager, db, config) {
501
504
  res.status(400).json({ error: "metadata must be an object" });
502
505
  return;
503
506
  }
504
- const updated = await accountManager.updateMetadata(agent.id, metadata);
507
+ const updated = await accountManager2.updateMetadata(agent.id, metadata);
505
508
  if (!updated) {
506
509
  res.status(404).json({ error: "Agent not found" });
507
510
  return;
@@ -526,7 +529,7 @@ function createAccountRoutes(accountManager, db, config) {
526
529
  });
527
530
  router.delete("/accounts/:id", requireMaster, async (req, res, next) => {
528
531
  try {
529
- const allAgents = await accountManager.list();
532
+ const allAgents = await accountManager2.list();
530
533
  if (allAgents.length <= 1) {
531
534
  res.status(400).json({ error: "Cannot delete the last agent. At least one agent must remain." });
532
535
  return;
@@ -544,7 +547,7 @@ function createAccountRoutes(accountManager, db, config) {
544
547
  }
545
548
  res.json(summary);
546
549
  } else {
547
- const deleted = await accountManager.delete(req.params.id);
550
+ const deleted = await accountManager2.delete(req.params.id);
548
551
  if (!deleted) {
549
552
  res.status(404).json({ error: "Agent not found" });
550
553
  return;
@@ -828,6 +831,8 @@ function createFeatureRoutes(db, _accountManager, config, gatewayManager) {
828
831
  return;
829
832
  }
830
833
  const agent = req.agent;
834
+ const wakeList = normalizeWakeList(req.body?.wake);
835
+ const customHeaders = wakeHeaders(wakeList);
831
836
  const mailOpts = {
832
837
  to: draft.to_addr,
833
838
  subject: draft.subject || "(no subject)",
@@ -836,7 +841,8 @@ function createFeatureRoutes(db, _accountManager, config, gatewayManager) {
836
841
  cc: draft.cc || void 0,
837
842
  bcc: draft.bcc || void 0,
838
843
  inReplyTo: draft.in_reply_to || void 0,
839
- references: draft.refs ? JSON.parse(draft.refs) : void 0
844
+ references: draft.refs ? JSON.parse(draft.refs) : void 0,
845
+ ...Object.keys(customHeaders).length > 0 ? { headers: customHeaders } : {}
840
846
  };
841
847
  if (gatewayManager) {
842
848
  const gatewayResult = await gatewayManager.routeOutbound(agent.name, mailOpts);
@@ -857,6 +863,19 @@ function createFeatureRoutes(db, _accountManager, config, gatewayManager) {
857
863
  try {
858
864
  const result = await sender.send(mailOpts);
859
865
  db.prepare("DELETE FROM drafts WHERE id = ?").run(draft.id);
866
+ notifyLocalRecipientsOfNewMail(
867
+ accountManager,
868
+ mailOpts.to,
869
+ mailOpts.cc,
870
+ mailOpts.bcc,
871
+ agent,
872
+ mailOpts.subject,
873
+ result.messageId,
874
+ config,
875
+ wakeList
876
+ ).catch((err) => {
877
+ console.warn(`[drafts] SSE notify failed: ${err.message}`);
878
+ });
860
879
  res.json(result);
861
880
  } finally {
862
881
  sender.close();
@@ -1078,20 +1097,24 @@ function createFeatureRoutes(db, _accountManager, config, gatewayManager) {
1078
1097
  res.status(404).json({ error: "Template not found" });
1079
1098
  return;
1080
1099
  }
1081
- const { to, variables, cc, bcc } = req.body || {};
1100
+ const { to, variables, cc, bcc, wake } = req.body || {};
1082
1101
  if (!to) {
1083
1102
  res.status(400).json({ error: "to is required" });
1084
1103
  return;
1085
1104
  }
1086
1105
  const applyVars = (text, vars2) => text.replace(/\{\{(\w+)\}\}/g, (m, key) => vars2[key] ?? m);
1106
+ const wakeList = normalizeWakeList(wake);
1107
+ const customHeaders = wakeHeaders(wakeList);
1087
1108
  const vars = variables && typeof variables === "object" ? variables : {};
1109
+ const renderedSubject = applyVars(template.subject || "(no subject)", vars);
1088
1110
  const mailOpts = {
1089
1111
  to,
1090
- subject: applyVars(template.subject || "(no subject)", vars),
1112
+ subject: renderedSubject,
1091
1113
  text: template.text_body ? applyVars(template.text_body, vars) : void 0,
1092
1114
  html: template.html_body ? applyVars(template.html_body, vars) : void 0,
1093
1115
  cc: cc || void 0,
1094
- bcc: bcc || void 0
1116
+ bcc: bcc || void 0,
1117
+ ...Object.keys(customHeaders).length > 0 ? { headers: customHeaders } : {}
1095
1118
  };
1096
1119
  const agent = req.agent;
1097
1120
  if (gatewayManager) {
@@ -1111,6 +1134,19 @@ function createFeatureRoutes(db, _accountManager, config, gatewayManager) {
1111
1134
  });
1112
1135
  try {
1113
1136
  const result = await sender.send(mailOpts);
1137
+ notifyLocalRecipientsOfNewMail(
1138
+ accountManager,
1139
+ to,
1140
+ cc,
1141
+ bcc,
1142
+ agent,
1143
+ renderedSubject,
1144
+ result.messageId,
1145
+ config,
1146
+ wakeList
1147
+ ).catch((err) => {
1148
+ console.warn(`[templates] SSE notify failed: ${err.message}`);
1149
+ });
1114
1150
  res.json(result);
1115
1151
  } finally {
1116
1152
  sender.close();
@@ -1181,7 +1217,7 @@ function evaluateRules(db, agentId, email) {
1181
1217
  }
1182
1218
  return null;
1183
1219
  }
1184
- function startScheduledSender(db, accountManager, config, gatewayManager) {
1220
+ function startScheduledSender(db, accountManager2, config, gatewayManager) {
1185
1221
  return setInterval(async () => {
1186
1222
  try {
1187
1223
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -1190,7 +1226,7 @@ function startScheduledSender(db, accountManager, config, gatewayManager) {
1190
1226
  ).all(now);
1191
1227
  for (const row of pending) {
1192
1228
  try {
1193
- const agent = await accountManager.getById(row.agent_id);
1229
+ const agent = await accountManager2.getById(row.agent_id);
1194
1230
  if (!agent) {
1195
1231
  db.prepare("UPDATE scheduled_emails SET status = 'failed', error = ? WHERE id = ?").run("Agent not found", row.id);
1196
1232
  continue;
@@ -1289,7 +1325,7 @@ async function closeAllWatchers() {
1289
1325
  }
1290
1326
  activeWatchers.clear();
1291
1327
  }
1292
- function createEventRoutes(accountManager, config, db) {
1328
+ function createEventRoutes(accountManager2, config, db) {
1293
1329
  const router = Router5();
1294
1330
  router.get("/events", requireAgent, async (req, res, next) => {
1295
1331
  try {
@@ -1677,7 +1713,18 @@ function normalizeMessageId(id) {
1677
1713
  if (!id) return "";
1678
1714
  return id.trim().replace(/^<+|>+$/g, "").toLowerCase();
1679
1715
  }
1680
- async function notifyLocalRecipientsOfNewMail(accountManager, toField, ccField, bccField, fromAgent, subject, messageId, config) {
1716
+ function normalizeWakeList(value) {
1717
+ if (value === void 0 || value === null) return void 0;
1718
+ const strip = (s) => s.trim().replace(/@localhost$/i, "").toLowerCase();
1719
+ if (Array.isArray(value)) return value.map((v) => strip(String(v))).filter(Boolean);
1720
+ if (typeof value === "string") return value.split(",").map(strip).filter(Boolean);
1721
+ return void 0;
1722
+ }
1723
+ function wakeHeaders(wakeList) {
1724
+ if (wakeList === void 0) return {};
1725
+ return { "X-AgenticMail-Wake": wakeList.join(", ") };
1726
+ }
1727
+ async function notifyLocalRecipientsOfNewMail(accountManager2, toField, ccField, bccField, fromAgent, subject, messageId, config, wakeList) {
1681
1728
  const collected = [];
1682
1729
  const push = (v) => {
1683
1730
  if (!v) return;
@@ -1707,7 +1754,7 @@ async function notifyLocalRecipientsOfNewMail(accountManager, toField, ccField,
1707
1754
  if (addr === fromAgent.email.toLowerCase()) continue;
1708
1755
  let recipient = null;
1709
1756
  try {
1710
- recipient = await accountManager.getByName(localPart);
1757
+ recipient = await accountManager2.getByName(localPart);
1711
1758
  } catch {
1712
1759
  }
1713
1760
  if (!recipient || notified.has(recipient.id)) continue;
@@ -1738,7 +1785,12 @@ async function notifyLocalRecipientsOfNewMail(accountManager, toField, ccField,
1738
1785
  internal: true,
1739
1786
  from: { name: fromAgent.name, address: fromAgent.email },
1740
1787
  subject,
1741
- messageId
1788
+ messageId,
1789
+ // Wake gating signal. Present iff the sender opted in. The
1790
+ // dispatcher reads this and spawns a Claude worker only for
1791
+ // recipients whose name is on the list (or for everyone if the
1792
+ // field is absent, preserving the v0.8.x default).
1793
+ ...wakeList !== void 0 ? { wakeAllowlist: wakeList } : {}
1742
1794
  });
1743
1795
  }
1744
1796
  }
@@ -1752,7 +1804,7 @@ function saveSentCopy(authUser, password, config, raw) {
1752
1804
  }
1753
1805
  })();
1754
1806
  }
1755
- function createMailRoutes(accountManager, config, db, gatewayManager) {
1807
+ function createMailRoutes(accountManager2, config, db, gatewayManager) {
1756
1808
  const router = Router6();
1757
1809
  router.post("/mail/send", requireAgent, async (req, res, next) => {
1758
1810
  try {
@@ -1761,7 +1813,7 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
1761
1813
  return;
1762
1814
  }
1763
1815
  const agent = req.agent;
1764
- const { to, subject, text, html, cc, bcc, replyTo, inReplyTo, references, attachments, allowSensitive } = req.body;
1816
+ const { to, subject, text, html, cc, bcc, replyTo, inReplyTo, references, attachments, allowSensitive, wake } = req.body;
1765
1817
  if (!to || !subject) {
1766
1818
  res.status(400).json({ error: "to and subject are required" });
1767
1819
  return;
@@ -1789,7 +1841,21 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
1789
1841
  const pendingId = crypto.randomUUID();
1790
1842
  const ownerName2 = agent.metadata?.ownerName;
1791
1843
  const fromName2 = ownerName2 ? `${agent.name} from ${ownerName2}` : agent.name;
1792
- const mailOptions = { to, subject, text, html, cc, bcc, replyTo, inReplyTo, references, attachments, fromName: fromName2 };
1844
+ const wakeListForPersist = normalizeWakeList(wake);
1845
+ const mailOptions = {
1846
+ to,
1847
+ subject,
1848
+ text,
1849
+ html,
1850
+ cc,
1851
+ bcc,
1852
+ replyTo,
1853
+ inReplyTo,
1854
+ references,
1855
+ attachments,
1856
+ fromName: fromName2,
1857
+ ...wakeListForPersist !== void 0 ? { wakeList: wakeListForPersist } : {}
1858
+ };
1793
1859
  db.prepare(
1794
1860
  `INSERT INTO pending_outbound (id, agent_id, mail_options, warnings, summary) VALUES (?, ?, ?, ?, ?)`
1795
1861
  ).run(pendingId, agent.id, JSON.stringify(mailOptions), JSON.stringify(scanResult.warnings), scanResult.summary);
@@ -1858,7 +1924,22 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
1858
1924
  }
1859
1925
  const ownerName = agent.metadata?.ownerName;
1860
1926
  const fromName = ownerName ? `${agent.name} from ${ownerName}` : agent.name;
1861
- const mailOpts = { to, subject, text, html, cc, bcc, replyTo, inReplyTo, references, attachments, fromName };
1927
+ const wakeList = normalizeWakeList(wake);
1928
+ const customHeaders = wakeHeaders(wakeList);
1929
+ const mailOpts = {
1930
+ to,
1931
+ subject,
1932
+ text,
1933
+ html,
1934
+ cc,
1935
+ bcc,
1936
+ replyTo,
1937
+ inReplyTo,
1938
+ references,
1939
+ attachments,
1940
+ fromName,
1941
+ ...Object.keys(customHeaders).length > 0 ? { headers: customHeaders } : {}
1942
+ };
1862
1943
  const password = getAgentPassword(agent);
1863
1944
  if (gatewayManager) {
1864
1945
  const gatewayResult = await gatewayManager.routeOutbound(agent.name, mailOpts);
@@ -1875,14 +1956,15 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
1875
1956
  const result = await sender.send(mailOpts);
1876
1957
  saveSentCopy(agent.stalwartPrincipal, password, config, result.raw);
1877
1958
  notifyLocalRecipientsOfNewMail(
1878
- accountManager,
1959
+ accountManager2,
1879
1960
  to,
1880
1961
  cc,
1881
1962
  bcc,
1882
1963
  agent,
1883
1964
  subject,
1884
1965
  result.messageId,
1885
- config
1966
+ config,
1967
+ wakeList
1886
1968
  ).catch((err) => {
1887
1969
  console.warn(`[mail] Internal SSE notify failed: ${err.message}`);
1888
1970
  });
@@ -2454,7 +2536,7 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
2454
2536
  res.status(400).json({ error: `Email already ${row.status}` });
2455
2537
  return;
2456
2538
  }
2457
- const agent = await accountManager.getById(row.agent_id);
2539
+ const agent = await accountManager2.getById(row.agent_id);
2458
2540
  if (!agent) {
2459
2541
  res.status(404).json({ error: "Agent account no longer exists" });
2460
2542
  return;
@@ -2469,6 +2551,11 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
2469
2551
  }
2470
2552
  }
2471
2553
  }
2554
+ const persistedWakeList = Array.isArray(mailOpts.wakeList) ? mailOpts.wakeList : void 0;
2555
+ if (persistedWakeList !== void 0) {
2556
+ mailOpts.headers = { ...mailOpts.headers ?? {}, ...wakeHeaders(persistedWakeList) };
2557
+ delete mailOpts.wakeList;
2558
+ }
2472
2559
  const password = getAgentPassword(agent);
2473
2560
  let response;
2474
2561
  if (gatewayManager) {
@@ -2486,14 +2573,15 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
2486
2573
  const result = await sender.send(mailOpts);
2487
2574
  saveSentCopy(agent.stalwartPrincipal, password, config, result.raw);
2488
2575
  notifyLocalRecipientsOfNewMail(
2489
- accountManager,
2576
+ accountManager2,
2490
2577
  mailOpts.to,
2491
2578
  mailOpts.cc,
2492
2579
  mailOpts.bcc,
2493
2580
  agent,
2494
2581
  mailOpts.subject,
2495
2582
  result.messageId,
2496
- config
2583
+ config,
2584
+ persistedWakeList
2497
2585
  ).catch((err) => {
2498
2586
  console.warn(`[mail] Internal SSE notify (approve) failed: ${err.message}`);
2499
2587
  });
@@ -2542,7 +2630,7 @@ var INBOUND_SECRET = process.env.AGENTICMAIL_INBOUND_SECRET || (() => {
2542
2630
  return generated;
2543
2631
  })();
2544
2632
  var DEBUG = () => !!process.env.AGENTICMAIL_DEBUG;
2545
- function createInboundRoutes(accountManager, config, gatewayManager) {
2633
+ function createInboundRoutes(accountManager2, config, gatewayManager) {
2546
2634
  const router = Router7();
2547
2635
  router.post("/mail/inbound", async (req, res, next) => {
2548
2636
  try {
@@ -2558,7 +2646,7 @@ function createInboundRoutes(accountManager, config, gatewayManager) {
2558
2646
  }
2559
2647
  const recipientEmail = typeof to === "string" ? to : to[0];
2560
2648
  const localPart = recipientEmail.split("@")[0];
2561
- const agent = await accountManager.getByName(localPart);
2649
+ const agent = await accountManager2.getByName(localPart);
2562
2650
  if (!agent) {
2563
2651
  console.warn(`[Inbound] No agent found for "${localPart}" (${recipientEmail})`);
2564
2652
  res.status(404).json({ error: `No agent found for ${recipientEmail}` });
@@ -3042,7 +3130,7 @@ import { Router as Router10 } from "express";
3042
3130
  import { v4 as uuidv43 } from "uuid";
3043
3131
  import { MailSender as MailSender4 } from "@agenticmail/core";
3044
3132
  var rpcResolvers = /* @__PURE__ */ new Map();
3045
- function createTaskRoutes(db, accountManager, config) {
3133
+ function createTaskRoutes(db, accountManager2, config) {
3046
3134
  const router = Router10();
3047
3135
  router.post("/tasks/assign", requireAuth, async (req, res, next) => {
3048
3136
  try {
@@ -3051,7 +3139,7 @@ function createTaskRoutes(db, accountManager, config) {
3051
3139
  res.status(400).json({ error: "assignee (agent name) is required" });
3052
3140
  return;
3053
3141
  }
3054
- const target = await accountManager.getByName(assignee);
3142
+ const target = await accountManager2.getByName(assignee);
3055
3143
  if (!target) {
3056
3144
  res.status(404).json({ error: `Agent "${assignee}" not found` });
3057
3145
  return;
@@ -3110,7 +3198,7 @@ Please check your pending tasks.`
3110
3198
  let assigneeId = req.agent.id;
3111
3199
  const assigneeName = req.query.assignee;
3112
3200
  if (assigneeName) {
3113
- const target = await accountManager.getByName(assigneeName);
3201
+ const target = await accountManager2.getByName(assigneeName);
3114
3202
  if (target) assigneeId = target.id;
3115
3203
  }
3116
3204
  const rows = db.prepare(
@@ -3238,7 +3326,7 @@ Please check your pending tasks.`
3238
3326
  res.status(400).json({ error: "target (agent name) and task are required" });
3239
3327
  return;
3240
3328
  }
3241
- const targetAgent = await accountManager.getByName(target);
3329
+ const targetAgent = await accountManager2.getByName(target);
3242
3330
  if (!targetAgent) {
3243
3331
  res.status(404).json({ error: `Agent "${target}" not found` });
3244
3332
  return;
@@ -3372,7 +3460,7 @@ import {
3372
3460
  normalizePhoneNumber,
3373
3461
  isValidPhoneNumber
3374
3462
  } from "@agenticmail/core";
3375
- function createSmsRoutes(db, accountManager, config, gatewayManager) {
3463
+ function createSmsRoutes(db, accountManager2, config, gatewayManager) {
3376
3464
  const router = Router11();
3377
3465
  const smsManager = new SmsManager(db);
3378
3466
  function getAgent(req, res) {
@@ -3760,7 +3848,7 @@ function adaptBetterSqlite(raw) {
3760
3848
  }
3761
3849
  };
3762
3850
  }
3763
- function createStorageRoutes(rawDb, accountManager, config, dialect = "sqlite") {
3851
+ function createStorageRoutes(rawDb, accountManager2, config, dialect = "sqlite") {
3764
3852
  const db = adaptBetterSqlite(rawDb);
3765
3853
  const router = Router12();
3766
3854
  function getAgent(req, res) {
@@ -4730,12 +4818,12 @@ function createApp(configOverrides) {
4730
4818
  adminUser: config.stalwart.adminUser,
4731
4819
  adminPassword: config.stalwart.adminPassword
4732
4820
  });
4733
- const accountManager = new AccountManager(db, stalwart);
4821
+ const accountManager2 = new AccountManager(db, stalwart);
4734
4822
  const domainManager = new DomainManager(db, stalwart);
4735
4823
  const gatewayManager = new GatewayManager2({
4736
4824
  db,
4737
4825
  stalwart,
4738
- accountManager,
4826
+ accountManager: accountManager2,
4739
4827
  localSmtp: {
4740
4828
  host: config.smtp.host,
4741
4829
  port: config.smtp.port,
@@ -4761,36 +4849,49 @@ function createApp(configOverrides) {
4761
4849
  message: { error: "Too many requests, please try again later" }
4762
4850
  })
4763
4851
  );
4852
+ const staticDir = (() => {
4853
+ const here = dirname2(fileURLToPath2(import.meta.url));
4854
+ const candidates = [
4855
+ join2(here, "..", "public"),
4856
+ join2(here, "public")
4857
+ ];
4858
+ for (const c of candidates) if (existsSync(c)) return c;
4859
+ return null;
4860
+ })();
4861
+ if (staticDir) {
4862
+ app2.use("/", express.static(staticDir, { index: "index.html", extensions: ["html"] }));
4863
+ app2.get("/ui", (_req, res) => res.sendFile(join2(staticDir, "index.html")));
4864
+ }
4764
4865
  app2.use("/api/agenticmail", createHealthRoutes(stalwart));
4765
- app2.use("/api/agenticmail", createInboundRoutes(accountManager, config, gatewayManager));
4866
+ app2.use("/api/agenticmail", createInboundRoutes(accountManager2, config, gatewayManager));
4766
4867
  const integrationFactory = readResolvedFactory(integrationRouteFactoryPromise);
4767
4868
  if (integrationFactory) {
4768
4869
  app2.use("/api/agenticmail", integrationFactory());
4769
4870
  }
4770
- app2.use("/api/agenticmail", createAuthMiddleware(config.masterKey, accountManager, db));
4771
- app2.use("/api/agenticmail", createAccountRoutes(accountManager, db, config));
4772
- app2.use("/api/agenticmail", createMailRoutes(accountManager, config, db, gatewayManager));
4773
- app2.use("/api/agenticmail", createEventRoutes(accountManager, config, db));
4871
+ app2.use("/api/agenticmail", createAuthMiddleware(config.masterKey, accountManager2, db));
4872
+ app2.use("/api/agenticmail", createAccountRoutes(accountManager2, db, config));
4873
+ app2.use("/api/agenticmail", createMailRoutes(accountManager2, config, db, gatewayManager));
4874
+ app2.use("/api/agenticmail", createEventRoutes(accountManager2, config, db));
4774
4875
  app2.use("/api/agenticmail", createDomainRoutes(domainManager));
4775
4876
  app2.use("/api/agenticmail", createGatewayRoutes(gatewayManager));
4776
- app2.use("/api/agenticmail", createFeatureRoutes(db, accountManager, config, gatewayManager));
4777
- app2.use("/api/agenticmail", createTaskRoutes(db, accountManager, config));
4778
- app2.use("/api/agenticmail", createSmsRoutes(db, accountManager, config, gatewayManager));
4779
- app2.use("/api/agenticmail", createStorageRoutes(db, accountManager, config));
4877
+ app2.use("/api/agenticmail", createFeatureRoutes(db, accountManager2, config, gatewayManager));
4878
+ app2.use("/api/agenticmail", createTaskRoutes(db, accountManager2, config));
4879
+ app2.use("/api/agenticmail", createSmsRoutes(db, accountManager2, config, gatewayManager));
4880
+ app2.use("/api/agenticmail", createStorageRoutes(db, accountManager2, config));
4780
4881
  app2.use("/api/agenticmail", createSystemEventRoutes());
4781
4882
  app2.use("/api/agenticmail", createDispatcherActivityRoutes());
4782
4883
  app2.use("/api/agenticmail", (_req, res) => {
4783
4884
  res.status(404).json({ error: "Not found" });
4784
4885
  });
4785
4886
  app2.use(errorHandler);
4786
- const context2 = { config, db, stalwart, accountManager, domainManager, gatewayManager };
4887
+ const context2 = { config, db, stalwart, accountManager: accountManager2, domainManager, gatewayManager };
4787
4888
  return { app: app2, context: context2 };
4788
4889
  }
4789
4890
 
4790
4891
  // src/index.ts
4791
4892
  import { readFileSync as readFileSync2 } from "fs";
4792
- import { fileURLToPath as fileURLToPath2 } from "url";
4793
- import { dirname as dirname2, join as join2 } from "path";
4893
+ import { fileURLToPath as fileURLToPath3 } from "url";
4894
+ import { dirname as dirname3, join as join3 } from "path";
4794
4895
  await prepareIntegrations();
4795
4896
  function getLocalIp() {
4796
4897
  const nets = networkInterfaces();
@@ -4804,8 +4905,8 @@ function getLocalIp() {
4804
4905
  }
4805
4906
  var VERSION = (() => {
4806
4907
  try {
4807
- const __dirname = dirname2(fileURLToPath2(import.meta.url));
4808
- const pkg = JSON.parse(readFileSync2(join2(__dirname, "..", "package.json"), "utf-8"));
4908
+ const __dirname = dirname3(fileURLToPath3(import.meta.url));
4909
+ const pkg = JSON.parse(readFileSync2(join3(__dirname, "..", "package.json"), "utf-8"));
4809
4910
  return pkg.version;
4810
4911
  } catch {
4811
4912
  return "0.5.31";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/api",
3
- "version": "0.7.4",
3
+ "version": "0.7.7",
4
4
  "description": "REST API server for AgenticMail — email and SMS endpoints for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,7 @@
14
14
  },
15
15
  "files": [
16
16
  "dist",
17
+ "public",
17
18
  "README.md",
18
19
  "REFERENCE.md",
19
20
  "LICENSE"