@agenticmail/api 0.9.9 → 0.9.11

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
@@ -1861,7 +1861,19 @@ function normalizeWakeList(value) {
1861
1861
  if (value === "all" || value === WAKE_ALL_SENTINEL) return void 0;
1862
1862
  const strip = (s) => s.trim().replace(/@localhost$/i, "").toLowerCase();
1863
1863
  if (Array.isArray(value)) return value.map((v) => strip(String(v))).filter(Boolean);
1864
- if (typeof value === "string") return value.split(",").map(strip).filter(Boolean);
1864
+ if (typeof value === "string") {
1865
+ const trimmed = value.trim();
1866
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
1867
+ try {
1868
+ const parsed = JSON.parse(trimmed);
1869
+ if (Array.isArray(parsed)) {
1870
+ return parsed.map((v) => strip(String(v))).filter(Boolean);
1871
+ }
1872
+ } catch {
1873
+ }
1874
+ }
1875
+ return value.split(",").map(strip).filter(Boolean);
1876
+ }
1865
1877
  return void 0;
1866
1878
  }
1867
1879
  function deriveDefaultWakeList(toField) {
@@ -2560,19 +2572,22 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
2560
2572
  router.post("/mail/batch/move", requireAgent, async (req, res, next) => {
2561
2573
  try {
2562
2574
  const agent = req.agent;
2563
- const { uids: rawUids, from: fromFolder, to: toFolder } = req.body || {};
2564
- const uids = validateUids(rawUids);
2575
+ const body = req.body || {};
2576
+ const uids = validateUids(body.uids);
2565
2577
  if (!uids) {
2566
2578
  res.status(400).json({ error: "uids must be a non-empty array of positive integers (max 1000)" });
2567
2579
  return;
2568
2580
  }
2581
+ const fromFolder = body.from ?? body.folder;
2582
+ const toFolder = body.to ?? body.toFolder;
2569
2583
  if (!toFolder) {
2570
- res.status(400).json({ error: "to (destination folder) is required" });
2584
+ res.status(400).json({ error: "destination folder is required (pass as `to` or `toFolder`)" });
2571
2585
  return;
2572
2586
  }
2573
2587
  const password = getAgentPassword(agent);
2574
2588
  const receiver = await getReceiver(agent.stalwartPrincipal, password, config);
2575
2589
  await receiver.batchMove(uids, fromFolder || "INBOX", toFolder);
2590
+ for (const uid of uids) invalidateParsedMessage(agent.id, uid);
2576
2591
  res.json({ ok: true, moved: uids.length });
2577
2592
  } catch (err) {
2578
2593
  next(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/api",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
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",
@@ -107,7 +107,7 @@ export async function loadList(agent, folder) {
107
107
  </div>
108
108
  <div class="list-toolbar-spacer"></div>
109
109
  <span class="count-text" id="list-count"></span>
110
- <button class="icon-btn pager-btn" id="pager-prev" title="Newer" data-icon="back"></button>
110
+ <button class="icon-btn pager-btn" id="pager-prev" title="Newer"></button>
111
111
  <button class="icon-btn pager-btn" id="pager-next" title="Older"></button>
112
112
  </div>
113
113
  <div class="list-rows" id="list-rows"><div class="empty">Loading…</div></div>
@@ -116,6 +116,14 @@ export async function loadList(agent, folder) {
116
116
  // the head of the inbox); "Older" advances to higher offsets.
117
117
  // Each handler clamps to valid bounds and refetches via loadList
118
118
  // with the new offset preserved in state.pagination.
119
+ //
120
+ // Both buttons share the same `back` chevron glyph — Prev is the
121
+ // glyph as-is (points left), Next rotates it 180° to point right.
122
+ // Previously Prev had only a `data-icon="back"` attribute (no
123
+ // innerHTML assignment), which left it visually empty — the user
124
+ // could click it but couldn't see it, so on page 2+ the back
125
+ // button looked entirely missing.
126
+ document.getElementById('pager-prev').innerHTML = icon('back', { size: 18 });
119
127
  document.getElementById('pager-next').innerHTML = icon('back', { size: 18 });
120
128
  document.getElementById('pager-next').style.transform = 'rotate(180deg)';
121
129
  document.getElementById('pager-prev')?.addEventListener('click', () => goToPage(agent, folder, -1));
@@ -149,7 +157,18 @@ export async function loadList(agent, folder) {
149
157
  // side flag filter (Gmail convention); other folders need a real
150
158
  // mailbox name from the discovery cache.
151
159
  const isStarred = folder === 'starred';
152
- const imap = isStarred ? 'INBOX' : imapNameFor(folder);
160
+ let imap = isStarred ? 'INBOX' : imapNameFor(folder);
161
+ if (!imap) {
162
+ // The cache was populated at agent-switch time; some folders are
163
+ // created LATER on demand (the API auto-creates Archive on first
164
+ // archive, Spam on first report-as-spam). If we don't see the
165
+ // requested folder in the cache, force a fresh discovery once
166
+ // before declaring "no such folder" — covers the "moved to
167
+ // Archive but Archive tab is empty" report.
168
+ state.folderNames = {};
169
+ await ensureFolderCache(agent);
170
+ imap = imapNameFor(folder);
171
+ }
153
172
  if (!imap) {
154
173
  document.getElementById('list-rows').innerHTML =
155
174
  `<div class="empty"><div class="big">📭</div>No ${escapeHtml(folderTitle(folder))} folder on this server.</div>`;