@rubytech/create-maxy-code 0.1.501 → 0.1.502

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.
Files changed (65) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/docs/superpowers/plans/2026-07-25-task-1974-uploads-intake-inbox.md +235 -0
  3. package/payload/platform/docs/superpowers/plans/2026-07-25-task-1976-intra-folder-hygiene.md +215 -0
  4. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
  5. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +7 -0
  6. package/payload/platform/plugins/docs/references/internals.md +1 -1
  7. package/payload/platform/templates/account-schema/SCHEMA.md +36 -1
  8. package/payload/platform/templates/specialists/agents/data-manager.md +4 -2
  9. package/payload/server/public/activity.html +5 -5
  10. package/payload/server/public/assets/AdminLoginScreens-Bv_bKKeL.js +1 -0
  11. package/payload/server/public/assets/AdminShell-Gq8DU_ig.js +2 -0
  12. package/payload/server/public/assets/{activity-CVdVSw5V.js → activity-DZFYDHNA.js} +1 -1
  13. package/payload/server/public/assets/{admin-If1QLlS3.js → admin-DLUOixl6.js} +1 -1
  14. package/payload/server/public/assets/{bot-8b26IlQY.js → bot-CrEhKW1l.js} +1 -1
  15. package/payload/server/public/assets/{browser-F40DXfKA.js → browser-Bt4-LKLU.js} +1 -1
  16. package/payload/server/public/assets/{calendar-DZiHiBwV.js → calendar-D0qIvLUR.js} +1 -1
  17. package/payload/server/public/assets/chat-geSkx0j2.js +1 -0
  18. package/payload/server/public/assets/chevron-left-CQ8rcBoO.js +1 -0
  19. package/payload/server/public/assets/chevron-right-CSRSqblN.js +1 -0
  20. package/payload/server/public/assets/clock-B7Ba8AZL.js +1 -0
  21. package/payload/server/public/assets/data-BdlGqjKM.js +1 -0
  22. package/payload/server/public/assets/{file-text-B1HjPFbM.js → file-text-BpLcZKld.js} +1 -1
  23. package/payload/server/public/assets/{graph-CIC-mgKR.js → graph-HB0199x-.js} +3 -3
  24. package/payload/server/public/assets/{graph-labels-BnpHCHaQ.js → graph-labels-Bx19ZYvJ.js} +1 -1
  25. package/payload/server/public/assets/{maximize-2-BL7QVTcQ.js → maximize-2-BhR-Ec21.js} +1 -1
  26. package/payload/server/public/assets/operator-DejfJlvi.js +1 -0
  27. package/payload/server/public/assets/page-DomkejEB.js +32 -0
  28. package/payload/server/public/assets/page-FnCmAeHc.js +1 -0
  29. package/payload/server/public/assets/{public-BI21tOkm.js → public-Be_Galv6.js} +1 -1
  30. package/payload/server/public/assets/{rotate-ccw-C_20Bc3E.js → rotate-ccw-D9qOBLig.js} +1 -1
  31. package/payload/server/public/assets/{routines-Ci3N8wqV.js → routines-lGiYaMiX.js} +1 -1
  32. package/payload/server/public/assets/{skills-CiflzOko.js → skills-D9nWOqoz.js} +1 -1
  33. package/payload/server/public/assets/{tasks-DC2Yf2Ev.js → tasks-Cyc1EfLA.js} +1 -1
  34. package/payload/server/public/assets/{time-entry-format-CNcjs2HV.js → time-entry-format-RkCW7hKu.js} +1 -1
  35. package/payload/server/public/assets/{triangle-alert-CngnWtjD.js → triangle-alert-k8ulav-N.js} +1 -1
  36. package/payload/server/public/assets/{useCopyFeedback-DZ9Bw5CI.js → useCopyFeedback-DN1WA5vU.js} +1 -1
  37. package/payload/server/public/assets/useSubAccountSwitcher-fvBunpOC.css +1 -0
  38. package/payload/server/public/assets/useSubAccountSwitcher-iQGqNJhI.js +9 -0
  39. package/payload/server/public/assets/useVoiceRecorder-v--TIxaM.js +2 -0
  40. package/payload/server/public/assets/{wrench-dky2-13x.js → wrench-CKhz8KnQ.js} +1 -1
  41. package/payload/server/public/browser.html +4 -4
  42. package/payload/server/public/calendar.html +7 -7
  43. package/payload/server/public/chat.html +14 -14
  44. package/payload/server/public/data.html +11 -11
  45. package/payload/server/public/graph.html +9 -9
  46. package/payload/server/public/index.html +15 -15
  47. package/payload/server/public/operator.html +15 -15
  48. package/payload/server/public/public.html +14 -14
  49. package/payload/server/public/routines.html +6 -6
  50. package/payload/server/public/skills.html +5 -5
  51. package/payload/server/public/tasks.html +6 -6
  52. package/payload/server/server.js +840 -748
  53. package/payload/server/public/assets/AdminLoginScreens-C3LZOPIY.js +0 -1
  54. package/payload/server/public/assets/AdminShell-BlbUNAPc.js +0 -2
  55. package/payload/server/public/assets/chat-uD28FVCS.js +0 -1
  56. package/payload/server/public/assets/chevron-left-lBxD57tD.js +0 -1
  57. package/payload/server/public/assets/chevron-right-C-lDig9Y.js +0 -1
  58. package/payload/server/public/assets/clock-DqRNsY40.js +0 -1
  59. package/payload/server/public/assets/data-BsFyBN85.js +0 -1
  60. package/payload/server/public/assets/operator-B62h_TaC.js +0 -1
  61. package/payload/server/public/assets/page-BUUBseJZ.js +0 -32
  62. package/payload/server/public/assets/page-Bw-tYjw7.js +0 -1
  63. package/payload/server/public/assets/useSubAccountSwitcher-CHwQhkaI.js +0 -9
  64. package/payload/server/public/assets/useSubAccountSwitcher-yFQqnpQ8.css +0 -1
  65. package/payload/server/public/assets/useVoiceRecorder-C3G6aqZr.js +0 -2
@@ -1753,10 +1753,10 @@ var serveStatic = (options = { root: "" }) => {
1753
1753
  };
1754
1754
 
1755
1755
  // server/index.ts
1756
- import { readFileSync as readFileSync46, existsSync as existsSync43, watchFile, readdirSync as readdirSync27, statSync as statSync18 } from "fs";
1756
+ import { readFileSync as readFileSync46, existsSync as existsSync45, watchFile, readdirSync as readdirSync27, statSync as statSync20 } from "fs";
1757
1757
  import { spawn as spawn3 } from "child_process";
1758
1758
  import { createHash as createHash7 } from "crypto";
1759
- import { resolve as resolve42, join as join47, basename as basename13 } from "path";
1759
+ import { resolve as resolve43, join as join47, basename as basename14 } from "path";
1760
1760
  import { homedir as homedir4 } from "os";
1761
1761
  import { monitorEventLoopDelay } from "perf_hooks";
1762
1762
 
@@ -3030,7 +3030,7 @@ var credsSaveQueue = Promise.resolve();
3030
3030
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
3031
3031
  console.error(`${TAG6} draining credential save queue\u2026`);
3032
3032
  const timer = new Promise(
3033
- (resolve43) => setTimeout(() => resolve43("timeout"), timeoutMs)
3033
+ (resolve44) => setTimeout(() => resolve44("timeout"), timeoutMs)
3034
3034
  );
3035
3035
  const result = await Promise.race([
3036
3036
  credsSaveQueue.then(() => "drained"),
@@ -3207,11 +3207,11 @@ async function createWaSocket(opts) {
3207
3207
  return sock;
3208
3208
  }
3209
3209
  async function waitForConnection(sock) {
3210
- return new Promise((resolve43, reject) => {
3210
+ return new Promise((resolve44, reject) => {
3211
3211
  const handler = (update) => {
3212
3212
  if (update.connection === "open") {
3213
3213
  sock.ev.off("connection.update", handler);
3214
- resolve43();
3214
+ resolve44();
3215
3215
  }
3216
3216
  if (update.connection === "close") {
3217
3217
  sock.ev.off("connection.update", handler);
@@ -3319,7 +3319,7 @@ function isTimeoutError(err) {
3319
3319
  return Boolean(err?.__maxyTimeout);
3320
3320
  }
3321
3321
  function withTimeout(label, promise, timeoutMs) {
3322
- return new Promise((resolve43, reject) => {
3322
+ return new Promise((resolve44, reject) => {
3323
3323
  const timer = setTimeout(() => {
3324
3324
  const err = new Error(`${label} timed out after ${timeoutMs}ms`);
3325
3325
  err.__maxyTimeout = true;
@@ -3329,7 +3329,7 @@ function withTimeout(label, promise, timeoutMs) {
3329
3329
  promise.then(
3330
3330
  (value) => {
3331
3331
  clearTimeout(timer);
3332
- resolve43(value);
3332
+ resolve44(value);
3333
3333
  },
3334
3334
  (err) => {
3335
3335
  clearTimeout(timer);
@@ -4394,8 +4394,8 @@ async function persistWhatsAppMessage(input) {
4394
4394
  const { givenName, familyName } = splitName(input.pushName);
4395
4395
  const prev = sessionWriteLocks.get(input.cacheKey);
4396
4396
  let release;
4397
- const mine = new Promise((resolve43) => {
4398
- release = resolve43;
4397
+ const mine = new Promise((resolve44) => {
4398
+ release = resolve44;
4399
4399
  });
4400
4400
  const chained = (prev ?? Promise.resolve()).then(() => mine);
4401
4401
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -6132,11 +6132,11 @@ async function connectWithReconnect(conn) {
6132
6132
  console.error(
6133
6133
  `${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
6134
6134
  );
6135
- await new Promise((resolve43) => {
6136
- const timer = setTimeout(resolve43, delay);
6135
+ await new Promise((resolve44) => {
6136
+ const timer = setTimeout(resolve44, delay);
6137
6137
  conn.abortController.signal.addEventListener("abort", () => {
6138
6138
  clearTimeout(timer);
6139
- resolve43();
6139
+ resolve44();
6140
6140
  }, { once: true });
6141
6141
  });
6142
6142
  }
@@ -6144,16 +6144,16 @@ async function connectWithReconnect(conn) {
6144
6144
  }
6145
6145
  }
6146
6146
  function waitForDisconnectEvent(conn) {
6147
- return new Promise((resolve43) => {
6147
+ return new Promise((resolve44) => {
6148
6148
  if (!conn.sock) {
6149
- resolve43();
6149
+ resolve44();
6150
6150
  return;
6151
6151
  }
6152
6152
  const sock = conn.sock;
6153
6153
  const handler = (update) => {
6154
6154
  if (update.connection === "close") {
6155
6155
  sock.ev.off("connection.update", handler);
6156
- resolve43();
6156
+ resolve44();
6157
6157
  }
6158
6158
  };
6159
6159
  sock.ev.on("connection.update", handler);
@@ -6627,8 +6627,8 @@ async function handleInboundMessage(conn, msg) {
6627
6627
  const conversationKey = isGroup ? remoteJid : senderPhone;
6628
6628
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
6629
6629
  let resolvePending;
6630
- const sttPending = new Promise((resolve43) => {
6631
- resolvePending = resolve43;
6630
+ const sttPending = new Promise((resolve44) => {
6631
+ resolvePending = resolve44;
6632
6632
  });
6633
6633
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
6634
6634
  try {
@@ -7017,20 +7017,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
7017
7017
 
7018
7018
  // server/routes/health.ts
7019
7019
  function checkPort(port2, timeoutMs = 500) {
7020
- return new Promise((resolve43) => {
7020
+ return new Promise((resolve44) => {
7021
7021
  const socket = createConnection2(port2, "127.0.0.1");
7022
7022
  socket.setTimeout(timeoutMs);
7023
7023
  socket.once("connect", () => {
7024
7024
  socket.destroy();
7025
- resolve43(true);
7025
+ resolve44(true);
7026
7026
  });
7027
7027
  socket.once("error", () => {
7028
7028
  socket.destroy();
7029
- resolve43(false);
7029
+ resolve44(false);
7030
7030
  });
7031
7031
  socket.once("timeout", () => {
7032
7032
  socket.destroy();
7033
- resolve43(false);
7033
+ resolve44(false);
7034
7034
  });
7035
7035
  });
7036
7036
  }
@@ -7285,8 +7285,8 @@ function webchatTurnTimeoutMs() {
7285
7285
  return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
7286
7286
  }
7287
7287
  function createChatRoutes(deps) {
7288
- const app67 = new Hono();
7289
- app67.post("/", async (c) => {
7288
+ const app68 = new Hono();
7289
+ app68.post("/", async (c) => {
7290
7290
  console.log(`[chat-route] entered route=public method=POST`);
7291
7291
  const contentType = c.req.header("content-type") ?? "";
7292
7292
  const account = resolveAccount();
@@ -7550,7 +7550,7 @@ ${result.result.text}` : result.result.text;
7550
7550
  }
7551
7551
  });
7552
7552
  });
7553
- return app67;
7553
+ return app68;
7554
7554
  }
7555
7555
 
7556
7556
  // app/lib/channel-pty-bridge/admin-session-id.ts
@@ -7584,8 +7584,8 @@ function isLoopbackAddr(addr) {
7584
7584
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
7585
7585
  }
7586
7586
  function createScheduleInjectRoutes(deps) {
7587
- const app67 = new Hono();
7588
- app67.post("/", async (c) => {
7587
+ const app68 = new Hono();
7588
+ app68.post("/", async (c) => {
7589
7589
  const env = c.env;
7590
7590
  const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
7591
7591
  if (!isLoopbackAddr(remoteAddr)) {
@@ -7686,7 +7686,7 @@ function createScheduleInjectRoutes(deps) {
7686
7686
  console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
7687
7687
  return c.json({ ok: true }, 200);
7688
7688
  });
7689
- return app67;
7689
+ return app68;
7690
7690
  }
7691
7691
 
7692
7692
  // server/index.ts
@@ -8369,8 +8369,8 @@ async function startLogin(opts) {
8369
8369
  await clearAuth(authDir);
8370
8370
  let resolveCode = null;
8371
8371
  let rejectCode = null;
8372
- const codePromise = new Promise((resolve43, reject) => {
8373
- resolveCode = resolve43;
8372
+ const codePromise = new Promise((resolve44, reject) => {
8373
+ resolveCode = resolve44;
8374
8374
  rejectCode = reject;
8375
8375
  });
8376
8376
  const codeTimer = setTimeout(
@@ -11164,8 +11164,8 @@ function runReconcileLivenessAudit(statePath, nowMs, intervalMs, emit) {
11164
11164
  }
11165
11165
 
11166
11166
  // server/routes/whatsapp-reader.ts
11167
- import { readFileSync as readFileSync21, watch, statSync as statSync7, openSync, readSync, closeSync, existsSync as existsSync16, readdirSync as readdirSync14, realpathSync as realpathSync5 } from "fs";
11168
- import { basename as basename5, dirname as dirname6, isAbsolute, join as join21, relative as relative3, resolve as resolve15, sep as sep4 } from "path";
11167
+ import { readFileSync as readFileSync21, watch, statSync as statSync8, openSync, readSync, closeSync, existsSync as existsSync17, readdirSync as readdirSync14, realpathSync as realpathSync6 } from "fs";
11168
+ import { basename as basename6, dirname as dirname7, isAbsolute, join as join21, relative as relative3, resolve as resolve16, sep as sep5 } from "path";
11169
11169
 
11170
11170
  // server/routes/admin/sidebar-sessions.ts
11171
11171
  import { readdirSync as readdirSync12, readFileSync as readFileSync19, statSync as statSync6 } from "fs";
@@ -11184,11 +11184,11 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
11184
11184
  } catch {
11185
11185
  return null;
11186
11186
  }
11187
- const basename14 = `${sessionId}.jsonl`;
11187
+ const basename15 = `${sessionId}.jsonl`;
11188
11188
  for (const slug of slugs) {
11189
- const live = join17(projectsRoot, slug, basename14);
11189
+ const live = join17(projectsRoot, slug, basename15);
11190
11190
  if (existsSync14(live)) return live;
11191
- const archived = join17(projectsRoot, slug, "archive", basename14);
11191
+ const archived = join17(projectsRoot, slug, "archive", basename15);
11192
11192
  if (existsSync14(archived)) return archived;
11193
11193
  }
11194
11194
  return null;
@@ -11982,8 +11982,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
11982
11982
  }
11983
11983
 
11984
11984
  // app/lib/whatsapp-reader/enrich-attachments.ts
11985
- import { readFileSync as readFileSync20, readdirSync as readdirSync13 } from "fs";
11986
- import { join as join20 } from "path";
11985
+ import { readFileSync as readFileSync20, readdirSync as readdirSync13, existsSync as existsSync16, statSync as statSync7, realpathSync as realpathSync5 } from "fs";
11986
+ import { basename as basename5, dirname as dirname6, join as join20, resolve as resolve15, sep as sep4 } from "path";
11987
11987
  var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
11988
11988
  function adminAttachmentIds(text) {
11989
11989
  const ids = [];
@@ -12001,6 +12001,48 @@ function adminAttachmentsFromText(text, uploadsBase) {
12001
12001
  }
12002
12002
  return out;
12003
12003
  }
12004
+ function claudeUploadsRoot() {
12005
+ return process.env.CLAUDE_CONFIG_DIR ? resolve15(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
12006
+ }
12007
+ var CC_MENTION_RE = /@"([^"]+)"/g;
12008
+ function claudeUploadAttachmentsFromText(text, sessionId) {
12009
+ const root = claudeUploadsRoot();
12010
+ if (!root) return { attachments: [], strippedText: text };
12011
+ const sessionDir = resolve15(root, sessionId);
12012
+ const attachments = [];
12013
+ const accepted = [];
12014
+ for (const m of text.matchAll(CC_MENTION_RE)) {
12015
+ let abs;
12016
+ try {
12017
+ abs = resolve15(m[1]);
12018
+ } catch {
12019
+ continue;
12020
+ }
12021
+ if (dirname6(abs) !== sessionDir) continue;
12022
+ if (abs !== sessionDir + sep4 + basename5(abs)) continue;
12023
+ if (!existsSync16(abs)) continue;
12024
+ let real;
12025
+ try {
12026
+ real = realpathSync5(abs);
12027
+ } catch {
12028
+ continue;
12029
+ }
12030
+ if (dirname6(real) !== realpathSync5(sessionDir)) continue;
12031
+ const filename = basename5(abs);
12032
+ attachments.push({
12033
+ attachmentId: filename,
12034
+ filename,
12035
+ mimeType: detectMimeType(filename),
12036
+ sizeBytes: statSync7(real).size,
12037
+ source: "claude-upload"
12038
+ });
12039
+ accepted.push(m[0]);
12040
+ }
12041
+ if (accepted.length === 0) return { attachments, strippedText: text };
12042
+ let strippedText = text;
12043
+ for (const tok of accepted) strippedText = strippedText.split(tok).join("");
12044
+ return { attachments, strippedText: strippedText.trim() };
12045
+ }
12004
12046
  function readSidecar(dir, attachmentId) {
12005
12047
  let parsed;
12006
12048
  try {
@@ -12198,8 +12240,8 @@ app5.get("/conversations", requireAdminSession, async (c) => {
12198
12240
  const rows = [];
12199
12241
  let sessionRowsExcludedUntagged = 0;
12200
12242
  for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
12201
- const sessionId = basename5(path3).replace(/\.jsonl$/, "");
12202
- const projectDir = dirname6(path3);
12243
+ const sessionId = basename6(path3).replace(/\.jsonl$/, "");
12244
+ const projectDir = dirname7(path3);
12203
12245
  const meta = readSidecarMeta(join21(projectDir, `${sessionId}.meta.json`));
12204
12246
  if (!isReaderChannelSession(meta.role, meta.channel)) continue;
12205
12247
  if (multiAccount) {
@@ -12337,8 +12379,8 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
12337
12379
  const houseIds = new Set(validAccounts.filter((a) => a.config.role === "house").map((a) => a.accountId));
12338
12380
  const rawByAccount = /* @__PURE__ */ new Map();
12339
12381
  for (const { path: path3 } of enumerateJsonls(projectsRoot)) {
12340
- const sessionId = basename5(path3).replace(/\.jsonl$/, "");
12341
- const projectDir = dirname6(path3);
12382
+ const sessionId = basename6(path3).replace(/\.jsonl$/, "");
12383
+ const projectDir = dirname7(path3);
12342
12384
  const meta = readSidecarMeta(join21(projectDir, `${sessionId}.meta.json`));
12343
12385
  if (!isReaderChannelSession(meta.role, meta.channel)) continue;
12344
12386
  if (meta.accountId === null || !validIds.has(meta.accountId)) continue;
@@ -12407,7 +12449,7 @@ app5.get("/conversations-all", requireAdminSession, async (c) => {
12407
12449
  return c.json({ conversations });
12408
12450
  });
12409
12451
  function readFrom(path3, from) {
12410
- const end = statSync7(path3).size;
12452
+ const end = statSync8(path3).size;
12411
12453
  if (end <= from) return { buf: Buffer.alloc(0), end: from };
12412
12454
  const fd = openSync(path3, "r");
12413
12455
  try {
@@ -12431,7 +12473,7 @@ function enrichDownloads(turn, scratchpadRoot) {
12431
12473
  if (turn.kind !== "agent-file") return turn;
12432
12474
  let scratchpadReal = null;
12433
12475
  try {
12434
- scratchpadReal = realpathSync5(scratchpadRoot);
12476
+ scratchpadReal = realpathSync6(scratchpadRoot);
12435
12477
  } catch {
12436
12478
  scratchpadReal = null;
12437
12479
  }
@@ -12442,8 +12484,8 @@ function enrichDownloads(turn, scratchpadRoot) {
12442
12484
  }
12443
12485
  if (scratchpadReal) {
12444
12486
  try {
12445
- const fileReal = realpathSync5(f);
12446
- if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal + sep4)) {
12487
+ const fileReal = realpathSync6(f);
12488
+ if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal + sep5)) {
12447
12489
  return { root: "scratchpad", path: relative3(scratchpadReal, fileReal) };
12448
12490
  }
12449
12491
  } catch {
@@ -12454,13 +12496,19 @@ function enrichDownloads(turn, scratchpadRoot) {
12454
12496
  });
12455
12497
  return { ...turn, downloads };
12456
12498
  }
12457
- function enrichAdminAttachments(turn) {
12499
+ function enrichAdminAttachments(turn, sessionId) {
12458
12500
  if (turn.kind !== "operator-inbound") return turn;
12459
- if (adminAttachmentIds(turn.text).length === 0) return turn;
12501
+ if (!turn.text.includes('@"') && adminAttachmentIds(turn.text).length === 0) return turn;
12460
12502
  const account = resolveAccount();
12461
- if (!account) return turn;
12462
- const attachments = adminAttachmentsFromText(turn.text, resolve15(DATA_ROOT, "accounts", account.accountId, "uploads"));
12463
- return attachments.length > 0 ? { ...turn, attachments } : turn;
12503
+ const store2 = account ? adminAttachmentsFromText(turn.text, resolve16(DATA_ROOT, "accounts", account.accountId, "uploads")) : [];
12504
+ const cc = claudeUploadAttachmentsFromText(turn.text, sessionId);
12505
+ if (cc.attachments.length > 0) {
12506
+ console.log(`[session-upload-shape] op=mention accepted=${cc.attachments.length} session=${sessionId.slice(0, 8)}`);
12507
+ }
12508
+ const attachments = [...store2, ...cc.attachments];
12509
+ if (attachments.length === 0) return turn;
12510
+ const text = cc.attachments.length > 0 ? cc.strippedText : turn.text;
12511
+ return { ...turn, attachments, text };
12464
12512
  }
12465
12513
  var CONCURRENCY_WINDOW_MS = 3e5;
12466
12514
  var AGENT_JSONL_RE = /^agent-([0-9a-f]+)\.jsonl$/;
@@ -12527,7 +12575,7 @@ function runActivityTick(c) {
12527
12575
  let size = 0;
12528
12576
  let mtimeMs = 0;
12529
12577
  try {
12530
- const st = statSync7(join21(c.subagentsDir, name));
12578
+ const st = statSync8(join21(c.subagentsDir, name));
12531
12579
  size = st.size;
12532
12580
  mtimeMs = st.mtimeMs;
12533
12581
  } catch {
@@ -12572,12 +12620,12 @@ app5.get("/stream", requireAdminSession, (c) => {
12572
12620
  const sessionId = c.req.query("sessionId") ?? "";
12573
12621
  const projectDir = c.req.query("projectDir") ?? "";
12574
12622
  const cfg = claudeConfigDir();
12575
- const projectsRoot = cfg ? resolve15(join21(cfg, "projects")) : null;
12623
+ const projectsRoot = cfg ? resolve16(join21(cfg, "projects")) : null;
12576
12624
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
12577
12625
  return c.json({ error: "bad session reference" }, 400);
12578
12626
  }
12579
- const jsonlPath = resolve15(join21(projectDir, `${sessionId}.jsonl`));
12580
- if (!jsonlPath.startsWith(projectsRoot + sep4)) {
12627
+ const jsonlPath = resolve16(join21(projectDir, `${sessionId}.jsonl`));
12628
+ if (!jsonlPath.startsWith(projectsRoot + sep5)) {
12581
12629
  return c.json({ error: "bad session reference" }, 400);
12582
12630
  }
12583
12631
  const scratchpadRoot = sessionScratchpadRoot(projectDir, sessionId);
@@ -12595,7 +12643,7 @@ data: ${JSON.stringify(turn)}
12595
12643
  start(controller) {
12596
12644
  const fileEnd0 = (() => {
12597
12645
  try {
12598
- return statSync7(jsonlPath).size;
12646
+ return statSync8(jsonlPath).size;
12599
12647
  } catch {
12600
12648
  return 0;
12601
12649
  }
@@ -12603,9 +12651,9 @@ data: ${JSON.stringify(turn)}
12603
12651
  let offset = resumeOffset(lastEventId, fileEnd0);
12604
12652
  console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
12605
12653
  const sessionKey = c.req.query("session_key") ?? "";
12606
- const subagentsDir = resolve15(join21(projectDir, sessionId, "subagents"));
12654
+ const subagentsDir = resolve16(join21(projectDir, sessionId, "subagents"));
12607
12655
  console.log(
12608
- `[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync16(subagentsDir)}`
12656
+ `[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync17(subagentsDir)}`
12609
12657
  );
12610
12658
  const actx = makeActivityCtx({
12611
12659
  subagentsDir,
@@ -12631,7 +12679,7 @@ data: ${JSON.stringify(obj)}
12631
12679
  offset = nextOffset;
12632
12680
  let n = 0;
12633
12681
  for (const turn of parseTranscript(lines, queuedPendingSuppress, turnCtx)) {
12634
- send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
12682
+ send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot), sessionId), offset);
12635
12683
  actx.lastParentTurns.push(turn);
12636
12684
  if (turn.kind === "agent-error") {
12637
12685
  console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
@@ -12651,7 +12699,7 @@ data: ${JSON.stringify(obj)}
12651
12699
  offset = end;
12652
12700
  let n = 0;
12653
12701
  for (const turn of parseTranscript(buf.toString("utf8").split("\n"), queuedPendingSuppress, turnCtx)) {
12654
- send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
12702
+ send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot), sessionId), offset);
12655
12703
  actx.lastParentTurns.push(turn);
12656
12704
  if (turn.kind === "agent-error") {
12657
12705
  console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
@@ -12713,13 +12761,13 @@ var DIRECTIVE_NAME_RE = /^\d+-\d+\.txt$/;
12713
12761
  function directiveStoreDir(sessionId) {
12714
12762
  const account = resolveAccount();
12715
12763
  if (!account) return null;
12716
- return resolve15(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
12764
+ return resolve16(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
12717
12765
  }
12718
12766
  app5.get("/directives", requireAdminSession, (c) => {
12719
12767
  const sessionId = c.req.query("sessionId") ?? "";
12720
12768
  if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
12721
12769
  const dir = directiveStoreDir(sessionId);
12722
- if (!dir || !existsSync16(dir)) return c.json({ entries: [] });
12770
+ if (!dir || !existsSync17(dir)) return c.json({ entries: [] });
12723
12771
  let names;
12724
12772
  try {
12725
12773
  names = readdirSync14(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
@@ -12732,7 +12780,7 @@ app5.get("/directives", requireAdminSession, (c) => {
12732
12780
  const pid = Number(pidPart);
12733
12781
  let len = 0;
12734
12782
  try {
12735
- len = statSync7(join21(dir, name)).size;
12783
+ len = statSync8(join21(dir, name)).size;
12736
12784
  } catch {
12737
12785
  }
12738
12786
  return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
@@ -12747,8 +12795,8 @@ app5.get("/directive", requireAdminSession, (c) => {
12747
12795
  }
12748
12796
  const dir = directiveStoreDir(sessionId);
12749
12797
  if (!dir) return c.json({ error: "no account" }, 404);
12750
- const path3 = resolve15(join21(dir, name));
12751
- if (!path3.startsWith(dir + sep4)) return c.json({ error: "bad reference" }, 400);
12798
+ const path3 = resolve16(join21(dir, name));
12799
+ if (!path3.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
12752
12800
  let body;
12753
12801
  try {
12754
12802
  body = readFileSync21(path3, "utf8");
@@ -12777,7 +12825,7 @@ app5.get("/store-stream", requireAdminSession, (c) => {
12777
12825
  const connId = `${remoteJid.slice(0, 12)}-${process.hrtime.bigint().toString(36).slice(-6)}`;
12778
12826
  const startedAt = Date.now();
12779
12827
  const lastEventId = c.req.header("Last-Event-ID");
12780
- const uploadsBase = resolve15(DATA_ROOT, "accounts", accountId, "uploads");
12828
+ const uploadsBase = resolve16(DATA_ROOT, "accounts", accountId, "uploads");
12781
12829
  const byMsgKeyId = /* @__PURE__ */ new Map();
12782
12830
  const reactionRecords = [];
12783
12831
  const reactionsForTarget = (msgKeyId) => foldReactions(reactionRecords).get(msgKeyId);
@@ -12838,7 +12886,7 @@ data: ${JSON.stringify(payload)}
12838
12886
  };
12839
12887
  const fileEnd0 = (() => {
12840
12888
  try {
12841
- return statSync7(file).size;
12889
+ return statSync8(file).size;
12842
12890
  } catch {
12843
12891
  return 0;
12844
12892
  }
@@ -13056,7 +13104,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
13056
13104
  const absolute = resolved.absolute;
13057
13105
  let size = -1;
13058
13106
  try {
13059
- const st = statSync7(absolute);
13107
+ const st = statSync8(absolute);
13060
13108
  size = st.isFile() ? st.size : -1;
13061
13109
  } catch {
13062
13110
  size = -1;
@@ -13069,7 +13117,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
13069
13117
  console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=none ok=true`);
13070
13118
  if (size > MAX_FILE_BYTES) {
13071
13119
  exit("rejected");
13072
- return c.json({ error: `"${basename5(absolute)}" exceeds the 50 MB limit` }, 400);
13120
+ return c.json({ error: `"${basename6(absolute)}" exceeds the 50 MB limit` }, 400);
13073
13121
  }
13074
13122
  const mime = detectMimeType(absolute);
13075
13123
  if (!isMimeAdmitted(mime, SUPPORTED_MIME_SET)) {
@@ -13166,7 +13214,7 @@ app5.post("/reply", requireAdminSession, async (c) => {
13166
13214
  }
13167
13215
  for (let i = 0; i < resolvedRefs.length; i++) {
13168
13216
  const { absolute, mime } = resolvedRefs[i];
13169
- const file = new File([readFileSync21(absolute)], basename5(absolute), { type: mime });
13217
+ const file = new File([readFileSync21(absolute)], basename6(absolute), { type: mime });
13170
13218
  const out = await sendStagedFile(file, `ref=${i}`);
13171
13219
  if (!out.ok) {
13172
13220
  exit("error");
@@ -13185,8 +13233,8 @@ app5.post("/reply", requireAdminSession, async (c) => {
13185
13233
  var whatsapp_reader_default = app5;
13186
13234
 
13187
13235
  // server/routes/public-reader.ts
13188
- import { statSync as statSync8, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync22, readdirSync as readdirSync15 } from "fs";
13189
- import { basename as basename6, dirname as dirname7, join as join22, resolve as resolve16, sep as sep5 } from "path";
13236
+ import { statSync as statSync9, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync22, readdirSync as readdirSync15 } from "fs";
13237
+ import { basename as basename7, dirname as dirname8, join as join22, resolve as resolve17, sep as sep6 } from "path";
13190
13238
 
13191
13239
  // app/lib/whatsapp-reader/delivered-kinds.ts
13192
13240
  var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
@@ -13261,8 +13309,8 @@ function enumeratePublicRows() {
13261
13309
  if (!cfg) return [];
13262
13310
  const rows = [];
13263
13311
  for (const { path: path3 } of enumerateJsonls(join22(cfg, "projects"))) {
13264
- const sessionId = basename6(path3).replace(/\.jsonl$/, "");
13265
- const projectDir = dirname7(path3);
13312
+ const sessionId = basename7(path3).replace(/\.jsonl$/, "");
13313
+ const projectDir = dirname8(path3);
13266
13314
  const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
13267
13315
  rows.push({
13268
13316
  sessionId,
@@ -13308,7 +13356,7 @@ app6.get("/session", (c) => {
13308
13356
  return c.json({ sessionId: null, projectDir: null, sessionKey });
13309
13357
  });
13310
13358
  function publicUploadsDir(accountId, sessionId) {
13311
- return resolve16(DATA_ROOT, "accounts", accountId, "uploads", "public", sessionId);
13359
+ return resolve17(DATA_ROOT, "accounts", accountId, "uploads", "public", sessionId);
13312
13360
  }
13313
13361
  function enrichPublicAttachments(turns, sessionAttachments, cursor) {
13314
13362
  for (const turn of turns) {
@@ -13319,7 +13367,7 @@ function enrichPublicAttachments(turns, sessionAttachments, cursor) {
13319
13367
  }
13320
13368
  }
13321
13369
  function readFrom2(path3, from) {
13322
- const end = statSync8(path3).size;
13370
+ const end = statSync9(path3).size;
13323
13371
  if (end <= from) return { buf: Buffer.alloc(0), end: from };
13324
13372
  const fd = openSync2(path3, "r");
13325
13373
  try {
@@ -13339,12 +13387,12 @@ app6.get("/stream", (c) => {
13339
13387
  const sessionId = c.req.query("sessionId") ?? "";
13340
13388
  const projectDir = c.req.query("projectDir") ?? "";
13341
13389
  const cfg = claudeConfigDir();
13342
- const projectsRoot = cfg ? resolve16(join22(cfg, "projects")) : null;
13390
+ const projectsRoot = cfg ? resolve17(join22(cfg, "projects")) : null;
13343
13391
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
13344
13392
  return c.json({ error: "bad session reference" }, 400);
13345
13393
  }
13346
- const jsonlPath = resolve16(join22(projectDir, `${sessionId}.jsonl`));
13347
- if (!jsonlPath.startsWith(projectsRoot + sep5)) {
13394
+ const jsonlPath = resolve17(join22(projectDir, `${sessionId}.jsonl`));
13395
+ if (!jsonlPath.startsWith(projectsRoot + sep6)) {
13348
13396
  return c.json({ error: "bad session reference" }, 400);
13349
13397
  }
13350
13398
  const meta = readSidecarMeta(join22(projectDir, `${sessionId}.meta.json`));
@@ -13447,8 +13495,8 @@ app6.get("/attachment/:attachmentId", (c) => {
13447
13495
  return new Response("Not found", { status: 404 });
13448
13496
  }
13449
13497
  const uploadsRoot = publicUploadsDir(account.accountId, sessionId);
13450
- const dir = resolve16(uploadsRoot, attachmentId);
13451
- if (!dir.startsWith(uploadsRoot + sep5)) {
13498
+ const dir = resolve17(uploadsRoot, attachmentId);
13499
+ if (!dir.startsWith(uploadsRoot + sep6)) {
13452
13500
  console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=bad-id`);
13453
13501
  return new Response("Not found", { status: 404 });
13454
13502
  }
@@ -13462,7 +13510,7 @@ app6.get("/attachment/:attachmentId", (c) => {
13462
13510
  try {
13463
13511
  dataFile = readdirSync15(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
13464
13512
  if (!dataFile) throw new Error("no data file");
13465
- buffer = readFileSync22(resolve16(dir, dataFile));
13513
+ buffer = readFileSync22(resolve17(dir, dataFile));
13466
13514
  } catch {
13467
13515
  console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
13468
13516
  return new Response("Not found", { status: 404 });
@@ -13483,9 +13531,9 @@ app6.get("/attachment/:attachmentId", (c) => {
13483
13531
  var public_reader_default = app6;
13484
13532
 
13485
13533
  // server/routes/webchat.ts
13486
- import { basename as basename7, dirname as dirname8 } from "path";
13534
+ import { basename as basename8, dirname as dirname9 } from "path";
13487
13535
  import { join as join25 } from "path";
13488
- import { existsSync as existsSync18, readdirSync as readdirSync17, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
13536
+ import { existsSync as existsSync19, readdirSync as readdirSync17, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync10, writeFileSync as writeFileSync9 } from "fs";
13489
13537
 
13490
13538
  // server/canonical-webchat-override.ts
13491
13539
  import { readFileSync as readFileSync23, writeFileSync as writeFileSync7, renameSync as renameSync2 } from "fs";
@@ -13572,7 +13620,7 @@ function isNewSessionEffortLevel(value) {
13572
13620
  }
13573
13621
 
13574
13622
  // ../services/claude-session-manager/src/sidecar-store.ts
13575
- import { existsSync as existsSync17, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync24, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
13623
+ import { existsSync as existsSync18, mkdirSync as mkdirSync4, readdirSync as readdirSync16, readFileSync as readFileSync24, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
13576
13624
  import { join as join24 } from "path";
13577
13625
  function escapeRegExp(s) {
13578
13626
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -13593,7 +13641,7 @@ function createSidecarStore(config) {
13593
13641
  return { ok: true };
13594
13642
  } catch (error) {
13595
13643
  try {
13596
- if (existsSync17(tmp)) unlinkSync2(tmp);
13644
+ if (existsSync18(tmp)) unlinkSync2(tmp);
13597
13645
  } catch {
13598
13646
  }
13599
13647
  return { ok: false, error };
@@ -13649,7 +13697,7 @@ function createSidecarStore(config) {
13649
13697
  function clear(sessionsDir, id) {
13650
13698
  const path3 = pathFor(sessionsDir, id);
13651
13699
  try {
13652
- if (existsSync17(path3)) {
13700
+ if (existsSync18(path3)) {
13653
13701
  unlinkSync2(path3);
13654
13702
  return { ok: true, removed: true };
13655
13703
  }
@@ -13717,7 +13765,7 @@ function locateSidecar(sessionId) {
13717
13765
  }
13718
13766
  for (const slug of slugs) {
13719
13767
  const metaPath = join25(projectsRoot, slug, `${sessionId}.meta.json`);
13720
- if (existsSync18(metaPath)) return readSidecarMeta(metaPath);
13768
+ if (existsSync19(metaPath)) return readSidecarMeta(metaPath);
13721
13769
  }
13722
13770
  return null;
13723
13771
  }
@@ -13747,7 +13795,7 @@ function sessionSidecarExists(sessionId) {
13747
13795
  function jsonlSizeBytes(projectDir, sessionId) {
13748
13796
  if (projectDir === null) return null;
13749
13797
  try {
13750
- return statSync9(join25(projectDir, `${sessionId}.jsonl`)).size;
13798
+ return statSync10(join25(projectDir, `${sessionId}.jsonl`)).size;
13751
13799
  } catch {
13752
13800
  return null;
13753
13801
  }
@@ -13885,13 +13933,13 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
13885
13933
  let best = null;
13886
13934
  for (const { path: path3, isSubagent, archived } of enumerateJsonls(join25(cfg, "projects"))) {
13887
13935
  if (isSubagent || archived) continue;
13888
- const id = basename7(path3).slice(0, -".jsonl".length);
13889
- const meta = readSidecarMeta(join25(dirname8(path3), `${id}.meta.json`));
13936
+ const id = basename8(path3).slice(0, -".jsonl".length);
13937
+ const meta = readSidecarMeta(join25(dirname9(path3), `${id}.meta.json`));
13890
13938
  if (meta.role !== "admin" || meta.channel !== "webchat") continue;
13891
13939
  if (multiAccount && meta.accountId !== scopeAccountId) continue;
13892
13940
  let mtimeMs;
13893
13941
  try {
13894
- mtimeMs = statSync9(path3).mtimeMs;
13942
+ mtimeMs = statSync10(path3).mtimeMs;
13895
13943
  } catch {
13896
13944
  continue;
13897
13945
  }
@@ -13909,7 +13957,7 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
13909
13957
  function overrideKnownNonArchived(id) {
13910
13958
  const { projectDir } = locateSession(id);
13911
13959
  if (projectDir === null) return sessionSidecarExists(id);
13912
- return basename7(projectDir) !== "archive";
13960
+ return basename8(projectDir) !== "archive";
13913
13961
  }
13914
13962
  function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId, scopeAccountId, multiAccount) {
13915
13963
  const bootstrapAccountId = scopeAccountId ?? accountId;
@@ -13945,8 +13993,8 @@ async function reapplyLeversViaManager() {
13945
13993
  var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
13946
13994
  var sendSeq = 0;
13947
13995
  function createWebchatRoutes(deps) {
13948
- const app67 = new Hono();
13949
- app67.post("/send", requireAdminSession, async (c) => {
13996
+ const app68 = new Hono();
13997
+ app68.post("/send", requireAdminSession, async (c) => {
13950
13998
  let accountId;
13951
13999
  try {
13952
14000
  accountId = resolvePlatformAccountId();
@@ -14149,7 +14197,7 @@ ${note}` : note;
14149
14197
  if (turnTimer.unref) turnTimer.unref();
14150
14198
  return c.json({ ok: true });
14151
14199
  });
14152
- app67.post("/interrupt", requireAdminSession, async (c) => {
14200
+ app68.post("/interrupt", requireAdminSession, async (c) => {
14153
14201
  const cacheKey = c.get("cacheKey");
14154
14202
  const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
14155
14203
  const primaryUserId = resolvePrimaryAdminUserId();
@@ -14177,7 +14225,7 @@ ${note}` : note;
14177
14225
  }
14178
14226
  return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
14179
14227
  });
14180
- app67.post("/settings", requireAdminSession, async (c) => {
14228
+ app68.post("/settings", requireAdminSession, async (c) => {
14181
14229
  const body = await c.req.json().catch(() => null);
14182
14230
  const op = body?.op;
14183
14231
  const value = body?.value;
@@ -14217,7 +14265,7 @@ ${note}` : note;
14217
14265
  console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
14218
14266
  return c.json({ ok: true, settingsApplied });
14219
14267
  });
14220
- app67.get("/session", requireAdminSession, async (c) => {
14268
+ app68.get("/session", requireAdminSession, async (c) => {
14221
14269
  let accountId;
14222
14270
  try {
14223
14271
  accountId = resolvePlatformAccountId();
@@ -14280,8 +14328,8 @@ ${note}` : note;
14280
14328
  let projectDir = null;
14281
14329
  if (cfg) {
14282
14330
  for (const { path: path3 } of enumerateJsonls(join25(cfg, "projects"))) {
14283
- if (basename7(path3) === `${sessionId}.jsonl`) {
14284
- projectDir = dirname8(path3);
14331
+ if (basename8(path3) === `${sessionId}.jsonl`) {
14332
+ projectDir = dirname9(path3);
14285
14333
  break;
14286
14334
  }
14287
14335
  }
@@ -14295,7 +14343,7 @@ ${note}` : note;
14295
14343
  const indicators = await fetchComposerIndicators(sessionId);
14296
14344
  return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
14297
14345
  });
14298
- app67.post("/permission-verdict", requireAdminSession, async (c) => {
14346
+ app68.post("/permission-verdict", requireAdminSession, async (c) => {
14299
14347
  const body = await c.req.json().catch(() => null);
14300
14348
  const sessionId = body?.sessionId;
14301
14349
  const requestId = body?.request_id;
@@ -14312,14 +14360,14 @@ ${note}` : note;
14312
14360
  const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
14313
14361
  return c.json({ ok });
14314
14362
  });
14315
- return app67;
14363
+ return app68;
14316
14364
  }
14317
14365
 
14318
14366
  // server/routes/webchat-greeting.ts
14319
- import { resolve as resolve17 } from "path";
14367
+ import { resolve as resolve18 } from "path";
14320
14368
 
14321
14369
  // app/lib/claude-agent/specialist-roster.ts
14322
- import { existsSync as existsSync19, readFileSync as readFileSync26, readdirSync as readdirSync18 } from "fs";
14370
+ import { existsSync as existsSync20, readFileSync as readFileSync26, readdirSync as readdirSync18 } from "fs";
14323
14371
  import { join as join26 } from "path";
14324
14372
  function field(fm, name) {
14325
14373
  const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
@@ -14331,7 +14379,7 @@ function field(fm, name) {
14331
14379
  return value || null;
14332
14380
  }
14333
14381
  function readSpecialistRoster(specialistsDir) {
14334
- if (!existsSync19(specialistsDir)) return { specialists: [], skipped: [] };
14382
+ if (!existsSync20(specialistsDir)) return { specialists: [], skipped: [] };
14335
14383
  const entries = readdirSync18(specialistsDir);
14336
14384
  const specialists = [];
14337
14385
  const skipped = [];
@@ -14421,7 +14469,7 @@ app7.get("/", requireAdminSession, async (c) => {
14421
14469
  let specialists = [];
14422
14470
  try {
14423
14471
  const roster = readSpecialistRoster(
14424
- resolve17(ACCOUNTS_DIR, accountId, "specialists", "agents")
14472
+ resolve18(ACCOUNTS_DIR, accountId, "specialists", "agents")
14425
14473
  );
14426
14474
  specialists = roster.specialists;
14427
14475
  for (const s of roster.skipped) {
@@ -14456,8 +14504,8 @@ var webchat_greeting_default = app7;
14456
14504
 
14457
14505
  // server/routes/telegram.ts
14458
14506
  import { homedir as homedir2 } from "os";
14459
- import { resolve as resolve18, join as join27 } from "path";
14460
- import { existsSync as existsSync20, readFileSync as readFileSync27 } from "fs";
14507
+ import { resolve as resolve19, join as join27 } from "path";
14508
+ import { existsSync as existsSync21, readFileSync as readFileSync27 } from "fs";
14461
14509
 
14462
14510
  // app/lib/telegram/gateway/instance.ts
14463
14511
  var instance = null;
@@ -14515,9 +14563,9 @@ function routeTelegramUpdate(input) {
14515
14563
  // server/routes/telegram.ts
14516
14564
  var TAG29 = "[telegram-inbound]";
14517
14565
  function configDirName() {
14518
- const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
14566
+ const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
14519
14567
  const brandPath = join27(platformRoot5, "config", "brand.json");
14520
- if (existsSync20(brandPath)) {
14568
+ if (existsSync21(brandPath)) {
14521
14569
  try {
14522
14570
  return JSON.parse(readFileSync27(brandPath, "utf-8")).configDir ?? ".maxy";
14523
14571
  } catch {
@@ -14527,7 +14575,7 @@ function configDirName() {
14527
14575
  }
14528
14576
  function secretPath(botType) {
14529
14577
  const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
14530
- return resolve18(homedir2(), configDirName(), filename);
14578
+ return resolve19(homedir2(), configDirName(), filename);
14531
14579
  }
14532
14580
  var app8 = new Hono();
14533
14581
  app8.post("/", async (c) => {
@@ -14538,7 +14586,7 @@ app8.post("/", async (c) => {
14538
14586
  return c.json({ ok: false }, 400);
14539
14587
  }
14540
14588
  const sp = secretPath(botType);
14541
- if (!existsSync20(sp)) {
14589
+ if (!existsSync21(sp)) {
14542
14590
  console.error(`${TAG29} op=reject reason=no-secret-file botType=${botType}`);
14543
14591
  return c.json({ ok: false }, 401);
14544
14592
  }
@@ -14606,7 +14654,7 @@ var telegram_default = app8;
14606
14654
 
14607
14655
  // server/routes/quickbooks.ts
14608
14656
  import { join as join28 } from "path";
14609
- import { existsSync as existsSync21, readFileSync as readFileSync28, writeFileSync as writeFileSync10, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
14657
+ import { existsSync as existsSync22, readFileSync as readFileSync28, writeFileSync as writeFileSync10, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
14610
14658
  var TAG30 = "[quickbooks]";
14611
14659
  var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
14612
14660
  var STATE_RE = /^[A-Za-z0-9_-]+$/;
@@ -14619,7 +14667,7 @@ function storePath(accountDir) {
14619
14667
  async function completeConsent(args) {
14620
14668
  const { accountDir, code, realmId } = args;
14621
14669
  const state = args.state;
14622
- if (!state || !STATE_RE.test(state) || !existsSync21(pendingPath(accountDir, state))) {
14670
+ if (!state || !STATE_RE.test(state) || !existsSync22(pendingPath(accountDir, state))) {
14623
14671
  console.error(`${TAG30} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
14624
14672
  return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
14625
14673
  }
@@ -14646,7 +14694,7 @@ async function completeConsent(args) {
14646
14694
  if (!code || !realmId) {
14647
14695
  return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
14648
14696
  }
14649
- if (!existsSync21(storePath(accountDir))) {
14697
+ if (!existsSync22(storePath(accountDir))) {
14650
14698
  return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
14651
14699
  }
14652
14700
  const store2 = JSON.parse(readFileSync28(storePath(accountDir), "utf-8"));
@@ -14714,7 +14762,7 @@ var quickbooks_default = app9;
14714
14762
 
14715
14763
  // server/routes/onboarding.ts
14716
14764
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync4 } from "child_process";
14717
- import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync23, readFileSync as readFileSync30, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
14765
+ import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync24, readFileSync as readFileSync30, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
14718
14766
  import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
14719
14767
 
14720
14768
  // app/lib/claude-spawn-env.ts
@@ -14723,7 +14771,7 @@ function claudeBin() {
14723
14771
  }
14724
14772
 
14725
14773
  // server/routes/onboarding.ts
14726
- import { dirname as dirname10, join as join30 } from "path";
14774
+ import { dirname as dirname11, join as join30 } from "path";
14727
14775
 
14728
14776
  // app/lib/claude-keychain.ts
14729
14777
  import { execFileSync as execFileSync3 } from "child_process";
@@ -14852,8 +14900,8 @@ function readHostCredsBlob(service) {
14852
14900
  }
14853
14901
 
14854
14902
  // ../lib/admins-write/src/index.ts
14855
- import { existsSync as existsSync22, readFileSync as readFileSync29, writeFileSync as writeFileSync11, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as statSync10, appendFileSync as appendFileSync3 } from "fs";
14856
- import { dirname as dirname9, join as join29 } from "path";
14903
+ import { existsSync as existsSync23, readFileSync as readFileSync29, writeFileSync as writeFileSync11, renameSync as renameSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync19, statSync as statSync11, appendFileSync as appendFileSync3 } from "fs";
14904
+ import { dirname as dirname10, join as join29 } from "path";
14857
14905
  function id8(value) {
14858
14906
  return value.slice(0, 8);
14859
14907
  }
@@ -14867,7 +14915,7 @@ function appendUsersAuditLine(audit, fields) {
14867
14915
  const line = `[users-audit] action=${fields.action} actor=${actor}${targetFields}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
14868
14916
  `;
14869
14917
  try {
14870
- mkdirSync6(dirname9(audit.logFile), { recursive: true, mode: 448 });
14918
+ mkdirSync6(dirname10(audit.logFile), { recursive: true, mode: 448 });
14871
14919
  appendFileSync3(audit.logFile, line, { mode: 384 });
14872
14920
  } catch (err) {
14873
14921
  console.error(
@@ -14885,7 +14933,7 @@ function logLine(input, result) {
14885
14933
  );
14886
14934
  }
14887
14935
  function writeFileAtomic(filePath, contents, mode) {
14888
- mkdirSync6(dirname9(filePath), { recursive: true });
14936
+ mkdirSync6(dirname10(filePath), { recursive: true });
14889
14937
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
14890
14938
  writeFileSync11(tempPath, contents, mode !== void 0 ? { mode } : void 0);
14891
14939
  renameSync6(tempPath, filePath);
@@ -14894,7 +14942,7 @@ function writeAdminEntry(input) {
14894
14942
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
14895
14943
  try {
14896
14944
  let users = [];
14897
- if (existsSync22(input.usersFile)) {
14945
+ if (existsSync23(input.usersFile)) {
14898
14946
  const raw = readFileSync29(input.usersFile, "utf-8").trim();
14899
14947
  if (raw) {
14900
14948
  const parsed = JSON.parse(raw);
@@ -14927,7 +14975,7 @@ function writeAdminEntry(input) {
14927
14975
  }
14928
14976
  try {
14929
14977
  const accountJsonPath = join29(input.accountDir, "account.json");
14930
- if (!existsSync22(accountJsonPath)) {
14978
+ if (!existsSync23(accountJsonPath)) {
14931
14979
  throw new Error(`account.json not found at ${accountJsonPath}`);
14932
14980
  }
14933
14981
  const config = JSON.parse(readFileSync29(accountJsonPath, "utf-8"));
@@ -14950,7 +14998,7 @@ function writeAdminEntry(input) {
14950
14998
  function computeAdminStoreDivergence(input) {
14951
14999
  const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
14952
15000
  const usersUserIds = /* @__PURE__ */ new Set();
14953
- if (existsSync22(input.usersFile)) {
15001
+ if (existsSync23(input.usersFile)) {
14954
15002
  try {
14955
15003
  const raw = readFileSync29(input.usersFile, "utf-8").trim();
14956
15004
  if (raw) {
@@ -14964,7 +15012,7 @@ function computeAdminStoreDivergence(input) {
14964
15012
  }
14965
15013
  }
14966
15014
  const accountUserIds = /* @__PURE__ */ new Set();
14967
- if (existsSync22(input.accountsDir)) {
15015
+ if (existsSync23(input.accountsDir)) {
14968
15016
  let entries;
14969
15017
  try {
14970
15018
  entries = readdirSync19(input.accountsDir);
@@ -14976,12 +15024,12 @@ function computeAdminStoreDivergence(input) {
14976
15024
  if (entry.startsWith(".")) continue;
14977
15025
  const accountDir = join29(input.accountsDir, entry);
14978
15026
  try {
14979
- if (!statSync10(accountDir).isDirectory()) continue;
15027
+ if (!statSync11(accountDir).isDirectory()) continue;
14980
15028
  } catch {
14981
15029
  continue;
14982
15030
  }
14983
15031
  const accountJsonPath = join29(accountDir, "account.json");
14984
- if (!existsSync22(accountJsonPath)) continue;
15032
+ if (!existsSync23(accountJsonPath)) continue;
14985
15033
  let admins = [];
14986
15034
  try {
14987
15035
  const config = JSON.parse(readFileSync29(accountJsonPath, "utf-8"));
@@ -15032,7 +15080,7 @@ function hashPin2(pin) {
15032
15080
  return createHash4("sha256").update(pin).digest("hex");
15033
15081
  }
15034
15082
  function readUsersFile2() {
15035
- if (!existsSync23(USERS_FILE)) return null;
15083
+ if (!existsSync24(USERS_FILE)) return null;
15036
15084
  const raw = readFileSync30(USERS_FILE, "utf-8").trim();
15037
15085
  if (!raw) return [];
15038
15086
  return JSON.parse(raw);
@@ -15092,7 +15140,7 @@ app10.post("/claude-auth", async (c) => {
15092
15140
  } catch (err) {
15093
15141
  logoutError = err instanceof Error ? err.message : String(err);
15094
15142
  }
15095
- const credentialsPresent = existsSync23(CLAUDE_CREDENTIALS_FILE);
15143
+ const credentialsPresent = existsSync24(CLAUDE_CREDENTIALS_FILE);
15096
15144
  const ranMs = Date.now() - start;
15097
15145
  console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
15098
15146
  return c.json({ logged_out: !credentialsPresent });
@@ -15158,7 +15206,7 @@ app10.post("/claude-auth", async (c) => {
15158
15206
  });
15159
15207
  persistKeychainService(
15160
15208
  writebackResult,
15161
- (service) => writeFileSync12(join30(dirname10(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
15209
+ (service) => writeFileSync12(join30(dirname11(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
15162
15210
  (line) => console.log(line)
15163
15211
  );
15164
15212
  if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
@@ -15241,7 +15289,7 @@ app10.post("/set-pin", async (c) => {
15241
15289
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
15242
15290
  if (process.platform === "linux") {
15243
15291
  let installOwner = null;
15244
- if (existsSync23(INSTALL_OWNER_FILE)) {
15292
+ if (existsSync24(INSTALL_OWNER_FILE)) {
15245
15293
  try {
15246
15294
  const raw = readFileSync30(INSTALL_OWNER_FILE, "utf-8").trim();
15247
15295
  if (raw.length > 0) installOwner = raw;
@@ -15389,7 +15437,7 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
15389
15437
  console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
15390
15438
  if (process.platform === "linux") {
15391
15439
  let installOwner = null;
15392
- if (existsSync23(INSTALL_OWNER_FILE)) {
15440
+ if (existsSync24(INSTALL_OWNER_FILE)) {
15393
15441
  try {
15394
15442
  const raw = readFileSync30(INSTALL_OWNER_FILE, "utf-8").trim();
15395
15443
  if (raw.length > 0) installOwner = raw;
@@ -15423,7 +15471,7 @@ ${body.newPin}
15423
15471
  var onboarding_default = app10;
15424
15472
 
15425
15473
  // server/routes/client-error.ts
15426
- import { appendFileSync as appendFileSync4, existsSync as existsSync24, renameSync as renameSync8, statSync as statSync11 } from "fs";
15474
+ import { appendFileSync as appendFileSync4, existsSync as existsSync25, renameSync as renameSync8, statSync as statSync12 } from "fs";
15427
15475
  import { join as join31 } from "path";
15428
15476
  var CLIENT_ERRORS_LOG = join31(LOG_DIR, "client-errors.log");
15429
15477
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
@@ -15482,8 +15530,8 @@ function stackHead(stack) {
15482
15530
  }
15483
15531
  function rotateIfNeeded() {
15484
15532
  try {
15485
- if (!existsSync24(CLIENT_ERRORS_LOG)) return;
15486
- const stats = statSync11(CLIENT_ERRORS_LOG);
15533
+ if (!existsSync25(CLIENT_ERRORS_LOG)) return;
15534
+ const stats = statSync12(CLIENT_ERRORS_LOG);
15487
15535
  if (stats.size < MAX_LOG_SIZE) return;
15488
15536
  renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
15489
15537
  } catch (err) {
@@ -15668,15 +15716,15 @@ function operatorRoleFor(config, userId) {
15668
15716
  async function buildAccountOptionList(accounts, userId) {
15669
15717
  const houseAccount = accounts.find((a) => a.config.role === "house");
15670
15718
  console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
15671
- const resolve43 = async (a) => {
15719
+ const resolve44 = async (a) => {
15672
15720
  const businessName = await fetchAccountName(a.accountId) || void 0;
15673
15721
  return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
15674
15722
  };
15675
15723
  const houseOptions = await Promise.all(
15676
- accounts.filter((a) => a.config.role === "house").map(resolve43)
15724
+ accounts.filter((a) => a.config.role === "house").map(resolve44)
15677
15725
  );
15678
15726
  const nonHouseOptions = await Promise.all(
15679
- accounts.filter((a) => a.config.role !== "house").map(resolve43)
15727
+ accounts.filter((a) => a.config.role !== "house").map(resolve44)
15680
15728
  );
15681
15729
  const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
15682
15730
  nonHouseOptions.sort((x, y) => {
@@ -15809,18 +15857,18 @@ app13.get("/", requireAdminSession, async (c) => {
15809
15857
  var accounts_default = app13;
15810
15858
 
15811
15859
  // server/routes/admin/logs.ts
15812
- import { existsSync as existsSync26, readdirSync as readdirSync20, readFileSync as readFileSync31, statSync as statSync12 } from "fs";
15813
- import { resolve as resolve19, basename as basename8 } from "path";
15860
+ import { existsSync as existsSync27, readdirSync as readdirSync20, readFileSync as readFileSync31, statSync as statSync13 } from "fs";
15861
+ import { resolve as resolve20, basename as basename9 } from "path";
15814
15862
 
15815
15863
  // app/lib/logs-read-resolve.ts
15816
- import { existsSync as existsSync25 } from "fs";
15864
+ import { existsSync as existsSync26 } from "fs";
15817
15865
  import { join as join32 } from "path";
15818
15866
  function resolveSessionLogPaths(filename, logDirs) {
15819
15867
  const tried = [filename];
15820
15868
  const hits = [];
15821
15869
  for (const dir of logDirs) {
15822
15870
  const fullPath = join32(dir, filename);
15823
- if (existsSync25(fullPath)) {
15871
+ if (existsSync26(fullPath)) {
15824
15872
  hits.push({ path: fullPath, dir });
15825
15873
  }
15826
15874
  }
@@ -15837,19 +15885,19 @@ app14.get("/", async (c) => {
15837
15885
  const cacheKeyParam = c.req.query("cacheKey");
15838
15886
  const download = c.req.query("download") === "1";
15839
15887
  const account = resolveAccount();
15840
- const accountLogDir = account ? resolve19(account.accountDir, "logs") : null;
15888
+ const accountLogDir = account ? resolve20(account.accountDir, "logs") : null;
15841
15889
  const logDirs = [];
15842
15890
  if (accountLogDir) logDirs.push(accountLogDir);
15843
15891
  logDirs.push(LOG_DIR);
15844
15892
  if (fileParam) {
15845
- const safe = basename8(fileParam);
15893
+ const safe = basename9(fileParam);
15846
15894
  const searched = [];
15847
15895
  for (const dir of logDirs) {
15848
- const filePath = resolve19(dir, safe);
15896
+ const filePath = resolve20(dir, safe);
15849
15897
  searched.push(filePath);
15850
15898
  try {
15851
15899
  const buffer = readFileSync31(filePath);
15852
- const onDiskBytes = statSync12(filePath).size;
15900
+ const onDiskBytes = statSync13(filePath).size;
15853
15901
  const headers = {
15854
15902
  "Content-Type": "text/plain; charset=utf-8",
15855
15903
  "Content-Length": String(buffer.byteLength)
@@ -15912,9 +15960,9 @@ app14.get("/", async (c) => {
15912
15960
  if (hit) {
15913
15961
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
15914
15962
  try {
15915
- const filename = basename8(hit.path);
15963
+ const filename = basename9(hit.path);
15916
15964
  const buffer = readFileSync31(hit.path);
15917
- const onDiskBytes = statSync12(hit.path).size;
15965
+ const onDiskBytes = statSync13(hit.path).size;
15918
15966
  const headers = {
15919
15967
  "Content-Type": "text/plain; charset=utf-8",
15920
15968
  "Content-Length": String(buffer.byteLength)
@@ -15948,7 +15996,7 @@ app14.get("/", async (c) => {
15948
15996
  const seen = /* @__PURE__ */ new Set();
15949
15997
  const logs = {};
15950
15998
  for (const dir of logDirs) {
15951
- if (!existsSync26(dir)) continue;
15999
+ if (!existsSync27(dir)) continue;
15952
16000
  let files;
15953
16001
  try {
15954
16002
  files = readdirSync20(dir).filter((f) => f.endsWith(".log"));
@@ -15957,10 +16005,10 @@ app14.get("/", async (c) => {
15957
16005
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
15958
16006
  continue;
15959
16007
  }
15960
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync12(resolve19(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
16008
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync13(resolve20(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
15961
16009
  seen.add(name);
15962
16010
  try {
15963
- const content = readFileSync31(resolve19(dir, name));
16011
+ const content = readFileSync31(resolve20(dir, name));
15964
16012
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
15965
16013
  logs[name] = tail.trim() || "(empty)";
15966
16014
  } catch (err) {
@@ -16000,12 +16048,12 @@ var claude_info_default = app15;
16000
16048
 
16001
16049
  // server/routes/admin/attachment.ts
16002
16050
  import { readFile as readFile4, readdir as readdir2 } from "fs/promises";
16003
- import { existsSync as existsSync27 } from "fs";
16004
- import { resolve as resolve20 } from "path";
16051
+ import { existsSync as existsSync28 } from "fs";
16052
+ import { resolve as resolve21 } from "path";
16005
16053
  var app16 = new Hono();
16006
16054
  var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
16007
16055
  function uploadsDirFor2(accountId, attachmentId) {
16008
- return resolve20(DATA_ROOT, "accounts", accountId, "uploads", attachmentId);
16056
+ return resolve21(DATA_ROOT, "accounts", accountId, "uploads", attachmentId);
16009
16057
  }
16010
16058
  app16.get("/:attachmentId", requireAdminSession, async (c) => {
16011
16059
  const attachmentId = c.req.param("attachmentId");
@@ -16023,12 +16071,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
16023
16071
  }
16024
16072
  let accountId = pinnedAccountId;
16025
16073
  let dir = uploadsDirFor2(accountId, attachmentId);
16026
- let found = existsSync27(dir);
16074
+ let found = existsSync28(dir);
16027
16075
  if (!found) {
16028
16076
  for (const candidate of listValidAccounts()) {
16029
16077
  if (candidate.accountId === pinnedAccountId) continue;
16030
16078
  const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
16031
- if (existsSync27(candidateDir)) {
16079
+ if (existsSync28(candidateDir)) {
16032
16080
  accountId = candidate.accountId;
16033
16081
  dir = candidateDir;
16034
16082
  found = true;
@@ -16042,8 +16090,8 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
16042
16090
  if (!found) {
16043
16091
  return new Response("Not found", { status: 404 });
16044
16092
  }
16045
- const metaPath = resolve20(dir, `${attachmentId}.meta.json`);
16046
- if (!existsSync27(metaPath)) {
16093
+ const metaPath = resolve21(dir, `${attachmentId}.meta.json`);
16094
+ if (!existsSync28(metaPath)) {
16047
16095
  return new Response("Not found", { status: 404 });
16048
16096
  }
16049
16097
  let meta;
@@ -16057,7 +16105,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
16057
16105
  if (!dataFile) {
16058
16106
  return new Response("Not found", { status: 404 });
16059
16107
  }
16060
- const filePath = resolve20(dir, dataFile);
16108
+ const filePath = resolve21(dir, dataFile);
16061
16109
  const buffer = await readFile4(filePath);
16062
16110
  const inlineSafe = isInlineSafeMime(meta.mimeType);
16063
16111
  const safeName = meta.filename.replace(/["\\\r\n]/g, "_");
@@ -16075,23 +16123,66 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
16075
16123
  });
16076
16124
  var attachment_default = app16;
16077
16125
 
16078
- // server/routes/admin/agents.ts
16079
- import { resolve as resolve21 } from "path";
16080
- import { readdirSync as readdirSync21, readFileSync as readFileSync32, existsSync as existsSync28, rmSync as rmSync2 } from "fs";
16126
+ // server/routes/admin/session-upload.ts
16127
+ import { readFile as readFile5 } from "fs/promises";
16128
+ import { existsSync as existsSync29, statSync as statSync14 } from "fs";
16081
16129
  var app17 = new Hono();
16082
- app17.get("/", (c) => {
16130
+ app17.get("/", requireAdminSession, async (c) => {
16131
+ const cacheKey = c.var.cacheKey;
16132
+ const sessionId = c.req.query("session_id") ?? "";
16133
+ const file = c.req.query("file") ?? "";
16134
+ const short2 = sessionId.slice(0, 8);
16135
+ if (!SESSION_ID_RE2.test(sessionId) || !file || file.includes("/") || file.includes("\\") || file.includes("..")) {
16136
+ console.log(`[session-upload] op=miss session=${short2} status=400 reason=bad-param`);
16137
+ return c.json({ error: "bad request" }, 400);
16138
+ }
16139
+ const accountId = getAccountIdForSession(cacheKey);
16140
+ if (!accountId) {
16141
+ console.log(`[session-upload] op=miss session=${short2} status=401 reason=no-account`);
16142
+ return c.json({ error: "Unauthorized" }, 401);
16143
+ }
16144
+ if (await verifyAndGetConversationUpdatedAt(sessionId, accountId) === null) {
16145
+ console.log(`[session-upload] op=miss session=${short2} status=404 reason=not-owned account=${accountId.slice(0, 8)}`);
16146
+ return c.json({ error: "Not found" }, 404);
16147
+ }
16148
+ const resolution = resolveClaudeUploadsPath(`${sessionId}/${file}`);
16149
+ if (!resolution.ok || !existsSync29(resolution.absolute) || !statSync14(resolution.absolute).isFile()) {
16150
+ console.log(`[session-upload] op=miss session=${short2} file=${file} status=404 reason=absent`);
16151
+ return c.json({ error: "Not found" }, 404);
16152
+ }
16153
+ const mimeType = detectMimeType(file);
16154
+ const inlineSafe = isInlineSafeMime(mimeType);
16155
+ const safeName = file.replace(/["\\\r\n]/g, "_");
16156
+ console.log(`[session-upload] op=served session=${short2} file=${file} disposition=${inlineSafe ? "inline" : "attachment"} mime=${mimeType}`);
16157
+ const buffer = await readFile5(resolution.absolute);
16158
+ return new Response(new Uint8Array(buffer), {
16159
+ headers: {
16160
+ "Content-Type": mimeType,
16161
+ "Content-Disposition": `${inlineSafe ? "inline" : "attachment"}; filename="${safeName}"`,
16162
+ "X-Content-Type-Options": "nosniff",
16163
+ "Cache-Control": "private, max-age=3600"
16164
+ }
16165
+ });
16166
+ });
16167
+ var session_upload_default = app17;
16168
+
16169
+ // server/routes/admin/agents.ts
16170
+ import { resolve as resolve22 } from "path";
16171
+ import { readdirSync as readdirSync21, readFileSync as readFileSync32, existsSync as existsSync30, rmSync as rmSync2 } from "fs";
16172
+ var app18 = new Hono();
16173
+ app18.get("/", (c) => {
16083
16174
  const account = resolveAccount();
16084
16175
  if (!account) return c.json({ agents: [] });
16085
- const agentsDir = resolve21(account.accountDir, "agents");
16086
- if (!existsSync28(agentsDir)) return c.json({ agents: [] });
16176
+ const agentsDir = resolve22(account.accountDir, "agents");
16177
+ if (!existsSync30(agentsDir)) return c.json({ agents: [] });
16087
16178
  const agents = [];
16088
16179
  try {
16089
16180
  const entries = readdirSync21(agentsDir, { withFileTypes: true });
16090
16181
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
16091
16182
  if (!entry.isDirectory()) continue;
16092
16183
  if (entry.name === "admin") continue;
16093
- const configPath2 = resolve21(agentsDir, entry.name, "config.json");
16094
- if (!existsSync28(configPath2)) continue;
16184
+ const configPath2 = resolve22(agentsDir, entry.name, "config.json");
16185
+ if (!existsSync30(configPath2)) continue;
16095
16186
  try {
16096
16187
  const config = JSON.parse(readFileSync32(configPath2, "utf-8"));
16097
16188
  agents.push({
@@ -16109,7 +16200,7 @@ app17.get("/", (c) => {
16109
16200
  }
16110
16201
  return c.json({ agents });
16111
16202
  });
16112
- app17.delete("/:slug", async (c) => {
16203
+ app18.delete("/:slug", async (c) => {
16113
16204
  const slug = c.req.param("slug");
16114
16205
  const account = resolveAccount();
16115
16206
  if (!account) return c.json({ error: "No account resolved" }, 400);
@@ -16119,8 +16210,8 @@ app17.delete("/:slug", async (c) => {
16119
16210
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
16120
16211
  return c.json({ error: "Invalid agent slug" }, 400);
16121
16212
  }
16122
- const agentDir = resolve21(account.accountDir, "agents", slug);
16123
- if (!existsSync28(agentDir)) {
16213
+ const agentDir = resolve22(account.accountDir, "agents", slug);
16214
+ if (!existsSync30(agentDir)) {
16124
16215
  return c.json({ error: "Agent not found" }, 404);
16125
16216
  }
16126
16217
  try {
@@ -16139,7 +16230,7 @@ app17.delete("/:slug", async (c) => {
16139
16230
  return c.json({ error: "Failed to delete agent" }, 500);
16140
16231
  }
16141
16232
  });
16142
- app17.post("/:slug/project", async (c) => {
16233
+ app18.post("/:slug/project", async (c) => {
16143
16234
  const slug = c.req.param("slug");
16144
16235
  const account = resolveAccount();
16145
16236
  if (!account) return c.json({ error: "No account resolved" }, 400);
@@ -16149,8 +16240,8 @@ app17.post("/:slug/project", async (c) => {
16149
16240
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
16150
16241
  return c.json({ error: "Invalid agent slug" }, 400);
16151
16242
  }
16152
- const agentDir = resolve21(account.accountDir, "agents", slug);
16153
- if (!existsSync28(agentDir)) {
16243
+ const agentDir = resolve22(account.accountDir, "agents", slug);
16244
+ if (!existsSync30(agentDir)) {
16154
16245
  return c.json({ error: "Agent not found on disk" }, 404);
16155
16246
  }
16156
16247
  try {
@@ -16161,12 +16252,12 @@ app17.post("/:slug/project", async (c) => {
16161
16252
  return c.json({ error: `Projection failed: ${msg}` }, 500);
16162
16253
  }
16163
16254
  });
16164
- var agents_default = app17;
16255
+ var agents_default = app18;
16165
16256
 
16166
16257
  // server/routes/admin/sessions.ts
16167
16258
  import crypto2 from "crypto";
16168
16259
  import { resolve as resolvePath } from "path";
16169
- import { existsSync as existsSync29, mkdirSync as mkdirSync7, createWriteStream } from "fs";
16260
+ import { existsSync as existsSync31, mkdirSync as mkdirSync7, createWriteStream } from "fs";
16170
16261
 
16171
16262
  // ../lib/admin-conversation-purge/src/index.ts
16172
16263
  async function purgeAdminConversationJsonls(args) {
@@ -16326,7 +16417,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
16326
16417
  let reason = null;
16327
16418
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
16328
16419
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
16329
- else if (!existsSync29(a.storagePath)) reason = "missing-file";
16420
+ else if (!existsSync31(a.storagePath)) reason = "missing-file";
16330
16421
  if (reason) {
16331
16422
  invalid++;
16332
16423
  try {
@@ -16433,8 +16524,8 @@ function formatAge(updatedAtStr) {
16433
16524
  return "unknown";
16434
16525
  }
16435
16526
  }
16436
- var app18 = new Hono();
16437
- app18.get("/", requireAdminSession, async (c) => {
16527
+ var app19 = new Hono();
16528
+ app19.get("/", requireAdminSession, async (c) => {
16438
16529
  const cacheKey = c.var.cacheKey;
16439
16530
  const accountId = getAccountIdForSession(cacheKey);
16440
16531
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -16464,7 +16555,7 @@ app18.get("/", requireAdminSession, async (c) => {
16464
16555
  return c.json({ error: "Failed to fetch sessions" }, 500);
16465
16556
  }
16466
16557
  });
16467
- app18.post("/new", requireAdminSession, async (c) => {
16558
+ app19.post("/new", requireAdminSession, async (c) => {
16468
16559
  const oldCacheKey = c.var.cacheKey;
16469
16560
  console.log(`[admin-chat] new-conversation outcome=ingress cacheKey=${oldCacheKey.slice(0, 8)}`);
16470
16561
  const accountId = getAccountIdForSession(oldCacheKey);
@@ -16481,7 +16572,7 @@ app18.post("/new", requireAdminSession, async (c) => {
16481
16572
  console.log(`[admin-chat] new-conversation outcome=ok oldKey=${oldCacheKey.slice(0, 8)} newKey=${newCacheKey.slice(0, 8)}`);
16482
16573
  return c.json({ session_key: newSignedSessionToken, sessionId: null });
16483
16574
  });
16484
- app18.post("/switch", requireAdminSession, async (c) => {
16575
+ app19.post("/switch", requireAdminSession, async (c) => {
16485
16576
  const cacheKey = c.var.cacheKey;
16486
16577
  const accountId = getAccountIdForSession(cacheKey);
16487
16578
  const userId = getUserIdForSession(cacheKey);
@@ -16509,7 +16600,7 @@ app18.post("/switch", requireAdminSession, async (c) => {
16509
16600
  console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetSessionId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
16510
16601
  return c.json({ session_key: targetSignedSessionToken, sessionId: targetSessionId });
16511
16602
  });
16512
- app18.delete("/:id", requireAdminSession, async (c) => {
16603
+ app19.delete("/:id", requireAdminSession, async (c) => {
16513
16604
  const sessionId = c.req.param("id");
16514
16605
  const cacheKey = c.var.cacheKey;
16515
16606
  const accountId = getAccountIdForSession(cacheKey);
@@ -16554,7 +16645,7 @@ app18.delete("/:id", requireAdminSession, async (c) => {
16554
16645
  500
16555
16646
  );
16556
16647
  });
16557
- app18.post("/:id/resume", async (c) => {
16648
+ app19.post("/:id/resume", async (c) => {
16558
16649
  const sessionId = c.req.param("id");
16559
16650
  const t0 = Date.now();
16560
16651
  const signedSessionToken = c.req.query("session_key") ?? "";
@@ -16823,7 +16914,7 @@ app18.post("/:id/resume", async (c) => {
16823
16914
  }
16824
16915
  });
16825
16916
  });
16826
- app18.put("/:id/label", requireAdminSession, async (c) => {
16917
+ app19.put("/:id/label", requireAdminSession, async (c) => {
16827
16918
  const sessionId = c.req.param("id");
16828
16919
  const cacheKey = c.var.cacheKey;
16829
16920
  let body;
@@ -16849,11 +16940,11 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
16849
16940
  return c.json({ error: "Failed to rename session" }, 500);
16850
16941
  }
16851
16942
  });
16852
- var sessions_default = app18;
16943
+ var sessions_default = app19;
16853
16944
 
16854
16945
  // app/lib/claude-agent/spawn-context.ts
16855
- import { existsSync as existsSync30, readFileSync as readFileSync33, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
16856
- import { dirname as dirname11, resolve as resolve22, join as join33 } from "path";
16946
+ import { existsSync as existsSync32, readFileSync as readFileSync33, readdirSync as readdirSync22, statSync as statSync15 } from "fs";
16947
+ import { dirname as dirname12, resolve as resolve23, join as join33 } from "path";
16857
16948
  async function resolveOwnerProfileBlock(accountId, userId) {
16858
16949
  if (!userId) return { ok: false, reason: "missing-user-id" };
16859
16950
  try {
@@ -16899,7 +16990,7 @@ function extractPluginToolDescriptions(pluginDir) {
16899
16990
  ];
16900
16991
  let raw = null;
16901
16992
  for (const path3 of candidates) {
16902
- if (!existsSync30(path3)) continue;
16993
+ if (!existsSync32(path3)) continue;
16903
16994
  try {
16904
16995
  raw = readFileSync33(path3, "utf-8");
16905
16996
  break;
@@ -16950,26 +17041,26 @@ function parseSkillPathsFromFrontmatter(fm) {
16950
17041
  }
16951
17042
  function listPluginDirs(accountPluginsDir) {
16952
17043
  const out = /* @__PURE__ */ new Map();
16953
- const platformPlugins = resolve22(PLATFORM_ROOT, "plugins");
16954
- if (existsSync30(platformPlugins)) {
17044
+ const platformPlugins = resolve23(PLATFORM_ROOT, "plugins");
17045
+ if (existsSync32(platformPlugins)) {
16955
17046
  for (const name of readdirSync22(platformPlugins)) {
16956
17047
  const dir = join33(platformPlugins, name);
16957
17048
  try {
16958
- if (statSync13(dir).isDirectory()) out.set(name, dir);
17049
+ if (statSync15(dir).isDirectory()) out.set(name, dir);
16959
17050
  } catch {
16960
17051
  }
16961
17052
  }
16962
17053
  }
16963
- const premiumRoot = resolve22(dirname11(PLATFORM_ROOT), "premium-plugins");
16964
- if (existsSync30(premiumRoot)) {
17054
+ const premiumRoot = resolve23(dirname12(PLATFORM_ROOT), "premium-plugins");
17055
+ if (existsSync32(premiumRoot)) {
16965
17056
  for (const bundle of readdirSync22(premiumRoot)) {
16966
17057
  const bundlePlugins = join33(premiumRoot, bundle, "plugins");
16967
- if (!existsSync30(bundlePlugins)) continue;
17058
+ if (!existsSync32(bundlePlugins)) continue;
16968
17059
  try {
16969
17060
  for (const name of readdirSync22(bundlePlugins)) {
16970
17061
  const dir = join33(bundlePlugins, name);
16971
17062
  try {
16972
- if (statSync13(dir).isDirectory()) out.set(name, dir);
17063
+ if (statSync15(dir).isDirectory()) out.set(name, dir);
16973
17064
  } catch {
16974
17065
  }
16975
17066
  }
@@ -16977,13 +17068,13 @@ function listPluginDirs(accountPluginsDir) {
16977
17068
  }
16978
17069
  }
16979
17070
  }
16980
- if (accountPluginsDir && existsSync30(accountPluginsDir)) {
17071
+ if (accountPluginsDir && existsSync32(accountPluginsDir)) {
16981
17072
  try {
16982
17073
  for (const name of readdirSync22(accountPluginsDir)) {
16983
17074
  if (out.has(name)) continue;
16984
17075
  const dir = join33(accountPluginsDir, name);
16985
17076
  try {
16986
- if (statSync13(dir).isDirectory()) out.set(name, dir);
17077
+ if (statSync15(dir).isDirectory()) out.set(name, dir);
16987
17078
  } catch {
16988
17079
  }
16989
17080
  }
@@ -16993,14 +17084,14 @@ function listPluginDirs(accountPluginsDir) {
16993
17084
  return out;
16994
17085
  }
16995
17086
  function accountPluginsDirFor(accountId) {
16996
- return resolve22(PLATFORM_ROOT, "..", "data/accounts", accountId, "plugins");
17087
+ return resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "plugins");
16997
17088
  }
16998
17089
  function listAccountPluginNames(accountPluginsDir) {
16999
- if (!existsSync30(accountPluginsDir)) return [];
17090
+ if (!existsSync32(accountPluginsDir)) return [];
17000
17091
  try {
17001
17092
  return readdirSync22(accountPluginsDir).filter((name) => {
17002
17093
  try {
17003
- return statSync13(join33(accountPluginsDir, name)).isDirectory();
17094
+ return statSync15(join33(accountPluginsDir, name)).isDirectory();
17004
17095
  } catch {
17005
17096
  return false;
17006
17097
  }
@@ -17010,8 +17101,8 @@ function listAccountPluginNames(accountPluginsDir) {
17010
17101
  }
17011
17102
  }
17012
17103
  function readEnabledPlugins(accountId) {
17013
- const accountFile = resolve22(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
17014
- if (!existsSync30(accountFile)) return /* @__PURE__ */ new Set();
17104
+ const accountFile = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
17105
+ if (!existsSync32(accountFile)) return /* @__PURE__ */ new Set();
17015
17106
  try {
17016
17107
  const parsed = JSON.parse(readFileSync33(accountFile, "utf-8"));
17017
17108
  return new Set(
@@ -17022,7 +17113,7 @@ function readEnabledPlugins(accountId) {
17022
17113
  }
17023
17114
  }
17024
17115
  function readFrontmatter(path3) {
17025
- if (!existsSync30(path3)) return null;
17116
+ if (!existsSync32(path3)) return null;
17026
17117
  let raw;
17027
17118
  try {
17028
17119
  raw = readFileSync33(path3, "utf-8");
@@ -17060,7 +17151,7 @@ ${fm}
17060
17151
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
17061
17152
  );
17062
17153
  if (toolNames.length > 0 && descMap.size === 0) {
17063
- const hasSource = existsSync30(join33(dir, "mcp/dist/index.js")) || existsSync30(join33(dir, "mcp/src/index.ts"));
17154
+ const hasSource = existsSync32(join33(dir, "mcp/dist/index.js")) || existsSync32(join33(dir, "mcp/src/index.ts"));
17064
17155
  if (hasSource) {
17065
17156
  console.warn(
17066
17157
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -17086,8 +17177,8 @@ ${skillFm}
17086
17177
  return out;
17087
17178
  }
17088
17179
  function computeSpecialistDomains(accountId) {
17089
- const specialistsDir = resolve22(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
17090
- if (!existsSync30(specialistsDir)) return [];
17180
+ const specialistsDir = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
17181
+ if (!existsSync32(specialistsDir)) return [];
17091
17182
  let entries;
17092
17183
  try {
17093
17184
  entries = readdirSync22(specialistsDir);
@@ -17099,10 +17190,10 @@ function computeSpecialistDomains(accountId) {
17099
17190
  const resolveDesc = (qualified) => {
17100
17191
  if (!qualified.startsWith("mcp__")) return void 0;
17101
17192
  const rest = qualified.slice(5);
17102
- const sep11 = rest.indexOf("__");
17103
- if (sep11 < 0) return void 0;
17104
- const plugin = rest.slice(0, sep11);
17105
- const tool = rest.slice(sep11 + 2);
17193
+ const sep12 = rest.indexOf("__");
17194
+ if (sep12 < 0) return void 0;
17195
+ const plugin = rest.slice(0, sep12);
17196
+ const tool = rest.slice(sep12 + 2);
17106
17197
  let map = descByPlugin.get(plugin);
17107
17198
  if (!map) {
17108
17199
  const dir = pluginDirs.get(plugin);
@@ -17132,8 +17223,8 @@ ${fm}
17132
17223
  return out;
17133
17224
  }
17134
17225
  function computeDormantPlugins(accountId) {
17135
- const accountFile = resolve22(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
17136
- if (!existsSync30(accountFile)) return [];
17226
+ const accountFile = resolve23(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
17227
+ if (!existsSync32(accountFile)) return [];
17137
17228
  let enabled;
17138
17229
  try {
17139
17230
  const raw = readFileSync33(accountFile, "utf-8");
@@ -17147,8 +17238,8 @@ function computeDormantPlugins(accountId) {
17147
17238
  );
17148
17239
  return [];
17149
17240
  }
17150
- const pluginsDir = resolve22(PLATFORM_ROOT, "plugins");
17151
- if (!existsSync30(pluginsDir)) return [];
17241
+ const pluginsDir = resolve23(PLATFORM_ROOT, "plugins");
17242
+ if (!existsSync32(pluginsDir)) return [];
17152
17243
  let entries;
17153
17244
  try {
17154
17245
  entries = readdirSync22(pluginsDir);
@@ -17158,8 +17249,8 @@ function computeDormantPlugins(accountId) {
17158
17249
  const out = [];
17159
17250
  for (const name of entries) {
17160
17251
  if (enabled.has(name)) continue;
17161
- const manifestPath = resolve22(pluginsDir, name, "PLUGIN.md");
17162
- if (!existsSync30(manifestPath)) continue;
17252
+ const manifestPath = resolve23(pluginsDir, name, "PLUGIN.md");
17253
+ if (!existsSync32(manifestPath)) continue;
17163
17254
  let manifest;
17164
17255
  try {
17165
17256
  manifest = readFileSync33(manifestPath, "utf-8");
@@ -17176,11 +17267,11 @@ function computeDormantPlugins(accountId) {
17176
17267
  }
17177
17268
 
17178
17269
  // server/routes/admin/claude-sessions.ts
17179
- import { existsSync as existsSync31, readFileSync as readFileSync34 } from "fs";
17180
- import { resolve as resolve23 } from "path";
17270
+ import { existsSync as existsSync33, readFileSync as readFileSync34 } from "fs";
17271
+ import { resolve as resolve24 } from "path";
17181
17272
  function readTunnelState(brandConfigDir) {
17182
17273
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
17183
- if (!existsSync31(statePath)) return null;
17274
+ if (!existsSync33(statePath)) return null;
17184
17275
  try {
17185
17276
  const parsed = JSON.parse(readFileSync34(statePath, "utf-8"));
17186
17277
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
@@ -17193,10 +17284,10 @@ function readTunnelState(brandConfigDir) {
17193
17284
  }
17194
17285
  }
17195
17286
  function resolveTunnelUrl() {
17196
- const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
17287
+ const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
17197
17288
  let brand;
17198
17289
  try {
17199
- brand = JSON.parse(readFileSync34(resolve23(platformRoot5, "config", "brand.json"), "utf-8"));
17290
+ brand = JSON.parse(readFileSync34(resolve24(platformRoot5, "config", "brand.json"), "utf-8"));
17200
17291
  } catch {
17201
17292
  return null;
17202
17293
  }
@@ -17219,7 +17310,7 @@ async function refuseIfClaudeAuthDead(c, route, sessionId) {
17219
17310
  503
17220
17311
  );
17221
17312
  }
17222
- var app19 = new Hono();
17313
+ var app20 = new Hono();
17223
17314
  async function performSpawnWithInitialMessage(args) {
17224
17315
  const ownerStart = Date.now();
17225
17316
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
@@ -17296,8 +17387,8 @@ function mintTranscriptEdge(sessionId, claudeSessionId, accountId) {
17296
17387
  if (!sessionId || !claudeSessionId) return;
17297
17388
  void linkConversationTranscript(sessionId, claudeSessionId, accountId);
17298
17389
  }
17299
- app19.use("*", requireAdminSession);
17300
- app19.post("/", async (c) => {
17390
+ app20.use("*", requireAdminSession);
17391
+ app20.post("/", async (c) => {
17301
17392
  const routeStart = Date.now();
17302
17393
  const cacheKey = c.get("cacheKey") ?? "";
17303
17394
  let body = {};
@@ -17340,18 +17431,18 @@ app19.post("/", async (c) => {
17340
17431
  console.log(`${TAG31} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
17341
17432
  return response;
17342
17433
  });
17343
- var claude_sessions_default = app19;
17434
+ var claude_sessions_default = app20;
17344
17435
 
17345
17436
  // server/routes/admin/log-ingest.ts
17346
17437
  var TAG32 = "[log-ingest]";
17347
17438
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
17348
17439
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
17349
17440
  var MAX_LINE_BYTES = 4096;
17350
- var app20 = new Hono();
17441
+ var app21 = new Hono();
17351
17442
  function isLoopbackAddr2(addr) {
17352
17443
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
17353
17444
  }
17354
- app20.post("/", async (c) => {
17445
+ app21.post("/", async (c) => {
17355
17446
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17356
17447
  if (!isLoopbackAddr2(remoteAddr)) {
17357
17448
  console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -17394,7 +17485,7 @@ app20.post("/", async (c) => {
17394
17485
  else console.log(formatted);
17395
17486
  return c.json({ ok: true }, 200);
17396
17487
  });
17397
- var log_ingest_default = app20;
17488
+ var log_ingest_default = app21;
17398
17489
 
17399
17490
  // server/routes/admin/events.ts
17400
17491
  var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
@@ -17403,8 +17494,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
17403
17494
  "device-url:vnc-surface-shown",
17404
17495
  "device-url:malformed"
17405
17496
  ]);
17406
- var app21 = new Hono();
17407
- app21.post("/", async (c) => {
17497
+ var app22 = new Hono();
17498
+ app22.post("/", async (c) => {
17408
17499
  const TAG56 = "[admin:events]";
17409
17500
  let body;
17410
17501
  try {
@@ -17435,14 +17526,14 @@ app21.post("/", async (c) => {
17435
17526
  console.error(`[${event}] ${formatted}`);
17436
17527
  return c.json({ ok: true });
17437
17528
  });
17438
- var events_default = app21;
17529
+ var events_default = app22;
17439
17530
 
17440
17531
  // server/routes/admin/files.ts
17441
- import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync32 } from "fs";
17442
- import { readdir as readdir4, readFile as readFile6, stat as stat6, mkdir as mkdir4, unlink as unlink3, rename as rename2, rmdir } from "fs/promises";
17443
- import { realpathSync as realpathSync6 } from "fs";
17532
+ import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync34 } from "fs";
17533
+ import { readdir as readdir4, readFile as readFile7, stat as stat6, mkdir as mkdir4, unlink as unlink3, rename as rename2, rmdir } from "fs/promises";
17534
+ import { realpathSync as realpathSync7 } from "fs";
17444
17535
  import { randomUUID as randomUUID10 } from "crypto";
17445
- import { basename as basename10, dirname as dirname12, join as join35, relative as relative5, resolve as resolve25, sep as sep7 } from "path";
17536
+ import { basename as basename11, dirname as dirname13, join as join35, relative as relative5, resolve as resolve26, sep as sep8 } from "path";
17446
17537
  import { Readable as Readable2 } from "stream";
17447
17538
 
17448
17539
  // ../lib/graph-trash/src/index.ts
@@ -17760,7 +17851,7 @@ async function cascadeDeleteDocument(params) {
17760
17851
 
17761
17852
  // app/lib/file-index.ts
17762
17853
  import * as fsp from "fs/promises";
17763
- import { resolve as resolve24, relative as relative4, join as join34, basename as basename9, extname as extname2, sep as sep6 } from "path";
17854
+ import { resolve as resolve25, relative as relative4, join as join34, basename as basename10, extname as extname2, sep as sep7 } from "path";
17764
17855
  import { tmpdir as tmpdir2 } from "os";
17765
17856
  import { execFile as execFile2 } from "child_process";
17766
17857
  import { promisify as promisify2 } from "util";
@@ -17898,8 +17989,8 @@ async function extractFileContent(absolute) {
17898
17989
  }
17899
17990
  }
17900
17991
  async function readDisplayName(absolute) {
17901
- const dir = absolute.slice(0, absolute.length - basename9(absolute).length);
17902
- const base = basename9(absolute);
17992
+ const dir = absolute.slice(0, absolute.length - basename10(absolute).length);
17993
+ const base = basename10(absolute);
17903
17994
  const dot = base.lastIndexOf(".");
17904
17995
  const stem = dot === -1 ? base : base.slice(0, dot);
17905
17996
  if (base === `${stem}.meta.json`) return null;
@@ -17934,7 +18025,7 @@ async function walkSubtree(root, dataRoot, out) {
17934
18025
  const st = await fsp.stat(abs);
17935
18026
  out.push({
17936
18027
  absolute: abs,
17937
- relativePath: relative4(dataRoot, abs).split(sep6).join("/"),
18028
+ relativePath: relative4(dataRoot, abs).split(sep7).join("/"),
17938
18029
  sizeBytes: st.size,
17939
18030
  modifiedAt: st.mtime.toISOString()
17940
18031
  });
@@ -18037,7 +18128,7 @@ async function cascadeTrashLinkedKnowledgeDocs(session, accountId, relativePaths
18037
18128
  return { kds, sections, chunks };
18038
18129
  }
18039
18130
  async function buildArtifact(accountId, wf, embed2) {
18040
- const name = basename9(wf.absolute);
18131
+ const name = basename10(wf.absolute);
18041
18132
  const { content, route } = await extractFileContent(wf.absolute);
18042
18133
  const displayName = await readDisplayName(wf.absolute);
18043
18134
  const embedInput = `${name}
@@ -18080,7 +18171,7 @@ async function reconcileFileIndex(accountId, opts) {
18080
18171
  return withSession(opts, async (session) => {
18081
18172
  const walked = [];
18082
18173
  const subtreeRoots = [
18083
- resolve24(dataRoot, "accounts", accountId)
18174
+ resolve25(dataRoot, "accounts", accountId)
18084
18175
  ];
18085
18176
  let clean = true;
18086
18177
  for (const root of subtreeRoots) {
@@ -18163,7 +18254,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
18163
18254
  async function indexFile(accountId, relativePath, opts) {
18164
18255
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
18165
18256
  const embed2 = opts?.embed ?? embed;
18166
- const absolute = resolve24(dataRoot, relativePath);
18257
+ const absolute = resolve25(dataRoot, relativePath);
18167
18258
  await withSession(opts, async (session) => {
18168
18259
  const st = await fsp.stat(absolute);
18169
18260
  const wf = {
@@ -18281,7 +18372,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
18281
18372
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18282
18373
  async function readMeta(absDir, baseName) {
18283
18374
  try {
18284
- const raw = await readFile6(join35(absDir, `${baseName}.meta.json`), "utf8");
18375
+ const raw = await readFile7(join35(absDir, `${baseName}.meta.json`), "utf8");
18285
18376
  const parsed = JSON.parse(raw);
18286
18377
  if (typeof parsed?.filename === "string") {
18287
18378
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -18292,7 +18383,7 @@ async function readMeta(absDir, baseName) {
18292
18383
  }
18293
18384
  async function readAccountNames() {
18294
18385
  const map = /* @__PURE__ */ new Map();
18295
- const accountsDir = resolve25(DATA_ROOT, "accounts");
18386
+ const accountsDir = resolve26(DATA_ROOT, "accounts");
18296
18387
  let names;
18297
18388
  try {
18298
18389
  names = await readdir4(accountsDir);
@@ -18301,9 +18392,9 @@ async function readAccountNames() {
18301
18392
  }
18302
18393
  for (const name of names) {
18303
18394
  if (!UUID_RE4.test(name)) continue;
18304
- const configPath2 = resolve25(accountsDir, name, "account.json");
18395
+ const configPath2 = resolve26(accountsDir, name, "account.json");
18305
18396
  try {
18306
- const raw = await readFile6(configPath2, "utf8");
18397
+ const raw = await readFile7(configPath2, "utf8");
18307
18398
  const parsed = JSON.parse(raw);
18308
18399
  if (typeof parsed?.name === "string" && parsed.name.length > 0) {
18309
18400
  map.set(name, parsed.name);
@@ -18480,8 +18571,8 @@ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
18480
18571
  await session.close();
18481
18572
  }
18482
18573
  }
18483
- var app22 = new Hono();
18484
- app22.get("/", requireAdminSession, async (c) => {
18574
+ var app23 = new Hono();
18575
+ app23.get("/", requireAdminSession, async (c) => {
18485
18576
  const cacheKey = c.var.cacheKey;
18486
18577
  const accountId = getAccountIdForSession(cacheKey);
18487
18578
  if (!accountId) {
@@ -18560,7 +18651,7 @@ app22.get("/", requireAdminSession, async (c) => {
18560
18651
  return c.json({ error: message }, 500);
18561
18652
  }
18562
18653
  });
18563
- app22.get("/download", requireAdminSession, async (c) => {
18654
+ app23.get("/download", requireAdminSession, async (c) => {
18564
18655
  const cacheKey = c.var.cacheKey;
18565
18656
  const accountId = getAccountIdForSession(cacheKey);
18566
18657
  if (!accountId) {
@@ -18614,7 +18705,7 @@ app22.get("/download", requireAdminSession, async (c) => {
18614
18705
  if (!info.isFile()) {
18615
18706
  return c.json({ error: "Path is not a file" }, 400);
18616
18707
  }
18617
- const filename = basename10(absolute);
18708
+ const filename = basename11(absolute);
18618
18709
  const mimeType = detectMimeType(absolute);
18619
18710
  const nodeStream = createReadStream2(absolute);
18620
18711
  const webStream = Readable2.toWeb(nodeStream);
@@ -18638,7 +18729,7 @@ app22.get("/download", requireAdminSession, async (c) => {
18638
18729
  if (root === "data") {
18639
18730
  const parsed = parseAttachmentPath(relPath);
18640
18731
  if (parsed) {
18641
- const meta = await readMeta(dirname12(absolute), parsed.attachmentId);
18732
+ const meta = await readMeta(dirname13(absolute), parsed.attachmentId);
18642
18733
  if (meta?.filename) downloadName = meta.filename;
18643
18734
  }
18644
18735
  }
@@ -18686,7 +18777,7 @@ async function* walkRegularFiles(dirAbsolute) {
18686
18777
  if (d.isFile()) yield child;
18687
18778
  }
18688
18779
  }
18689
- app22.get("/download-zip", requireAdminSession, async (c) => {
18780
+ app23.get("/download-zip", requireAdminSession, async (c) => {
18690
18781
  const cacheKey = c.var.cacheKey;
18691
18782
  const accountId = getAccountIdForSession(cacheKey);
18692
18783
  if (!accountId) {
@@ -18707,7 +18798,7 @@ app22.get("/download-zip", requireAdminSession, async (c) => {
18707
18798
  if (entries.length >= maxFiles) return c.json({ error: `Too many files (max ${maxFiles})` }, 413);
18708
18799
  total += size;
18709
18800
  if (total > maxTotalBytes) return c.json({ error: "Selection too large to zip" }, 413);
18710
- entries.push({ name: member, data: await readFile6(absolute) });
18801
+ entries.push({ name: member, data: await readFile7(absolute) });
18711
18802
  return null;
18712
18803
  };
18713
18804
  for (const rawPath of rawPaths) {
@@ -18727,21 +18818,21 @@ app22.get("/download-zip", requireAdminSession, async (c) => {
18727
18818
  const info = await stat6(absolute);
18728
18819
  if (info.isDirectory()) {
18729
18820
  dirsWalked++;
18730
- const parentAbs = dirname12(absolute);
18821
+ const parentAbs = dirname13(absolute);
18731
18822
  for await (const fileAbs of walkRegularFiles(absolute)) {
18732
- const within = relative5(absolute, fileAbs).split(sep7).join("/");
18823
+ const within = relative5(absolute, fileAbs).split(sep8).join("/");
18733
18824
  const fileRel = relPath === "" || relPath === "." ? within : `${relPath}/${within}`;
18734
18825
  if (crossesForeignAccountPartition(fileRel, accountId)) continue;
18735
18826
  const fileInfo = await stat6(fileAbs);
18736
- const member = relative5(parentAbs, fileAbs).split(sep7).join("/");
18827
+ const member = relative5(parentAbs, fileAbs).split(sep8).join("/");
18737
18828
  const over = await addFile(fileAbs, fileInfo.size, member);
18738
18829
  if (over) return over;
18739
18830
  }
18740
18831
  } else if (info.isFile()) {
18741
- let member = basename10(absolute);
18832
+ let member = basename11(absolute);
18742
18833
  const parsed = parseAttachmentPath(relPath);
18743
18834
  if (parsed) {
18744
- const meta = await readMeta(dirname12(absolute), parsed.attachmentId);
18835
+ const meta = await readMeta(dirname13(absolute), parsed.attachmentId);
18745
18836
  if (meta?.filename) member = meta.filename;
18746
18837
  }
18747
18838
  const over = await addFile(absolute, info.size, member);
@@ -18773,12 +18864,12 @@ function dataUploadCeiling() {
18773
18864
  }
18774
18865
  async function resolveUploadTarget(c, accountId, uid) {
18775
18866
  const rawName = c.req.query("filename") ?? "";
18776
- const safeName = basename10(rawName).replace(/[\0/\\]/g, "_");
18867
+ const safeName = basename11(rawName).replace(/[\0/\\]/g, "_");
18777
18868
  if (!safeName) return { ok: false, status: 400, error: "filename query param required" };
18778
18869
  const rawRelpath = c.req.query("relpath") ?? "";
18779
18870
  const relpath = rawRelpath !== "" ? rawRelpath : null;
18780
18871
  const token = c.req.query("token") ?? "";
18781
- const finalName = relpath ? basename10(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
18872
+ const finalName = relpath ? basename11(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
18782
18873
  const mimeType = (c.req.header("content-type") ?? "").split(";")[0].trim();
18783
18874
  if (!SUPPORTED_MIME_TYPES.has(mimeType)) {
18784
18875
  console.error(`[data-upload] op=reject-mime uid=${uid} mime="${mimeType}" token=${token} rel="${relpath ?? ""}"`);
@@ -18787,7 +18878,7 @@ async function resolveUploadTarget(c, accountId, uid) {
18787
18878
  const rawDir = c.req.query("path") ?? "";
18788
18879
  const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
18789
18880
  if (!base.ok) return { ok: false, status: base.status, error: base.error };
18790
- const relDir = relpath ? dirname12(relpath) : ".";
18881
+ const relDir = relpath ? dirname13(relpath) : ".";
18791
18882
  const destRel = relDir === "." ? base.relative : join35(base.relative, relDir);
18792
18883
  if (crossesForeignAccountPartition(destRel, accountId)) {
18793
18884
  console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
@@ -18797,8 +18888,8 @@ async function resolveUploadTarget(c, accountId, uid) {
18797
18888
  console.error(`[data] write-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
18798
18889
  return { ok: false, status: 403, error: "Path is outside your account folder" };
18799
18890
  }
18800
- const destDir = relDir === "." ? base.absolute : resolve25(base.absolute, relDir);
18801
- const destPath = resolve25(destDir, finalName);
18891
+ const destDir = relDir === "." ? base.absolute : resolve26(base.absolute, relDir);
18892
+ const destPath = resolve26(destDir, finalName);
18802
18893
  if (relpath) {
18803
18894
  const firstCreated = await mkdir4(destDir, { recursive: true });
18804
18895
  if (firstCreated) console.error(`[data-upload] op=mkdir uid=${uid} token=${token} dir="${destRel}"`);
@@ -18806,16 +18897,16 @@ async function resolveUploadTarget(c, accountId, uid) {
18806
18897
  const info = await stat6(destDir).catch(() => null);
18807
18898
  if (!info || !info.isDirectory()) return { ok: false, status: 400, error: "Upload destination is not a directory" };
18808
18899
  }
18809
- const dataRootReal = realpathSync6(DATA_ROOT);
18810
- const destDirReal = realpathSync6(destDir);
18811
- if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep7)) {
18900
+ const dataRootReal = realpathSync7(DATA_ROOT);
18901
+ const destDirReal = realpathSync7(destDir);
18902
+ if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep8)) {
18812
18903
  console.error(`[data-upload] op=path-traversal-blocked uid=${uid} requested="${destRel}" resolved="${destDirReal}"`);
18813
18904
  return { ok: false, status: 403, error: "Upload destination escapes DATA_ROOT" };
18814
18905
  }
18815
18906
  return { ok: true, destDir, destPath, destRel, finalName, mimeType, relpath, token };
18816
18907
  }
18817
18908
  async function logUploadsTmpCensus(accountId) {
18818
- const tmpDir = resolve25(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
18909
+ const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
18819
18910
  let live = 0;
18820
18911
  try {
18821
18912
  live = (await readdir4(tmpDir)).length;
@@ -18823,7 +18914,7 @@ async function logUploadsTmpCensus(accountId) {
18823
18914
  }
18824
18915
  console.error(`[uploads-tmp-census] dir=${accountId} live=${live}`);
18825
18916
  }
18826
- app22.post("/upload", requireAdminSession, async (c) => {
18917
+ app23.post("/upload", requireAdminSession, async (c) => {
18827
18918
  const cacheKey = c.var.cacheKey;
18828
18919
  const accountId = getAccountIdForSession(cacheKey);
18829
18920
  if (!accountId) {
@@ -18842,9 +18933,9 @@ app22.post("/upload", requireAdminSession, async (c) => {
18842
18933
  if (!body) return c.json({ error: "Empty request body" }, 400);
18843
18934
  console.error(`[data-upload] op=request uid=${uid} account=${accountId} dir="${destRel}" token=${token} rel="${relpath ?? ""}" declaredBytes=${declaredBytes}`);
18844
18935
  const ceiling = dataUploadCeiling();
18845
- const tmpDir = resolve25(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
18936
+ const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
18846
18937
  await mkdir4(tmpDir, { recursive: true });
18847
- const tmpPath = resolve25(tmpDir, `${uid}.part`);
18938
+ const tmpPath = resolve26(tmpDir, `${uid}.part`);
18848
18939
  const out = createWriteStream2(tmpPath);
18849
18940
  const t0 = Date.now();
18850
18941
  let received = 0;
@@ -18862,7 +18953,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
18862
18953
  });
18863
18954
  await unlink3(tmpPath).catch(() => {
18864
18955
  });
18865
- const tempRemoved = !existsSync32(tmpPath);
18956
+ const tempRemoved = !existsSync34(tmpPath);
18866
18957
  console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
18867
18958
  };
18868
18959
  const reader = body.getReader();
@@ -18936,7 +19027,7 @@ async function discardChunkUpload(uploadId, state) {
18936
19027
  });
18937
19028
  await unlink3(state.tmpPath).catch(() => {
18938
19029
  });
18939
- const tempRemoved = !existsSync32(state.tmpPath);
19030
+ const tempRemoved = !existsSync34(state.tmpPath);
18940
19031
  console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
18941
19032
  }
18942
19033
  async function writeChunkBody(body, out, alreadyReceived, ceiling) {
@@ -18991,9 +19082,9 @@ async function handleChunkUpload(c, accountId) {
18991
19082
  }
18992
19083
  const target = await resolveUploadTarget(c, accountId, uploadId);
18993
19084
  if (!target.ok) return c.json({ error: target.error }, target.status);
18994
- const tmpDir = resolve25(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
19085
+ const tmpDir = resolve26(DATA_ROOT, "accounts", accountId, UPLOAD_TMP_DIR);
18995
19086
  await mkdir4(tmpDir, { recursive: true });
18996
- const tmpPath = resolve25(tmpDir, `${uploadId}.part`);
19087
+ const tmpPath = resolve26(tmpDir, `${uploadId}.part`);
18997
19088
  const out = createWriteStream2(tmpPath);
18998
19089
  const state2 = {
18999
19090
  accountId,
@@ -19099,7 +19190,7 @@ async function evictStaleChunkUploads(ttlMs) {
19099
19190
  return evicted;
19100
19191
  }
19101
19192
  async function sweepStaleUploadTemps() {
19102
- const accountsRoot = resolve25(DATA_ROOT, "accounts");
19193
+ const accountsRoot = resolve26(DATA_ROOT, "accounts");
19103
19194
  let accounts;
19104
19195
  try {
19105
19196
  accounts = await readdir4(accountsRoot, { withFileTypes: true });
@@ -19109,7 +19200,7 @@ async function sweepStaleUploadTemps() {
19109
19200
  let removed = 0;
19110
19201
  for (const acc of accounts) {
19111
19202
  if (!acc.isDirectory()) continue;
19112
- const tmpDir = resolve25(accountsRoot, acc.name, UPLOAD_TMP_DIR);
19203
+ const tmpDir = resolve26(accountsRoot, acc.name, UPLOAD_TMP_DIR);
19113
19204
  let entries;
19114
19205
  try {
19115
19206
  entries = await readdir4(tmpDir);
@@ -19118,7 +19209,7 @@ async function sweepStaleUploadTemps() {
19118
19209
  }
19119
19210
  for (const name of entries) {
19120
19211
  try {
19121
- await unlink3(resolve25(tmpDir, name));
19212
+ await unlink3(resolve26(tmpDir, name));
19122
19213
  removed++;
19123
19214
  } catch {
19124
19215
  }
@@ -19127,7 +19218,7 @@ async function sweepStaleUploadTemps() {
19127
19218
  if (removed > 0) console.error(`[data-upload] op=sweep removed=${removed}`);
19128
19219
  return removed;
19129
19220
  }
19130
- app22.delete("/", requireAdminSession, async (c) => {
19221
+ app23.delete("/", requireAdminSession, async (c) => {
19131
19222
  const cacheKey = c.var.cacheKey;
19132
19223
  const accountId = getAccountIdForSession(cacheKey);
19133
19224
  if (!accountId) {
@@ -19148,7 +19239,7 @@ app22.delete("/", requireAdminSession, async (c) => {
19148
19239
  console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
19149
19240
  return c.json({ error: "Not found" }, 404);
19150
19241
  }
19151
- const base = basename10(absolute);
19242
+ const base = basename11(absolute);
19152
19243
  const protection = isProtectedFromDeletion(relPath);
19153
19244
  if (protection.protected) {
19154
19245
  console.error(`[data] file-delete blocked path="${relPath}" reason="protected" rule="${protection.rule}"`);
@@ -19164,9 +19255,9 @@ app22.delete("/", requireAdminSession, async (c) => {
19164
19255
  }
19165
19256
  const dot = base.lastIndexOf(".");
19166
19257
  const stem = dot === -1 ? base : base.slice(0, dot);
19167
- const containerDir = dirname12(absolute);
19258
+ const containerDir = dirname13(absolute);
19168
19259
  const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join35(containerDir, `${stem}.meta.json`) : null;
19169
- const isAttachmentContainer = UUID_RE4.test(stem) && basename10(containerDir) === stem;
19260
+ const isAttachmentContainer = UUID_RE4.test(stem) && basename11(containerDir) === stem;
19170
19261
  await unlink3(absolute);
19171
19262
  if (sidecarPath) {
19172
19263
  try {
@@ -19211,7 +19302,7 @@ app22.delete("/", requireAdminSession, async (c) => {
19211
19302
  return c.json({ error: message }, 500);
19212
19303
  }
19213
19304
  });
19214
- app22.post("/folder", requireAdminSession, async (c) => {
19305
+ app23.post("/folder", requireAdminSession, async (c) => {
19215
19306
  const cacheKey = c.var.cacheKey;
19216
19307
  const accountId = getAccountIdForSession(cacheKey);
19217
19308
  if (!accountId) {
@@ -19229,7 +19320,7 @@ app22.post("/folder", requireAdminSession, async (c) => {
19229
19320
  if (!isValidEntryName(name)) return c.json({ error: "Invalid folder name" }, 400);
19230
19321
  const parent = resolveOwnAccountWrite(rawPath, accountId, "POST /api/admin/files/folder");
19231
19322
  if (!parent.ok) return c.json({ error: parent.error }, parent.status);
19232
- const newAbs = resolve25(parent.absolute, name);
19323
+ const newAbs = resolve26(parent.absolute, name);
19233
19324
  const newRel = `${parent.relative}/${name}`;
19234
19325
  try {
19235
19326
  const info = await stat6(parent.absolute);
@@ -19246,7 +19337,7 @@ app22.post("/folder", requireAdminSession, async (c) => {
19246
19337
  console.error(`[data] folder-create path="${newRel}"`);
19247
19338
  return c.json({ path: newRel });
19248
19339
  });
19249
- app22.post("/rename", requireAdminSession, async (c) => {
19340
+ app23.post("/rename", requireAdminSession, async (c) => {
19250
19341
  const cacheKey = c.var.cacheKey;
19251
19342
  const accountId = getAccountIdForSession(cacheKey);
19252
19343
  if (!accountId) {
@@ -19268,8 +19359,8 @@ app22.post("/rename", requireAdminSession, async (c) => {
19268
19359
  console.error(`[data] file-rename blocked path="${src.relative}" reason="protected"`);
19269
19360
  return c.json({ error: "Protected entry \u2014 refusing to rename" }, 403);
19270
19361
  }
19271
- const destAbs = resolve25(dirname12(src.absolute), newName);
19272
- const newRel = `${dirname12(src.relative)}/${newName}`.replace(/^\.\//, "");
19362
+ const destAbs = resolve26(dirname13(src.absolute), newName);
19363
+ const newRel = `${dirname13(src.relative)}/${newName}`.replace(/^\.\//, "");
19273
19364
  if (isProtectedFromRename(newRel)) {
19274
19365
  console.error(`[data] file-rename blocked path="${newRel}" reason="protected-target"`);
19275
19366
  return c.json({ error: "That name is reserved" }, 403);
@@ -19296,7 +19387,7 @@ app22.post("/rename", requireAdminSession, async (c) => {
19296
19387
  });
19297
19388
  return c.json({ path: newRel });
19298
19389
  });
19299
- var files_default = app22;
19390
+ var files_default = app23;
19300
19391
 
19301
19392
  // ../lib/graph-search/src/index.ts
19302
19393
  var import_dist = __toESM(require_dist2());
@@ -20054,8 +20145,8 @@ var DEFAULT_LIMIT = 20;
20054
20145
  var MAX_LIMIT = 2e3;
20055
20146
  var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage"];
20056
20147
  var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
20057
- var app23 = new Hono();
20058
- app23.get("/", requireAdminSession, async (c) => {
20148
+ var app24 = new Hono();
20149
+ app24.get("/", requireAdminSession, async (c) => {
20059
20150
  const cacheKey = c.var.cacheKey;
20060
20151
  const q2 = (c.req.query("q") ?? "").trim();
20061
20152
  const rawLimit = c.req.query("limit");
@@ -20086,7 +20177,7 @@ app23.get("/", requireAdminSession, async (c) => {
20086
20177
  const wantsBodyFulltext = !allLabels && labels.some((l) => CONVERSATION_PARENT_LABELS.has(l));
20087
20178
  const forwardedLabels = allLabels ? void 0 : wantsBodyFulltext ? Array.from(/* @__PURE__ */ new Set([...labels, ...MESSAGE_FAMILY_LABELS])) : labels;
20088
20179
  if (labels.includes("FileArtifact")) {
20089
- await reconcileFileIndexDebounced(accountId);
20180
+ void reconcileFileIndexDebounced(accountId);
20090
20181
  }
20091
20182
  const started = Date.now();
20092
20183
  const session = getSession();
@@ -20191,7 +20282,7 @@ app23.get("/", requireAdminSession, async (c) => {
20191
20282
  await session.close();
20192
20283
  }
20193
20284
  });
20194
- var graph_search_default = app23;
20285
+ var graph_search_default = app24;
20195
20286
 
20196
20287
  // server/routes/admin/graph-subgraph.ts
20197
20288
  import neo4j2 from "neo4j-driver";
@@ -20285,7 +20376,7 @@ function isHiddenByDefault(label) {
20285
20376
  // server/lib/top-level-labels.ts
20286
20377
  var import_dist4 = __toESM(require_dist3(), 1);
20287
20378
  import { readdirSync as readdirSync23, readFileSync as readFileSync35 } from "fs";
20288
- import { join as join36, resolve as resolve26 } from "path";
20379
+ import { join as join36, resolve as resolve27 } from "path";
20289
20380
  var STATIC_TOP_LEVEL_LABELS = Object.freeze(
20290
20381
  /* @__PURE__ */ new Set([
20291
20382
  // Base-schema infra (schema-base.md has no top-level section).
@@ -20369,8 +20460,8 @@ function parseTopLevelLabels(content) {
20369
20460
  const line = lines[i];
20370
20461
  if (line.startsWith("## ")) return [];
20371
20462
  if (!line.includes("|")) continue;
20372
- const sep11 = lines[i + 1];
20373
- if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(sep11) || !sep11.includes("-")) continue;
20463
+ const sep12 = lines[i + 1];
20464
+ if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(sep12) || !sep12.includes("-")) continue;
20374
20465
  const headers = splitPipeRow(line).map((h) => stripBackticks(h).toLowerCase());
20375
20466
  const labelCol = headers.findIndex((h) => h === "neo4j label");
20376
20467
  if (labelCol === -1) return [];
@@ -20391,7 +20482,7 @@ function resolveReferencesDir() {
20391
20482
  if (process.env.MAXY_PLATFORM_ROOT) {
20392
20483
  return join36(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
20393
20484
  }
20394
- return resolve26(import.meta.dirname, "../../../plugins/memory/references");
20485
+ return resolve27(import.meta.dirname, "../../../plugins/memory/references");
20395
20486
  }
20396
20487
  function parseTableTopLevelLabels(referencesDir) {
20397
20488
  const labels = /* @__PURE__ */ new Set();
@@ -20444,8 +20535,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
20444
20535
  "otpCode",
20445
20536
  "cacheKey"
20446
20537
  ]);
20447
- var app24 = new Hono();
20448
- app24.get("/", requireAdminSession, async (c) => {
20538
+ var app25 = new Hono();
20539
+ app25.get("/", requireAdminSession, async (c) => {
20449
20540
  const cacheKey = c.var.cacheKey;
20450
20541
  const accountId = getAccountIdForSession(cacheKey);
20451
20542
  if (!accountId) {
@@ -21116,12 +21207,12 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
21116
21207
  }
21117
21208
  return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
21118
21209
  }
21119
- var graph_subgraph_default = app24;
21210
+ var graph_subgraph_default = app25;
21120
21211
 
21121
21212
  // server/routes/admin/graph-delete.ts
21122
21213
  var ALLOWED_BY = ["graph-page", "graph-drag-trash", "graph-side-panel-trash"];
21123
- var app25 = new Hono();
21124
- app25.post("/", requireAdminSession, async (c) => {
21214
+ var app26 = new Hono();
21215
+ app26.post("/", requireAdminSession, async (c) => {
21125
21216
  const cacheKey = c.var.cacheKey;
21126
21217
  const accountId = getAccountIdForSession(cacheKey);
21127
21218
  if (!accountId) {
@@ -21283,11 +21374,11 @@ app25.post("/", requireAdminSession, async (c) => {
21283
21374
  }
21284
21375
  }
21285
21376
  });
21286
- var graph_delete_default = app25;
21377
+ var graph_delete_default = app26;
21287
21378
 
21288
21379
  // server/routes/admin/graph-restore.ts
21289
- var app26 = new Hono();
21290
- app26.post("/", requireAdminSession, async (c) => {
21380
+ var app27 = new Hono();
21381
+ app27.post("/", requireAdminSession, async (c) => {
21291
21382
  const cacheKey = c.var.cacheKey;
21292
21383
  const accountId = getAccountIdForSession(cacheKey);
21293
21384
  if (!accountId) {
@@ -21351,11 +21442,11 @@ app26.post("/", requireAdminSession, async (c) => {
21351
21442
  }
21352
21443
  }
21353
21444
  });
21354
- var graph_restore_default = app26;
21445
+ var graph_restore_default = app27;
21355
21446
 
21356
21447
  // server/routes/admin/graph-labels-in-graph.ts
21357
- var app27 = new Hono();
21358
- app27.get("/", requireAdminSession, async (c) => {
21448
+ var app28 = new Hono();
21449
+ app28.get("/", requireAdminSession, async (c) => {
21359
21450
  const cacheKey = c.var.cacheKey;
21360
21451
  const accountId = getAccountIdForSession(cacheKey);
21361
21452
  if (!accountId) {
@@ -21421,11 +21512,11 @@ var LABELS_IN_GRAPH_CYPHER = `
21421
21512
  sum(halfEdges) AS relDegree
21422
21513
  RETURN label, nodeCount, relDegree
21423
21514
  `;
21424
- var graph_labels_in_graph_default = app27;
21515
+ var graph_labels_in_graph_default = app28;
21425
21516
 
21426
21517
  // server/routes/admin/graph-default-view.ts
21427
- var app28 = new Hono();
21428
- app28.get("/", requireAdminSession, async (c) => {
21518
+ var app29 = new Hono();
21519
+ app29.get("/", requireAdminSession, async (c) => {
21429
21520
  const cacheKey = c.var.cacheKey;
21430
21521
  const accountId = getAccountIdForSession(cacheKey);
21431
21522
  const userId = getUserIdForSession(cacheKey);
@@ -21463,7 +21554,7 @@ app28.get("/", requireAdminSession, async (c) => {
21463
21554
  }
21464
21555
  }
21465
21556
  });
21466
- app28.put("/", requireAdminSession, async (c) => {
21557
+ app29.put("/", requireAdminSession, async (c) => {
21467
21558
  const cacheKey = c.var.cacheKey;
21468
21559
  const accountId = getAccountIdForSession(cacheKey);
21469
21560
  const userId = getUserIdForSession(cacheKey);
@@ -21552,20 +21643,20 @@ var WRITE_CYPHER = `
21552
21643
  p.updatedAt = $updatedAt
21553
21644
  RETURN p.labels AS labels
21554
21645
  `;
21555
- var graph_default_view_default = app28;
21646
+ var graph_default_view_default = app29;
21556
21647
 
21557
21648
  // server/routes/admin/sidebar-artefacts.ts
21558
21649
  import { readdir as readdir5, stat as stat7 } from "fs/promises";
21559
- import { resolve as resolve27, relative as relative6, isAbsolute as isAbsolute2, sep as sep8, basename as basename11 } from "path";
21560
- import { existsSync as existsSync33 } from "fs";
21650
+ import { resolve as resolve28, relative as relative6, isAbsolute as isAbsolute2, sep as sep9, basename as basename12 } from "path";
21651
+ import { existsSync as existsSync35 } from "fs";
21561
21652
  var LIMIT = 50;
21562
21653
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
21563
21654
  function toDataRootRelPath(absPath) {
21564
- if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep8)) return null;
21655
+ if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep9)) return null;
21565
21656
  return relative6(DATA_ROOT, absPath);
21566
21657
  }
21567
- var app29 = new Hono();
21568
- app29.get("/", requireAdminSession, async (c) => {
21658
+ var app30 = new Hono();
21659
+ app30.get("/", requireAdminSession, async (c) => {
21569
21660
  const cacheKey = c.var.cacheKey;
21570
21661
  const accountId = getAccountIdForSession(cacheKey);
21571
21662
  if (!accountId) {
@@ -21576,7 +21667,7 @@ app29.get("/", requireAdminSession, async (c) => {
21576
21667
  if (accountFiles === null) {
21577
21668
  return c.json({ error: "Failed to load artefacts" }, 500);
21578
21669
  }
21579
- const accountDir = resolve27(ACCOUNTS_DIR, accountId);
21670
+ const accountDir = resolve28(ACCOUNTS_DIR, accountId);
21580
21671
  const agents = await fetchAgentTemplateRows(accountDir);
21581
21672
  const artefacts = [...accountFiles, ...agents].sort(
21582
21673
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -21609,7 +21700,7 @@ async function fetchAccountFileArtefacts(accountId) {
21609
21700
  const modifiedAt = r.get("modifiedAt") ?? "";
21610
21701
  return {
21611
21702
  id: `account-file:${relativePath}`,
21612
- name: displayName ?? basename11(relativePath),
21703
+ name: displayName ?? basename12(relativePath),
21613
21704
  kind: "account-file",
21614
21705
  updatedAt: modifiedAt,
21615
21706
  mimeType,
@@ -21628,8 +21719,8 @@ async function fetchAccountFileArtefacts(accountId) {
21628
21719
  async function fetchAgentTemplateRows(accountDir) {
21629
21720
  const rows = [];
21630
21721
  for (const filename of ADMIN_AGENT_FILES) {
21631
- const overridePath = resolve27(accountDir, "agents", "admin", filename);
21632
- const bundledPath = resolve27(PLATFORM_ROOT, "templates", "agents", "admin", filename);
21722
+ const overridePath = resolve28(accountDir, "agents", "admin", filename);
21723
+ const bundledPath = resolve28(PLATFORM_ROOT, "templates", "agents", "admin", filename);
21633
21724
  const labelStem = filename.replace(/\.md$/, "");
21634
21725
  const row = await readAgentTemplateRow({
21635
21726
  id: `agent-template:admin:${filename}`,
@@ -21642,12 +21733,12 @@ async function fetchAgentTemplateRows(accountDir) {
21642
21733
  });
21643
21734
  if (row) rows.push(row);
21644
21735
  }
21645
- const overrideDir = resolve27(accountDir, "specialists", "agents");
21646
- const bundledDir = resolve27(PLATFORM_ROOT, "templates", "specialists", "agents");
21736
+ const overrideDir = resolve28(accountDir, "specialists", "agents");
21737
+ const bundledDir = resolve28(PLATFORM_ROOT, "templates", "specialists", "agents");
21647
21738
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
21648
21739
  for (const filename of specialistNames) {
21649
- const overridePath = resolve27(overrideDir, filename);
21650
- const bundledPath = resolve27(bundledDir, filename);
21740
+ const overridePath = resolve28(overrideDir, filename);
21741
+ const bundledPath = resolve28(bundledDir, filename);
21651
21742
  const row = await readAgentTemplateRow({
21652
21743
  id: `agent-template:specialist:${filename}`,
21653
21744
  displayName: filename.replace(/\.md$/, ""),
@@ -21664,7 +21755,7 @@ async function fetchAgentTemplateRows(accountDir) {
21664
21755
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
21665
21756
  const names = /* @__PURE__ */ new Set();
21666
21757
  for (const dir of [overrideDir, bundledDir]) {
21667
- if (!existsSync33(dir)) continue;
21758
+ if (!existsSync35(dir)) continue;
21668
21759
  try {
21669
21760
  const entries = await readdir5(dir);
21670
21761
  for (const entry of entries) {
@@ -21679,7 +21770,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
21679
21770
  }
21680
21771
  async function readAgentTemplateRow(inp) {
21681
21772
  let chosenPath = null;
21682
- if (existsSync33(inp.overridePath)) {
21773
+ if (existsSync35(inp.overridePath)) {
21683
21774
  try {
21684
21775
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
21685
21776
  chosenPath = inp.overridePath;
@@ -21690,7 +21781,7 @@ async function readAgentTemplateRow(inp) {
21690
21781
  );
21691
21782
  return null;
21692
21783
  }
21693
- } else if (existsSync33(inp.bundledPath)) {
21784
+ } else if (existsSync35(inp.bundledPath)) {
21694
21785
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
21695
21786
  console.error(
21696
21787
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -21729,7 +21820,7 @@ function isWithin(target, root) {
21729
21820
  const rel = relative6(root, target);
21730
21821
  return !rel.startsWith("..") && !isAbsolute2(rel);
21731
21822
  }
21732
- var sidebar_artefacts_default = app29;
21823
+ var sidebar_artefacts_default = app30;
21733
21824
 
21734
21825
  // server/channel-session-override.ts
21735
21826
  import { readFileSync as readFileSync36, writeFileSync as writeFileSync13, renameSync as renameSync9 } from "fs";
@@ -21802,8 +21893,8 @@ function clearForwardPointers(sessionId) {
21802
21893
  }
21803
21894
 
21804
21895
  // server/routes/admin/session-delete.ts
21805
- var app30 = new Hono();
21806
- app30.post("/", requireAdminSession, async (c) => {
21896
+ var app31 = new Hono();
21897
+ app31.post("/", requireAdminSession, async (c) => {
21807
21898
  let body;
21808
21899
  try {
21809
21900
  body = await c.req.json();
@@ -21842,11 +21933,11 @@ app30.post("/", requireAdminSession, async (c) => {
21842
21933
  console.error(`[session-delete] sessionId=${sessionId} delete-status=${del.status}`);
21843
21934
  return c.json({ error: `manager-status-${del.status}` }, 502);
21844
21935
  });
21845
- var session_delete_default = app30;
21936
+ var session_delete_default = app31;
21846
21937
 
21847
21938
  // server/routes/admin/session-stop.ts
21848
- var app31 = new Hono();
21849
- app31.post("/", requireAdminSession, async (c) => {
21939
+ var app32 = new Hono();
21940
+ app32.post("/", requireAdminSession, async (c) => {
21850
21941
  let body;
21851
21942
  try {
21852
21943
  body = await c.req.json();
@@ -21871,11 +21962,11 @@ app31.post("/", requireAdminSession, async (c) => {
21871
21962
  console.error(`[session-stop] sessionId=${sessionId} manager-status=${res.status}`);
21872
21963
  return c.json({ error: `manager-status-${res.status}` }, 502);
21873
21964
  });
21874
- var session_stop_default = app31;
21965
+ var session_stop_default = app32;
21875
21966
 
21876
21967
  // server/routes/admin/session-archive.ts
21877
- var app32 = new Hono();
21878
- app32.post("/", requireAdminSession, async (c) => {
21968
+ var app33 = new Hono();
21969
+ app33.post("/", requireAdminSession, async (c) => {
21879
21970
  let body;
21880
21971
  try {
21881
21972
  body = await c.req.json();
@@ -21924,11 +22015,11 @@ app32.post("/", requireAdminSession, async (c) => {
21924
22015
  console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
21925
22016
  return c.json({ error: `manager-status-${res.status}` }, 502);
21926
22017
  });
21927
- var session_archive_default = app32;
22018
+ var session_archive_default = app33;
21928
22019
 
21929
22020
  // server/routes/admin/session-rename.ts
21930
- var app33 = new Hono();
21931
- app33.post("/", requireAdminSession, async (c) => {
22021
+ var app34 = new Hono();
22022
+ app34.post("/", requireAdminSession, async (c) => {
21932
22023
  let body;
21933
22024
  try {
21934
22025
  body = await c.req.json();
@@ -21967,11 +22058,11 @@ app33.post("/", requireAdminSession, async (c) => {
21967
22058
  console.error(`[session-rename] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
21968
22059
  return c.json({ error: `manager-status-${res.status}` }, 502);
21969
22060
  });
21970
- var session_rename_default = app33;
22061
+ var session_rename_default = app34;
21971
22062
 
21972
22063
  // server/routes/admin/session-usage.ts
21973
- var app34 = new Hono();
21974
- app34.get("/", requireAdminSession, async (c) => {
22064
+ var app35 = new Hono();
22065
+ app35.get("/", requireAdminSession, async (c) => {
21975
22066
  const sessionId = c.req.query("sessionId") ?? "";
21976
22067
  if (!SESSION_ID_RE2.test(sessionId)) {
21977
22068
  return c.json({ error: "sessionId must be a v4 UUID" }, 400);
@@ -21997,7 +22088,7 @@ app34.get("/", requireAdminSession, async (c) => {
21997
22088
  console.error(`[session-usage] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
21998
22089
  return c.json({ error: `manager-status-${res.status}` }, 502);
21999
22090
  });
22000
- var session_usage_default = app34;
22091
+ var session_usage_default = app35;
22001
22092
 
22002
22093
  // server/routes/admin/session-rc-spawn.ts
22003
22094
  import { randomUUID as randomUUID11 } from "crypto";
@@ -22044,8 +22135,8 @@ function shapeWebchatResponse(sessionId, manager) {
22044
22135
  const landed = redirected ? manager.sessionId : sessionId;
22045
22136
  return { sessionId: landed, outcome, target: `/chat?session=${landed}` };
22046
22137
  }
22047
- var app35 = new Hono();
22048
- app35.post("/", requireAdminSession, async (c) => {
22138
+ var app36 = new Hono();
22139
+ app36.post("/", requireAdminSession, async (c) => {
22049
22140
  let body;
22050
22141
  try {
22051
22142
  body = await c.req.json();
@@ -22127,30 +22218,30 @@ app35.post("/", requireAdminSession, async (c) => {
22127
22218
  }
22128
22219
  return c.json(parsed ?? {});
22129
22220
  });
22130
- var session_rc_spawn_default = app35;
22221
+ var session_rc_spawn_default = app36;
22131
22222
 
22132
22223
  // server/routes/admin/session-reseat.ts
22133
22224
  import { randomUUID as randomUUID12 } from "crypto";
22134
22225
 
22135
22226
  // server/wa-descriptor.ts
22136
- import { resolve as resolve28, join as join38 } from "path";
22227
+ import { resolve as resolve29, join as join38 } from "path";
22137
22228
  function waGatewayUrl() {
22138
22229
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
22139
22230
  }
22140
22231
  function waServerPath() {
22141
- return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
22232
+ return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve29(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
22142
22233
  }
22143
22234
  function waChannelDescriptor(senderId) {
22144
22235
  return { senderId, gatewayUrl: waGatewayUrl(), serverPath: waServerPath() };
22145
22236
  }
22146
22237
 
22147
22238
  // server/telegram-descriptor.ts
22148
- import { resolve as resolve29, join as join39 } from "path";
22239
+ import { resolve as resolve30, join as join39 } from "path";
22149
22240
  function telegramGatewayUrl() {
22150
22241
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
22151
22242
  }
22152
22243
  function telegramServerPath() {
22153
- return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve29(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "services/telegram-channel/dist/server.js");
22244
+ return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "services/telegram-channel/dist/server.js");
22154
22245
  }
22155
22246
  function telegramChannelDescriptor(senderId) {
22156
22247
  return { senderId, gatewayUrl: telegramGatewayUrl(), serverPath: telegramServerPath() };
@@ -22193,9 +22284,9 @@ function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticat
22193
22284
  if (authenticatedName) payload.authenticatedName = authenticatedName;
22194
22285
  return { sessionId, payload };
22195
22286
  }
22196
- var app36 = new Hono();
22287
+ var app37 = new Hono();
22197
22288
  var reseatsInFlight = /* @__PURE__ */ new Set();
22198
- app36.post("/", requireAdminSession, async (c) => {
22289
+ app37.post("/", requireAdminSession, async (c) => {
22199
22290
  let body;
22200
22291
  try {
22201
22292
  body = await c.req.json();
@@ -22310,10 +22401,10 @@ app36.post("/", requireAdminSession, async (c) => {
22310
22401
  reseatsInFlight.delete(fromSessionId);
22311
22402
  }
22312
22403
  });
22313
- var session_reseat_default = app36;
22404
+ var session_reseat_default = app37;
22314
22405
 
22315
22406
  // server/routes/admin/system-stats.ts
22316
- import { readFile as readFile7 } from "fs/promises";
22407
+ import { readFile as readFile8 } from "fs/promises";
22317
22408
  import { cpus, loadavg, totalmem, freemem } from "os";
22318
22409
  function parseCpuStat(blob) {
22319
22410
  const line = blob.split("\n", 1)[0] ?? "";
@@ -22357,11 +22448,11 @@ function parseMeminfo(blob) {
22357
22448
  }
22358
22449
  var SAMPLE_DELAY_MS = 100;
22359
22450
  async function sampleLinux() {
22360
- const a = parseCpuStat(await readFile7("/proc/stat", "utf-8"));
22451
+ const a = parseCpuStat(await readFile8("/proc/stat", "utf-8"));
22361
22452
  await new Promise((r) => setTimeout(r, SAMPLE_DELAY_MS));
22362
- const b = parseCpuStat(await readFile7("/proc/stat", "utf-8"));
22363
- const meminfo = parseMeminfo(await readFile7("/proc/meminfo", "utf-8"));
22364
- const loadavgRaw = (await readFile7("/proc/loadavg", "utf-8")).trim();
22453
+ const b = parseCpuStat(await readFile8("/proc/stat", "utf-8"));
22454
+ const meminfo = parseMeminfo(await readFile8("/proc/meminfo", "utf-8"));
22455
+ const loadavgRaw = (await readFile8("/proc/loadavg", "utf-8")).trim();
22365
22456
  const [l1, l5, l15] = loadavgRaw.split(/\s+/, 3).map(Number);
22366
22457
  if (![l1, l5, l15].every(Number.isFinite)) {
22367
22458
  throw new Error(`malformed /proc/loadavg: ${loadavgRaw}`);
@@ -22407,8 +22498,8 @@ async function sample() {
22407
22498
  if (process.platform === "linux") return sampleLinux();
22408
22499
  return sampleOsFallback();
22409
22500
  }
22410
- var app37 = new Hono();
22411
- app37.get("/", async (c) => {
22501
+ var app38 = new Hono();
22502
+ app38.get("/", async (c) => {
22412
22503
  const started = Date.now();
22413
22504
  if (!inflight) {
22414
22505
  inflight = sample().finally(() => {
@@ -22431,26 +22522,26 @@ app37.get("/", async (c) => {
22431
22522
  return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
22432
22523
  }
22433
22524
  });
22434
- var system_stats_default = app37;
22525
+ var system_stats_default = app38;
22435
22526
 
22436
22527
  // server/routes/admin/health.ts
22437
- import { existsSync as existsSync34, readFileSync as readFileSync37 } from "fs";
22438
- import { resolve as resolve30, join as join40 } from "path";
22439
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve30(process.cwd(), "..");
22528
+ import { existsSync as existsSync36, readFileSync as readFileSync37 } from "fs";
22529
+ import { resolve as resolve31, join as join40 } from "path";
22530
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve31(process.cwd(), "..");
22440
22531
  var brandHostname = "maxy";
22441
22532
  var brandJsonPath = join40(PLATFORM_ROOT6, "config", "brand.json");
22442
- if (existsSync34(brandJsonPath)) {
22533
+ if (existsSync36(brandJsonPath)) {
22443
22534
  try {
22444
22535
  const brand = JSON.parse(readFileSync37(brandJsonPath, "utf-8"));
22445
22536
  if (brand.hostname) brandHostname = brand.hostname;
22446
22537
  } catch {
22447
22538
  }
22448
22539
  }
22449
- var VERSION_FILE = resolve30(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
22540
+ var VERSION_FILE = resolve31(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
22450
22541
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
22451
22542
  var PROBE_TIMEOUT_MS = 1e3;
22452
22543
  function readVersion() {
22453
- if (!existsSync34(VERSION_FILE)) return "unknown";
22544
+ if (!existsSync36(VERSION_FILE)) return "unknown";
22454
22545
  return readFileSync37(VERSION_FILE, "utf-8").trim() || "unknown";
22455
22546
  }
22456
22547
  async function probeConversationDb() {
@@ -22476,8 +22567,8 @@ async function probeConversationDb() {
22476
22567
  });
22477
22568
  }
22478
22569
  }
22479
- var app38 = new Hono();
22480
- app38.get("/", async (c) => {
22570
+ var app39 = new Hono();
22571
+ app39.get("/", async (c) => {
22481
22572
  const version = readVersion();
22482
22573
  const probe = await probeConversationDb();
22483
22574
  const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
@@ -22499,7 +22590,7 @@ app38.get("/", async (c) => {
22499
22590
  uptimeMs
22500
22591
  });
22501
22592
  });
22502
- var health_default2 = app38;
22593
+ var health_default2 = app39;
22503
22594
 
22504
22595
  // server/routes/admin/linkedin-ingest.ts
22505
22596
  import { randomUUID as randomUUID13 } from "crypto";
@@ -22728,8 +22819,8 @@ function buildInitialMessage(env) {
22728
22819
  }
22729
22820
  return header;
22730
22821
  }
22731
- var app39 = new Hono();
22732
- app39.post("/", requireAdminSession, async (c) => {
22822
+ var app40 = new Hono();
22823
+ app40.post("/", requireAdminSession, async (c) => {
22733
22824
  let body;
22734
22825
  try {
22735
22826
  body = await c.req.json();
@@ -22774,7 +22865,7 @@ app39.post("/", requireAdminSession, async (c) => {
22774
22865
  );
22775
22866
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
22776
22867
  });
22777
- var linkedin_ingest_default = app39;
22868
+ var linkedin_ingest_default = app40;
22778
22869
 
22779
22870
  // server/routes/admin/post-turn-context.ts
22780
22871
  import neo4j3 from "neo4j-driver";
@@ -22816,8 +22907,8 @@ function pruneProperties(raw) {
22816
22907
  }
22817
22908
  return out;
22818
22909
  }
22819
- var app40 = new Hono();
22820
- app40.get("/", async (c) => {
22910
+ var app41 = new Hono();
22911
+ app41.get("/", async (c) => {
22821
22912
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
22822
22913
  if (!isLoopbackAddr3(remoteAddr)) {
22823
22914
  console.error(`${TAG34} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -22877,7 +22968,7 @@ app40.get("/", async (c) => {
22877
22968
  await session.close();
22878
22969
  }
22879
22970
  });
22880
- var post_turn_context_default = app40;
22971
+ var post_turn_context_default = app41;
22881
22972
 
22882
22973
  // app/lib/slice-writes.ts
22883
22974
  import neo4j4 from "neo4j-driver";
@@ -22987,8 +23078,8 @@ var TAG35 = "[public-session-context]";
22987
23078
  function isLoopbackAddr4(addr) {
22988
23079
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
22989
23080
  }
22990
- var app41 = new Hono();
22991
- app41.get("/", async (c) => {
23081
+ var app42 = new Hono();
23082
+ app42.get("/", async (c) => {
22992
23083
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
22993
23084
  if (!isLoopbackAddr4(remoteAddr)) {
22994
23085
  console.error(`${TAG35} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -23028,7 +23119,7 @@ app41.get("/", async (c) => {
23028
23119
  await session.close();
23029
23120
  }
23030
23121
  });
23031
- var public_session_context_default = app41;
23122
+ var public_session_context_default = app42;
23032
23123
 
23033
23124
  // app/lib/webchat/gateway/instance.ts
23034
23125
  var instance2 = null;
@@ -23044,8 +23135,8 @@ var TAG36 = "[public-session-exit-route]";
23044
23135
  function isLoopbackAddr5(addr) {
23045
23136
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23046
23137
  }
23047
- var app42 = new Hono();
23048
- app42.post("/", async (c) => {
23138
+ var app43 = new Hono();
23139
+ app43.post("/", async (c) => {
23049
23140
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23050
23141
  if (!isLoopbackAddr5(remoteAddr)) {
23051
23142
  console.error(`${TAG36} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -23077,15 +23168,15 @@ app42.post("/", async (c) => {
23077
23168
  gateway.handlePublicSessionExit(sessionId);
23078
23169
  return c.json({ ok: true });
23079
23170
  });
23080
- var public_session_exit_default = app42;
23171
+ var public_session_exit_default = app43;
23081
23172
 
23082
23173
  // server/routes/admin/access-session-evict.ts
23083
23174
  var TAG37 = "[access-session-evict]";
23084
23175
  function isLoopbackAddr6(addr) {
23085
23176
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23086
23177
  }
23087
- var app43 = new Hono();
23088
- app43.post("/", async (c) => {
23178
+ var app44 = new Hono();
23179
+ app44.post("/", async (c) => {
23089
23180
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23090
23181
  if (!isLoopbackAddr6(remoteAddr)) {
23091
23182
  console.error(`${TAG37} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -23113,7 +23204,7 @@ app43.post("/", async (c) => {
23113
23204
  console.log(`${TAG37} grantId=${grantId} dropped=${dropped}`);
23114
23205
  return c.json({ ok: true, dropped });
23115
23206
  });
23116
- var access_session_evict_default = app43;
23207
+ var access_session_evict_default = app44;
23117
23208
 
23118
23209
  // server/routes/admin/enrol-person.ts
23119
23210
  var TAG38 = "[enrol]";
@@ -23121,8 +23212,8 @@ function isLoopbackAddr7(addr) {
23121
23212
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23122
23213
  }
23123
23214
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
23124
- var app44 = new Hono();
23125
- app44.post("/", async (c) => {
23215
+ var app45 = new Hono();
23216
+ app45.post("/", async (c) => {
23126
23217
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23127
23218
  if (!isLoopbackAddr7(remoteAddr)) {
23128
23219
  console.error(`${TAG38} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -23185,11 +23276,11 @@ app44.post("/", async (c) => {
23185
23276
  );
23186
23277
  return c.json({ personId, grant }, 200);
23187
23278
  });
23188
- var enrol_person_default = app44;
23279
+ var enrol_person_default = app45;
23189
23280
 
23190
23281
  // server/routes/admin/browser.ts
23191
- var app45 = new Hono();
23192
- app45.post("/launch", requireAdminSession, async (c) => {
23282
+ var app46 = new Hono();
23283
+ app46.post("/launch", requireAdminSession, async (c) => {
23193
23284
  try {
23194
23285
  if (process.platform !== "linux") {
23195
23286
  console.error("[admin/browser/launch] op=skipped platform=darwin reason=no-display-stack");
@@ -23224,10 +23315,10 @@ app45.post("/launch", requireAdminSession, async (c) => {
23224
23315
  );
23225
23316
  }
23226
23317
  });
23227
- var browser_default = app45;
23318
+ var browser_default = app46;
23228
23319
 
23229
23320
  // server/routes/admin/calendar.ts
23230
- import { existsSync as existsSync35 } from "fs";
23321
+ import { existsSync as existsSync37 } from "fs";
23231
23322
  import { join as join42 } from "path";
23232
23323
 
23233
23324
  // server/lib/calendar-ics.ts
@@ -23370,7 +23461,7 @@ function readAvailabilityConfig(accountDir) {
23370
23461
  }
23371
23462
 
23372
23463
  // server/routes/admin/calendar.ts
23373
- var app46 = new Hono();
23464
+ var app47 = new Hono();
23374
23465
  function normalizeAttendees(raw) {
23375
23466
  if (!Array.isArray(raw)) return [];
23376
23467
  return raw.map((a) => {
@@ -23401,7 +23492,7 @@ function mapMeeting(r) {
23401
23492
  privateNote: r.get("privateNote")
23402
23493
  };
23403
23494
  }
23404
- app46.get("/meetings", requireAdminSession, async (c) => {
23495
+ app47.get("/meetings", requireAdminSession, async (c) => {
23405
23496
  const cacheKey = c.var.cacheKey;
23406
23497
  const accountId = getAccountIdForSession(cacheKey);
23407
23498
  if (!accountId) {
@@ -23464,7 +23555,7 @@ function icsFilename(title) {
23464
23555
  const slug = (title ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
23465
23556
  return `${slug || "meeting"}.ics`;
23466
23557
  }
23467
- app46.get("/meetings/:id/ics", requireAdminSession, async (c) => {
23558
+ app47.get("/meetings/:id/ics", requireAdminSession, async (c) => {
23468
23559
  const cacheKey = c.var.cacheKey;
23469
23560
  const accountId = getAccountIdForSession(cacheKey);
23470
23561
  if (!accountId) {
@@ -23522,7 +23613,7 @@ app46.get("/meetings/:id/ics", requireAdminSession, async (c) => {
23522
23613
  await session.close();
23523
23614
  }
23524
23615
  });
23525
- app46.patch("/meetings/:id", requireAdminSession, async (c) => {
23616
+ app47.patch("/meetings/:id", requireAdminSession, async (c) => {
23526
23617
  const cacheKey = c.var.cacheKey;
23527
23618
  const accountId = getAccountIdForSession(cacheKey);
23528
23619
  if (!accountId) {
@@ -23566,7 +23657,7 @@ app46.patch("/meetings/:id", requireAdminSession, async (c) => {
23566
23657
  await session.close();
23567
23658
  }
23568
23659
  });
23569
- app46.post("/meetings/:id/attendees", requireAdminSession, async (c) => {
23660
+ app47.post("/meetings/:id/attendees", requireAdminSession, async (c) => {
23570
23661
  const cacheKey = c.var.cacheKey;
23571
23662
  const accountId = getAccountIdForSession(cacheKey);
23572
23663
  if (!accountId) {
@@ -23616,7 +23707,7 @@ app46.post("/meetings/:id/attendees", requireAdminSession, async (c) => {
23616
23707
  await session.close();
23617
23708
  }
23618
23709
  });
23619
- app46.delete("/meetings/:id/attendees", requireAdminSession, async (c) => {
23710
+ app47.delete("/meetings/:id/attendees", requireAdminSession, async (c) => {
23620
23711
  const cacheKey = c.var.cacheKey;
23621
23712
  const accountId = getAccountIdForSession(cacheKey);
23622
23713
  if (!accountId) {
@@ -23662,7 +23753,7 @@ app46.delete("/meetings/:id/attendees", requireAdminSession, async (c) => {
23662
23753
  await session.close();
23663
23754
  }
23664
23755
  });
23665
- app46.delete("/meetings/:id", requireAdminSession, async (c) => {
23756
+ app47.delete("/meetings/:id", requireAdminSession, async (c) => {
23666
23757
  const cacheKey = c.var.cacheKey;
23667
23758
  const accountId = getAccountIdForSession(cacheKey);
23668
23759
  if (!accountId) {
@@ -23692,14 +23783,14 @@ app46.delete("/meetings/:id", requireAdminSession, async (c) => {
23692
23783
  await session.close();
23693
23784
  }
23694
23785
  });
23695
- app46.get("/booking-link", requireAdminSession, (c) => {
23786
+ app47.get("/booking-link", requireAdminSession, (c) => {
23696
23787
  try {
23697
23788
  const account = resolveAccount();
23698
23789
  if (!account) {
23699
23790
  console.error('[calendar] op=booking-link-fail err="no account configured"');
23700
23791
  return c.json({ bookingDomain: null });
23701
23792
  }
23702
- if (!existsSync35(join42(account.accountDir, AVAILABILITY_FILENAME))) {
23793
+ if (!existsSync37(join42(account.accountDir, AVAILABILITY_FILENAME))) {
23703
23794
  console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
23704
23795
  return c.json({ bookingDomain: null });
23705
23796
  }
@@ -23715,12 +23806,12 @@ app46.get("/booking-link", requireAdminSession, (c) => {
23715
23806
  return c.json({ bookingDomain: null });
23716
23807
  }
23717
23808
  });
23718
- var calendar_default = app46;
23809
+ var calendar_default = app47;
23719
23810
 
23720
23811
  // server/routes/admin/routines.ts
23721
23812
  import cronParser from "cron-parser";
23722
23813
  var { parseExpression } = cronParser;
23723
- var app47 = new Hono();
23814
+ var app48 = new Hono();
23724
23815
  var AUTOMATION_WHERE = "(e.recurrence IS NOT NULL OR e.agentChannel IS NOT NULL OR e.actionPlugin IS NOT NULL)";
23725
23816
  var ROUTINE_COLS = `e.eventId AS eventId, e.name AS name, e.eventStatus AS eventStatus,
23726
23817
  e.recurrence AS recurrence, e.nextRun AS nextRun, e.lastTriggered AS lastTriggered,
@@ -23750,7 +23841,7 @@ function mapRoutine(r) {
23750
23841
  lastDispatchAt: g("lastDispatchAt")
23751
23842
  };
23752
23843
  }
23753
- app47.get("/", requireAdminSession, async (c) => {
23844
+ app48.get("/", requireAdminSession, async (c) => {
23754
23845
  const accountId = getAccountIdForSession(c.var.cacheKey);
23755
23846
  if (!accountId) {
23756
23847
  console.error('[admin:routines] op=list auth-rejected reason="no account for session"');
@@ -23776,7 +23867,7 @@ app47.get("/", requireAdminSession, async (c) => {
23776
23867
  await session.close();
23777
23868
  }
23778
23869
  });
23779
- app47.get("/:eventId", requireAdminSession, async (c) => {
23870
+ app48.get("/:eventId", requireAdminSession, async (c) => {
23780
23871
  const accountId = getAccountIdForSession(c.var.cacheKey);
23781
23872
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
23782
23873
  const eventId = c.req.param("eventId");
@@ -23800,7 +23891,7 @@ app47.get("/:eventId", requireAdminSession, async (c) => {
23800
23891
  await session.close();
23801
23892
  }
23802
23893
  });
23803
- app47.patch("/:eventId", requireAdminSession, async (c) => {
23894
+ app48.patch("/:eventId", requireAdminSession, async (c) => {
23804
23895
  const accountId = getAccountIdForSession(c.var.cacheKey);
23805
23896
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
23806
23897
  const eventId = c.req.param("eventId");
@@ -23870,7 +23961,7 @@ app47.patch("/:eventId", requireAdminSession, async (c) => {
23870
23961
  await session.close();
23871
23962
  }
23872
23963
  });
23873
- app47.delete("/:eventId", requireAdminSession, async (c) => {
23964
+ app48.delete("/:eventId", requireAdminSession, async (c) => {
23874
23965
  const accountId = getAccountIdForSession(c.var.cacheKey);
23875
23966
  if (!accountId) {
23876
23967
  console.error('[admin:routines] op=delete auth-rejected reason="no account for session"');
@@ -23898,12 +23989,12 @@ app47.delete("/:eventId", requireAdminSession, async (c) => {
23898
23989
  await session.close();
23899
23990
  }
23900
23991
  });
23901
- var routines_default = app47;
23992
+ var routines_default = app48;
23902
23993
 
23903
23994
  // server/routes/admin/skills.ts
23904
- import { existsSync as existsSync36, readdirSync as readdirSync24, readFileSync as readFileSync39, rmSync as rmSync3 } from "fs";
23905
- import { resolve as resolve31 } from "path";
23906
- var app48 = new Hono();
23995
+ import { existsSync as existsSync38, readdirSync as readdirSync24, readFileSync as readFileSync39, rmSync as rmSync3 } from "fs";
23996
+ import { resolve as resolve32 } from "path";
23997
+ var app49 = new Hono();
23907
23998
  var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
23908
23999
  function splitSkillMd(text) {
23909
24000
  const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
@@ -23931,32 +24022,32 @@ function accountDirForSession(cacheKey) {
23931
24022
  return match ? { accountId, accountDir: match.accountDir } : null;
23932
24023
  }
23933
24024
  function subdirs(dir) {
23934
- if (!existsSync36(dir)) return [];
24025
+ if (!existsSync38(dir)) return [];
23935
24026
  try {
23936
24027
  return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
23937
24028
  } catch {
23938
24029
  return [];
23939
24030
  }
23940
24031
  }
23941
- app48.get("/", requireAdminSession, async (c) => {
24032
+ app49.get("/", requireAdminSession, async (c) => {
23942
24033
  const acct = accountDirForSession(c.var.cacheKey);
23943
24034
  if (!acct) {
23944
24035
  console.error('[admin:skills] op=list auth-rejected reason="no account for session"');
23945
24036
  return c.json({ error: "Account not found for session" }, 401);
23946
24037
  }
23947
- const pluginsDir = resolve31(acct.accountDir, "plugins");
24038
+ const pluginsDir = resolve32(acct.accountDir, "plugins");
23948
24039
  const skills = [];
23949
24040
  let pluginCount = 0;
23950
24041
  for (const plugin of subdirs(pluginsDir)) {
23951
24042
  pluginCount++;
23952
- const skillsDir = resolve31(pluginsDir, plugin, "skills");
24043
+ const skillsDir = resolve32(pluginsDir, plugin, "skills");
23953
24044
  for (const skill of subdirs(skillsDir)) {
23954
- const skillMd = resolve31(skillsDir, skill, "SKILL.md");
23955
- if (!existsSync36(skillMd)) continue;
24045
+ const skillMd = resolve32(skillsDir, skill, "SKILL.md");
24046
+ if (!existsSync38(skillMd)) continue;
23956
24047
  try {
23957
24048
  const { frontmatter } = splitSkillMd(readFileSync39(skillMd, "utf-8"));
23958
- const refsDir = resolve31(skillsDir, skill, "references");
23959
- const refCount = existsSync36(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
24049
+ const refsDir = resolve32(skillsDir, skill, "references");
24050
+ const refCount = existsSync38(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
23960
24051
  skills.push({ plugin, skill, description: frontmatter.description, refCount });
23961
24052
  } catch (err) {
23962
24053
  console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
@@ -23967,7 +24058,7 @@ app48.get("/", requireAdminSession, async (c) => {
23967
24058
  console.log(`[admin:skills] op=list accountId=${acct.accountId.slice(0, 8)} plugins=${pluginCount} skills=${skills.length}`);
23968
24059
  return c.json({ skills });
23969
24060
  });
23970
- app48.get("/:plugin/:skill", requireAdminSession, async (c) => {
24061
+ app49.get("/:plugin/:skill", requireAdminSession, async (c) => {
23971
24062
  const acct = accountDirForSession(c.var.cacheKey);
23972
24063
  if (!acct) return c.json({ error: "Account not found for session" }, 401);
23973
24064
  const plugin = c.req.param("plugin");
@@ -23976,15 +24067,15 @@ app48.get("/:plugin/:skill", requireAdminSession, async (c) => {
23976
24067
  console.error(`[admin:skills] op=get outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
23977
24068
  return c.json({ error: "Invalid plugin or skill name" }, 400);
23978
24069
  }
23979
- const skillDir = resolve31(acct.accountDir, "plugins", plugin, "skills", skill);
23980
- const skillMd = resolve31(skillDir, "SKILL.md");
23981
- const found = existsSync36(skillMd);
24070
+ const skillDir = resolve32(acct.accountDir, "plugins", plugin, "skills", skill);
24071
+ const skillMd = resolve32(skillDir, "SKILL.md");
24072
+ const found = existsSync38(skillMd);
23982
24073
  console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
23983
24074
  if (!found) return c.json({ error: "Skill not found" }, 404);
23984
24075
  try {
23985
24076
  const { frontmatter, body } = splitSkillMd(readFileSync39(skillMd, "utf-8"));
23986
- const refsDir = resolve31(skillDir, "references");
23987
- const references = existsSync36(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
24077
+ const refsDir = resolve32(skillDir, "references");
24078
+ const references = existsSync38(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
23988
24079
  return c.json({ skill: { plugin, skill, frontmatter, body, references } });
23989
24080
  } catch (err) {
23990
24081
  const message = err instanceof Error ? err.message : String(err);
@@ -23992,7 +24083,7 @@ app48.get("/:plugin/:skill", requireAdminSession, async (c) => {
23992
24083
  return c.json({ error: `Skill unavailable: ${message}` }, 503);
23993
24084
  }
23994
24085
  });
23995
- app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
24086
+ app49.delete("/:plugin/:skill", requireAdminSession, async (c) => {
23996
24087
  const acct = accountDirForSession(c.var.cacheKey);
23997
24088
  if (!acct) return c.json({ error: "Account not found for session" }, 401);
23998
24089
  const plugin = c.req.param("plugin");
@@ -24001,10 +24092,10 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
24001
24092
  console.error(`[admin:skills] op=delete outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
24002
24093
  return c.json({ error: "Invalid plugin or skill name" }, 400);
24003
24094
  }
24004
- const pluginDir = resolve31(acct.accountDir, "plugins", plugin);
24005
- const skillsDir = resolve31(pluginDir, "skills");
24006
- const skillDir = resolve31(skillsDir, skill);
24007
- if (!existsSync36(resolve31(skillDir, "SKILL.md"))) {
24095
+ const pluginDir = resolve32(acct.accountDir, "plugins", plugin);
24096
+ const skillsDir = resolve32(pluginDir, "skills");
24097
+ const skillDir = resolve32(skillsDir, skill);
24098
+ if (!existsSync38(resolve32(skillDir, "SKILL.md"))) {
24008
24099
  console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
24009
24100
  return c.json({ error: "Skill not found" }, 404);
24010
24101
  }
@@ -24012,7 +24103,7 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
24012
24103
  rmSync3(skillDir, { recursive: true, force: true });
24013
24104
  const pluginDirRemoved = subdirs(skillsDir).length === 0;
24014
24105
  if (pluginDirRemoved) rmSync3(pluginDir, { recursive: true, force: true });
24015
- const skillDirGone = !existsSync36(skillDir);
24106
+ const skillDirGone = !existsSync38(skillDir);
24016
24107
  if (!skillDirGone) {
24017
24108
  console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
24018
24109
  return c.json({ error: "Delete did not remove the skill directory" }, 503);
@@ -24025,7 +24116,7 @@ app48.delete("/:plugin/:skill", requireAdminSession, async (c) => {
24025
24116
  return c.json({ error: `Delete failed: ${message}` }, 503);
24026
24117
  }
24027
24118
  });
24028
- var skills_default = app48;
24119
+ var skills_default = app49;
24029
24120
 
24030
24121
  // app/lib/time-entry-format.ts
24031
24122
  function secondsBetween(startIso, endIso) {
@@ -24048,8 +24139,8 @@ function toNum(v) {
24048
24139
  var TAG39 = "[task-timer]";
24049
24140
  var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
24050
24141
  var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
24051
- var app49 = new Hono();
24052
- app49.get("/", requireAdminSession, async (c) => {
24142
+ var app50 = new Hono();
24143
+ app50.get("/", requireAdminSession, async (c) => {
24053
24144
  const cacheKey = c.var.cacheKey;
24054
24145
  const accountId = getAccountIdForSession(cacheKey);
24055
24146
  if (!accountId) {
@@ -24136,13 +24227,13 @@ app49.get("/", requireAdminSession, async (c) => {
24136
24227
  await session.close();
24137
24228
  }
24138
24229
  });
24139
- var tasks_list_default = app49;
24230
+ var tasks_list_default = app50;
24140
24231
 
24141
24232
  // server/routes/admin/task-timer-start.ts
24142
24233
  import { randomUUID as randomUUID14 } from "crypto";
24143
24234
  var TAG40 = "[task-timer]";
24144
- var app50 = new Hono();
24145
- app50.post("/", requireAdminSession, async (c) => {
24235
+ var app51 = new Hono();
24236
+ app51.post("/", requireAdminSession, async (c) => {
24146
24237
  const cacheKey = c.var.cacheKey;
24147
24238
  const accountId = getAccountIdForSession(cacheKey);
24148
24239
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -24197,13 +24288,13 @@ app50.post("/", requireAdminSession, async (c) => {
24197
24288
  await session.close();
24198
24289
  }
24199
24290
  });
24200
- var task_timer_start_default = app50;
24291
+ var task_timer_start_default = app51;
24201
24292
 
24202
24293
  // server/routes/admin/task-timer-stop.ts
24203
24294
  import neo4j5 from "neo4j-driver";
24204
24295
  var TAG41 = "[task-timer]";
24205
- var app51 = new Hono();
24206
- app51.post("/", requireAdminSession, async (c) => {
24296
+ var app52 = new Hono();
24297
+ app52.post("/", requireAdminSession, async (c) => {
24207
24298
  const cacheKey = c.var.cacheKey;
24208
24299
  const accountId = getAccountIdForSession(cacheKey);
24209
24300
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -24270,12 +24361,12 @@ app51.post("/", requireAdminSession, async (c) => {
24270
24361
  await session.close();
24271
24362
  }
24272
24363
  });
24273
- var task_timer_stop_default = app51;
24364
+ var task_timer_stop_default = app52;
24274
24365
 
24275
24366
  // server/routes/admin/task-complete.ts
24276
24367
  var TAG42 = "[task-timer]";
24277
- var app52 = new Hono();
24278
- app52.post("/", requireAdminSession, async (c) => {
24368
+ var app53 = new Hono();
24369
+ app53.post("/", requireAdminSession, async (c) => {
24279
24370
  const cacheKey = c.var.cacheKey;
24280
24371
  const accountId = getAccountIdForSession(cacheKey);
24281
24372
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -24313,14 +24404,14 @@ app52.post("/", requireAdminSession, async (c) => {
24313
24404
  await session.close();
24314
24405
  }
24315
24406
  });
24316
- var task_complete_default = app52;
24407
+ var task_complete_default = app53;
24317
24408
 
24318
24409
  // server/routes/admin/task-time-adjust.ts
24319
24410
  import { randomUUID as randomUUID15 } from "crypto";
24320
24411
  import neo4j6 from "neo4j-driver";
24321
24412
  var TAG43 = "[task-time-adjust]";
24322
- var app53 = new Hono();
24323
- app53.post("/", requireAdminSession, async (c) => {
24413
+ var app54 = new Hono();
24414
+ app54.post("/", requireAdminSession, async (c) => {
24324
24415
  const cacheKey = c.var.cacheKey;
24325
24416
  const accountId = getAccountIdForSession(cacheKey);
24326
24417
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -24394,11 +24485,11 @@ app53.post("/", requireAdminSession, async (c) => {
24394
24485
  await session.close();
24395
24486
  }
24396
24487
  });
24397
- var task_time_adjust_default = app53;
24488
+ var task_time_adjust_default = app54;
24398
24489
 
24399
24490
  // server/routes/admin/activity.ts
24400
24491
  import { readdirSync as readdirSync25 } from "fs";
24401
- var app54 = new Hono();
24492
+ var app55 = new Hono();
24402
24493
  var TAG44 = "[activity]";
24403
24494
  function resolveHouseAccountId(accounts) {
24404
24495
  const houses = accounts.filter((a) => a.config.role === "house");
@@ -24420,7 +24511,7 @@ function countAccountDirsOnDisk() {
24420
24511
  return null;
24421
24512
  }
24422
24513
  }
24423
- app54.get("/", requireAdminSession, async (c) => {
24514
+ app55.get("/", requireAdminSession, async (c) => {
24424
24515
  const req = requestToken();
24425
24516
  const cacheKey = c.var.cacheKey;
24426
24517
  const caller2 = getAccountIdForSession(cacheKey) ?? null;
@@ -24529,62 +24620,63 @@ app54.get("/", requireAdminSession, async (c) => {
24529
24620
  }
24530
24621
  });
24531
24622
  });
24532
- var activity_default = app54;
24623
+ var activity_default = app55;
24533
24624
 
24534
24625
  // server/routes/admin/index.ts
24535
- var app55 = new Hono();
24536
- app55.route("/session", session_default);
24537
- app55.route("/accounts", accounts_default);
24538
- app55.route("/logs", logs_default);
24539
- app55.route("/claude-info", claude_info_default);
24540
- app55.route("/attachment", attachment_default);
24541
- app55.route("/agents", agents_default);
24542
- app55.route("/sessions", sessions_default);
24543
- app55.route("/claude-sessions", claude_sessions_default);
24544
- app55.route("/log-ingest", log_ingest_default);
24545
- app55.route("/events", events_default);
24546
- app55.route("/files", files_default);
24547
- app55.route("/graph-search", graph_search_default);
24548
- app55.route("/graph-subgraph", graph_subgraph_default);
24549
- app55.route("/graph-delete", graph_delete_default);
24550
- app55.route("/graph-restore", graph_restore_default);
24551
- app55.route("/graph-labels-in-graph", graph_labels_in_graph_default);
24552
- app55.route("/graph-default-view", graph_default_view_default);
24553
- app55.route("/sidebar-artefacts", sidebar_artefacts_default);
24554
- app55.route("/sidebar-sessions", sidebar_sessions_default);
24555
- app55.route("/session-delete", session_delete_default);
24556
- app55.route("/session-stop", session_stop_default);
24557
- app55.route("/session-archive", session_archive_default);
24558
- app55.route("/session-rename", session_rename_default);
24559
- app55.route("/session-usage", session_usage_default);
24560
- app55.route("/browser", browser_default);
24561
- app55.route("/session-rc-spawn", session_rc_spawn_default);
24562
- app55.route("/session-reseat", session_reseat_default);
24563
- app55.route("/system-stats", system_stats_default);
24564
- app55.route("/health-brand", health_default2);
24565
- app55.route("/linkedin-ingest", linkedin_ingest_default);
24566
- app55.route("/post-turn-context", post_turn_context_default);
24567
- app55.route("/public-session-context", public_session_context_default);
24568
- app55.route("/public-session-exit", public_session_exit_default);
24569
- app55.route("/access-session-evict", access_session_evict_default);
24570
- app55.route("/enrol-person", enrol_person_default);
24571
- app55.route("/calendar", calendar_default);
24572
- app55.route("/routines", routines_default);
24573
- app55.route("/skills", skills_default);
24574
- app55.route("/tasks-list", tasks_list_default);
24575
- app55.route("/task-timer-start", task_timer_start_default);
24576
- app55.route("/task-timer-stop", task_timer_stop_default);
24577
- app55.route("/task-complete", task_complete_default);
24578
- app55.route("/task-time-adjust", task_time_adjust_default);
24579
- app55.route("/activity", activity_default);
24580
- var admin_default = app55;
24626
+ var app56 = new Hono();
24627
+ app56.route("/session", session_default);
24628
+ app56.route("/accounts", accounts_default);
24629
+ app56.route("/logs", logs_default);
24630
+ app56.route("/claude-info", claude_info_default);
24631
+ app56.route("/attachment", attachment_default);
24632
+ app56.route("/session-upload", session_upload_default);
24633
+ app56.route("/agents", agents_default);
24634
+ app56.route("/sessions", sessions_default);
24635
+ app56.route("/claude-sessions", claude_sessions_default);
24636
+ app56.route("/log-ingest", log_ingest_default);
24637
+ app56.route("/events", events_default);
24638
+ app56.route("/files", files_default);
24639
+ app56.route("/graph-search", graph_search_default);
24640
+ app56.route("/graph-subgraph", graph_subgraph_default);
24641
+ app56.route("/graph-delete", graph_delete_default);
24642
+ app56.route("/graph-restore", graph_restore_default);
24643
+ app56.route("/graph-labels-in-graph", graph_labels_in_graph_default);
24644
+ app56.route("/graph-default-view", graph_default_view_default);
24645
+ app56.route("/sidebar-artefacts", sidebar_artefacts_default);
24646
+ app56.route("/sidebar-sessions", sidebar_sessions_default);
24647
+ app56.route("/session-delete", session_delete_default);
24648
+ app56.route("/session-stop", session_stop_default);
24649
+ app56.route("/session-archive", session_archive_default);
24650
+ app56.route("/session-rename", session_rename_default);
24651
+ app56.route("/session-usage", session_usage_default);
24652
+ app56.route("/browser", browser_default);
24653
+ app56.route("/session-rc-spawn", session_rc_spawn_default);
24654
+ app56.route("/session-reseat", session_reseat_default);
24655
+ app56.route("/system-stats", system_stats_default);
24656
+ app56.route("/health-brand", health_default2);
24657
+ app56.route("/linkedin-ingest", linkedin_ingest_default);
24658
+ app56.route("/post-turn-context", post_turn_context_default);
24659
+ app56.route("/public-session-context", public_session_context_default);
24660
+ app56.route("/public-session-exit", public_session_exit_default);
24661
+ app56.route("/access-session-evict", access_session_evict_default);
24662
+ app56.route("/enrol-person", enrol_person_default);
24663
+ app56.route("/calendar", calendar_default);
24664
+ app56.route("/routines", routines_default);
24665
+ app56.route("/skills", skills_default);
24666
+ app56.route("/tasks-list", tasks_list_default);
24667
+ app56.route("/task-timer-start", task_timer_start_default);
24668
+ app56.route("/task-timer-stop", task_timer_stop_default);
24669
+ app56.route("/task-complete", task_complete_default);
24670
+ app56.route("/task-time-adjust", task_time_adjust_default);
24671
+ app56.route("/activity", activity_default);
24672
+ var admin_default = app56;
24581
24673
 
24582
24674
  // server/routes/access/verify-token.ts
24583
24675
  var TAG45 = "[access-verify]";
24584
24676
  var MINT_TAG = "[access-session-mint]";
24585
24677
  var COOKIE_NAME = "__access_session";
24586
- var app56 = new Hono();
24587
- app56.post("/", async (c) => {
24678
+ var app57 = new Hono();
24679
+ app57.post("/", async (c) => {
24588
24680
  const ip = c.var.clientIp || "unknown";
24589
24681
  let body;
24590
24682
  try {
@@ -24666,13 +24758,13 @@ app56.post("/", async (c) => {
24666
24758
  displayName: grant.displayName
24667
24759
  });
24668
24760
  });
24669
- var verify_token_default = app56;
24761
+ var verify_token_default = app57;
24670
24762
 
24671
24763
  // app/lib/access-email.ts
24672
24764
  import { spawn as spawn2 } from "child_process";
24673
- import { resolve as resolve32 } from "path";
24674
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve32(process.cwd(), "..");
24675
- var SEND_SCRIPT = resolve32(
24765
+ import { resolve as resolve33 } from "path";
24766
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve33(process.cwd(), "..");
24767
+ var SEND_SCRIPT = resolve33(
24676
24768
  PLATFORM_ROOT7,
24677
24769
  "plugins",
24678
24770
  "email",
@@ -24729,9 +24821,9 @@ async function sendMagicLinkEmail(payload) {
24729
24821
 
24730
24822
  // server/routes/access/request-magic-link.ts
24731
24823
  var TAG46 = "[access-request-link]";
24732
- var app57 = new Hono();
24824
+ var app58 = new Hono();
24733
24825
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
24734
- app57.post("/", async (c) => {
24826
+ app58.post("/", async (c) => {
24735
24827
  let body;
24736
24828
  try {
24737
24829
  body = await c.req.json();
@@ -24805,17 +24897,17 @@ app57.post("/", async (c) => {
24805
24897
  );
24806
24898
  return c.json({ message: VISITOR_MESSAGE }, 200);
24807
24899
  });
24808
- var request_magic_link_default = app57;
24900
+ var request_magic_link_default = app58;
24809
24901
 
24810
24902
  // server/routes/access/index.ts
24811
- var app58 = new Hono();
24812
- app58.route("/verify-token", verify_token_default);
24813
- app58.route("/request-magic-link", request_magic_link_default);
24814
- var access_default = app58;
24903
+ var app59 = new Hono();
24904
+ app59.route("/verify-token", verify_token_default);
24905
+ app59.route("/request-magic-link", request_magic_link_default);
24906
+ var access_default = app59;
24815
24907
 
24816
24908
  // server/routes/sites.ts
24817
- import { existsSync as existsSync37, readFileSync as readFileSync40, realpathSync as realpathSync7, statSync as statSync15 } from "fs";
24818
- import { resolve as resolve33 } from "path";
24909
+ import { existsSync as existsSync39, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync17 } from "fs";
24910
+ import { resolve as resolve34 } from "path";
24819
24911
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
24820
24912
  var MIME = {
24821
24913
  ".html": "text/html; charset=utf-8",
@@ -24846,8 +24938,8 @@ function getExt(p) {
24846
24938
  if (idx < p.lastIndexOf("/")) return "";
24847
24939
  return p.slice(idx).toLowerCase();
24848
24940
  }
24849
- var app59 = new Hono();
24850
- app59.get("/:rel{.*}", (c) => {
24941
+ var app60 = new Hono();
24942
+ app60.get("/:rel{.*}", (c) => {
24851
24943
  const reqPath = c.req.path;
24852
24944
  const rawRel = c.req.param("rel") ?? "";
24853
24945
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -24872,15 +24964,15 @@ app59.get("/:rel{.*}", (c) => {
24872
24964
  }
24873
24965
  segments.push(seg);
24874
24966
  }
24875
- const rootDir = resolve33(account.accountDir, "sites");
24876
- let filePath = segments.length === 0 ? rootDir : resolve33(rootDir, ...segments);
24967
+ const rootDir = resolve34(account.accountDir, "sites");
24968
+ let filePath = segments.length === 0 ? rootDir : resolve34(rootDir, ...segments);
24877
24969
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
24878
24970
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24879
24971
  return c.text("Forbidden", 403);
24880
24972
  }
24881
24973
  let stat11;
24882
24974
  try {
24883
- stat11 = existsSync37(filePath) ? statSync15(filePath) : null;
24975
+ stat11 = existsSync39(filePath) ? statSync17(filePath) : null;
24884
24976
  } catch {
24885
24977
  stat11 = null;
24886
24978
  }
@@ -24893,21 +24985,21 @@ app59.get("/:rel{.*}", (c) => {
24893
24985
  return c.redirect(target, 301);
24894
24986
  }
24895
24987
  if (stat11?.isDirectory()) {
24896
- filePath = resolve33(filePath, "index.html");
24988
+ filePath = resolve34(filePath, "index.html");
24897
24989
  }
24898
24990
  if (!filePath.startsWith(rootDir + "/")) {
24899
24991
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24900
24992
  return c.text("Forbidden", 403);
24901
24993
  }
24902
- if (!existsSync37(filePath)) {
24994
+ if (!existsSync39(filePath)) {
24903
24995
  console.error(`[sites] not-found path=${reqPath} status=404`);
24904
24996
  return c.text("Not found", 404);
24905
24997
  }
24906
24998
  let realPath;
24907
24999
  let realRoot;
24908
25000
  try {
24909
- realPath = realpathSync7(filePath);
24910
- realRoot = realpathSync7(rootDir);
25001
+ realPath = realpathSync8(filePath);
25002
+ realRoot = realpathSync8(rootDir);
24911
25003
  } catch {
24912
25004
  console.error(`[sites] not-found path=${reqPath} status=404`);
24913
25005
  return c.text("Not found", 404);
@@ -24950,12 +25042,12 @@ app59.get("/:rel{.*}", (c) => {
24950
25042
  "X-Content-Type-Options": "nosniff"
24951
25043
  });
24952
25044
  });
24953
- var sites_default = app59;
25045
+ var sites_default = app60;
24954
25046
 
24955
25047
  // app/lib/visitor-token.ts
24956
25048
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
24957
25049
  import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync14 } from "fs";
24958
- import { dirname as dirname13 } from "path";
25050
+ import { dirname as dirname14 } from "path";
24959
25051
  var TOKEN_PREFIX = "v1.";
24960
25052
  var SECRET_BYTES = 32;
24961
25053
  var DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -24972,7 +25064,7 @@ function getSecret() {
24972
25064
  }
24973
25065
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
24974
25066
  try {
24975
- mkdirSync8(dirname13(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
25067
+ mkdirSync8(dirname14(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
24976
25068
  writeFileSync14(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
24977
25069
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
24978
25070
  } catch {
@@ -25030,7 +25122,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
25030
25122
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
25031
25123
 
25032
25124
  // app/lib/brand-config.ts
25033
- import { existsSync as existsSync38, readFileSync as readFileSync42 } from "fs";
25125
+ import { existsSync as existsSync40, readFileSync as readFileSync42 } from "fs";
25034
25126
  import { join as join43 } from "path";
25035
25127
  var cached2 = null;
25036
25128
  var cachedAttempted = false;
@@ -25040,7 +25132,7 @@ function readBrandConfig() {
25040
25132
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
25041
25133
  if (!platformRoot5) return null;
25042
25134
  const brandPath = join43(platformRoot5, "config", "brand.json");
25043
- if (!existsSync38(brandPath)) return null;
25135
+ if (!existsSync40(brandPath)) return null;
25044
25136
  try {
25045
25137
  cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
25046
25138
  return cached2;
@@ -25050,7 +25142,7 @@ function readBrandConfig() {
25050
25142
  }
25051
25143
 
25052
25144
  // server/routes/visitor-consent.ts
25053
- var app60 = new Hono();
25145
+ var app61 = new Hono();
25054
25146
  var CONSENT_COOKIE_NAME = "mxy_consent";
25055
25147
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
25056
25148
  var DEFAULT_CONSENT_COPY = {
@@ -25095,17 +25187,17 @@ function siteSlugFromReferer(referer) {
25095
25187
  return "";
25096
25188
  }
25097
25189
  }
25098
- app60.options("/consent", (c) => {
25190
+ app61.options("/consent", (c) => {
25099
25191
  const origin = getOrigin(c);
25100
25192
  setCorsHeaders(c, origin);
25101
25193
  return c.body(null, 204);
25102
25194
  });
25103
- app60.options("/brand-config", (c) => {
25195
+ app61.options("/brand-config", (c) => {
25104
25196
  const origin = getOrigin(c);
25105
25197
  setCorsHeaders(c, origin);
25106
25198
  return c.body(null, 204);
25107
25199
  });
25108
- app60.post("/consent", async (c) => {
25200
+ app61.post("/consent", async (c) => {
25109
25201
  const origin = getOrigin(c);
25110
25202
  setCorsHeaders(c, origin);
25111
25203
  let raw;
@@ -25145,7 +25237,7 @@ app60.post("/consent", async (c) => {
25145
25237
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
25146
25238
  return c.body(null, 204);
25147
25239
  });
25148
- app60.get("/brand-config", (c) => {
25240
+ app61.get("/brand-config", (c) => {
25149
25241
  const origin = getOrigin(c);
25150
25242
  setCorsHeaders(c, origin);
25151
25243
  const brand = readBrandConfig();
@@ -25155,7 +25247,7 @@ app60.get("/brand-config", (c) => {
25155
25247
  c.header("Cache-Control", "public, max-age=300");
25156
25248
  return c.json({ consent: { copy, palette } });
25157
25249
  });
25158
- var visitor_consent_default = app60;
25250
+ var visitor_consent_default = app61;
25159
25251
 
25160
25252
  // server/routes/listings.ts
25161
25253
  function getCookie(headerValue, name) {
@@ -25176,14 +25268,14 @@ function appendConsentParams(pageUrl, token) {
25176
25268
  const hashIdx = pageUrl.indexOf("#");
25177
25269
  const hash = hashIdx >= 0 ? pageUrl.slice(hashIdx) : "";
25178
25270
  const base = hashIdx >= 0 ? pageUrl.slice(0, hashIdx) : pageUrl;
25179
- const sep11 = base.indexOf("?") >= 0 ? "&" : "?";
25180
- return base + sep11 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
25271
+ const sep12 = base.indexOf("?") >= 0 ? "&" : "?";
25272
+ return base + sep12 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
25181
25273
  }
25182
25274
  }
25183
25275
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
25184
25276
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
25185
- var app61 = new Hono();
25186
- app61.get("/:slug/click", async (c) => {
25277
+ var app62 = new Hono();
25278
+ app62.get("/:slug/click", async (c) => {
25187
25279
  const slug = c.req.param("slug") ?? "";
25188
25280
  const rawSession = c.req.query("session") ?? "";
25189
25281
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -25247,10 +25339,10 @@ app61.get("/:slug/click", async (c) => {
25247
25339
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
25248
25340
  return c.redirect(redirectUrl, 302);
25249
25341
  });
25250
- var listings_default = app61;
25342
+ var listings_default = app62;
25251
25343
 
25252
25344
  // server/routes/visitor-event.ts
25253
- var app62 = new Hono();
25345
+ var app63 = new Hono();
25254
25346
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
25255
25347
  var buckets = /* @__PURE__ */ new Map();
25256
25348
  var RATE_LIMIT = 60;
@@ -25326,12 +25418,12 @@ function originAllowed(origin, allowlist) {
25326
25418
  return false;
25327
25419
  }
25328
25420
  }
25329
- app62.options("/event", (c) => {
25421
+ app63.options("/event", (c) => {
25330
25422
  const origin = getOrigin2(c);
25331
25423
  setCorsHeaders2(c, origin);
25332
25424
  return c.body(null, 204);
25333
25425
  });
25334
- app62.post("/event", async (c) => {
25426
+ app63.post("/event", async (c) => {
25335
25427
  const origin = getOrigin2(c);
25336
25428
  setCorsHeaders2(c, origin);
25337
25429
  const ua = c.req.header("user-agent") ?? "";
@@ -25536,17 +25628,17 @@ async function writeEvent(opts) {
25536
25628
  );
25537
25629
  }
25538
25630
  }
25539
- var visitor_event_default = app62;
25631
+ var visitor_event_default = app63;
25540
25632
 
25541
25633
  // server/routes/session.ts
25542
- import { resolve as resolve34 } from "path";
25543
- import { existsSync as existsSync39, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
25634
+ import { resolve as resolve35 } from "path";
25635
+ import { existsSync as existsSync41, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
25544
25636
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
25545
25637
  function writeBrandingCache(accountId, agentSlug, branding) {
25546
25638
  try {
25547
- const cacheDir = resolve34(MAXY_DIR, "branding-cache", accountId);
25639
+ const cacheDir = resolve35(MAXY_DIR, "branding-cache", accountId);
25548
25640
  mkdirSync9(cacheDir, { recursive: true });
25549
- writeFileSync15(resolve34(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25641
+ writeFileSync15(resolve35(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25550
25642
  } catch (err) {
25551
25643
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
25552
25644
  }
@@ -25582,8 +25674,8 @@ function withVisitorCookie(response, visitorId) {
25582
25674
  headers
25583
25675
  });
25584
25676
  }
25585
- var app63 = new Hono();
25586
- app63.post("/", async (c) => {
25677
+ var app64 = new Hono();
25678
+ app64.post("/", async (c) => {
25587
25679
  let body;
25588
25680
  try {
25589
25681
  body = await c.req.json();
@@ -25623,8 +25715,8 @@ app63.post("/", async (c) => {
25623
25715
  }
25624
25716
  let agentConfig = null;
25625
25717
  if (account) {
25626
- const agentDir = resolve34(account.accountDir, "agents", agentSlug);
25627
- if (!existsSync39(agentDir) || !existsSync39(resolve34(agentDir, "config.json"))) {
25718
+ const agentDir = resolve35(account.accountDir, "agents", agentSlug);
25719
+ if (!existsSync41(agentDir) || !existsSync41(resolve35(agentDir, "config.json"))) {
25628
25720
  return c.json({ error: "Agent not found" }, 404);
25629
25721
  }
25630
25722
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -25730,7 +25822,7 @@ app63.post("/", async (c) => {
25730
25822
  newVisitorId
25731
25823
  );
25732
25824
  });
25733
- var session_default2 = app63;
25825
+ var session_default2 = app64;
25734
25826
 
25735
25827
  // server/lib/calendar-slots.ts
25736
25828
  var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
@@ -25813,17 +25905,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
25813
25905
  }
25814
25906
 
25815
25907
  // server/routes/calendar-public.ts
25816
- var app64 = new Hono();
25908
+ var app65 = new Hono();
25817
25909
  function setCors(c) {
25818
25910
  c.header("Access-Control-Allow-Origin", "*");
25819
25911
  c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
25820
25912
  c.header("Access-Control-Allow-Headers", "content-type");
25821
25913
  }
25822
- app64.options("/free-busy", (c) => {
25914
+ app65.options("/free-busy", (c) => {
25823
25915
  setCors(c);
25824
25916
  return c.body(null, 204);
25825
25917
  });
25826
- app64.get("/free-busy", async (c) => {
25918
+ app65.get("/free-busy", async (c) => {
25827
25919
  setCors(c);
25828
25920
  const from = c.req.query("from");
25829
25921
  const to = c.req.query("to");
@@ -25879,14 +25971,14 @@ app64.get("/free-busy", async (c) => {
25879
25971
  await session.close();
25880
25972
  }
25881
25973
  });
25882
- var calendar_public_default = app64;
25974
+ var calendar_public_default = app65;
25883
25975
 
25884
25976
  // server/routes/portal-fetch.ts
25885
25977
  import { createReadStream as createReadStream3 } from "fs";
25886
- import { stat as stat8, readFile as readFile8, realpath } from "fs/promises";
25887
- import { join as join44, resolve as resolve35, sep as sep9 } from "path";
25978
+ import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
25979
+ import { join as join44, resolve as resolve36, sep as sep10 } from "path";
25888
25980
  import { Readable as Readable3 } from "stream";
25889
- var app65 = new Hono();
25981
+ var app66 = new Hono();
25890
25982
  var TAG47 = "[portal-fetch]";
25891
25983
  async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
25892
25984
  if (!secret || !signature) return false;
@@ -25937,10 +26029,10 @@ ${expiresAtMs}`)
25937
26029
  return diff === 0;
25938
26030
  }
25939
26031
  async function readAccountSecret(accountId) {
25940
- const path3 = resolve35(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
26032
+ const path3 = resolve36(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
25941
26033
  let text;
25942
26034
  try {
25943
- text = await readFile8(path3, "utf8");
26035
+ text = await readFile9(path3, "utf8");
25944
26036
  } catch {
25945
26037
  console.error(`${TAG47} op=no-secret account="${accountId}" path="${path3}"`);
25946
26038
  return "";
@@ -25957,7 +26049,7 @@ function isValidAccountId2(value) {
25957
26049
  }
25958
26050
  async function readExposeFolders2(accountDir) {
25959
26051
  try {
25960
- const cfg = JSON.parse(await readFile8(join44(accountDir, "data-portal.json"), "utf8"));
26052
+ const cfg = JSON.parse(await readFile9(join44(accountDir, "data-portal.json"), "utf8"));
25961
26053
  return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
25962
26054
  } catch {
25963
26055
  return [];
@@ -25966,14 +26058,14 @@ async function readExposeFolders2(accountDir) {
25966
26058
  async function resolveFetchTarget(accountDir, relPath, ownerId) {
25967
26059
  let schemaText = null;
25968
26060
  try {
25969
- schemaText = await readFile8(join44(accountDir, "SCHEMA.md"), "utf8");
26061
+ schemaText = await readFile9(join44(accountDir, "SCHEMA.md"), "utf8");
25970
26062
  } catch {
25971
26063
  schemaText = null;
25972
26064
  }
25973
26065
  const exposeFolders = await readExposeFolders2(accountDir);
25974
26066
  const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
25975
26067
  if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
25976
- const lexical = resolve35(accountDir, relPath);
26068
+ const lexical = resolve36(accountDir, relPath);
25977
26069
  let root;
25978
26070
  let absolute;
25979
26071
  try {
@@ -25982,11 +26074,11 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
25982
26074
  } catch {
25983
26075
  return { ok: false, reason: "enoent" };
25984
26076
  }
25985
- if (absolute === root || !absolute.startsWith(root + sep9)) return { ok: false, reason: "not-exposed" };
26077
+ if (absolute === root || !absolute.startsWith(root + sep10)) return { ok: false, reason: "not-exposed" };
25986
26078
  const rel = absolute.slice(root.length + 1);
25987
- const top = rel.split(sep9)[0];
26079
+ const top = rel.split(sep10)[0];
25988
26080
  if (ownerId) {
25989
- const own = `uploads${sep9}${ownerId}${sep9}`;
26081
+ const own = `uploads${sep10}${ownerId}${sep10}`;
25990
26082
  if (!rel.startsWith(own)) return { ok: false, reason: "not-exposed" };
25991
26083
  } else if (!exposed.includes(top)) {
25992
26084
  return { ok: false, reason: "not-exposed" };
@@ -26022,7 +26114,7 @@ async function handle(c, headOnly) {
26022
26114
  return c.json({ ok: false, error: "denied" }, 401);
26023
26115
  }
26024
26116
  const target = await resolveFetchTarget(
26025
- resolve35(DATA_ROOT, "accounts", accountId),
26117
+ resolve36(DATA_ROOT, "accounts", accountId),
26026
26118
  relPath,
26027
26119
  owner || void 0
26028
26120
  );
@@ -26049,9 +26141,9 @@ async function handle(c, headOnly) {
26049
26141
  }
26050
26142
  });
26051
26143
  }
26052
- app65.get("/fetch", (c) => handle(c, false));
26053
- app65.on("HEAD", "/fetch", (c) => handle(c, true));
26054
- var portal_fetch_default = app65;
26144
+ app66.get("/fetch", (c) => handle(c, false));
26145
+ app66.on("HEAD", "/fetch", (c) => handle(c, true));
26146
+ var portal_fetch_default = app66;
26055
26147
 
26056
26148
  // app/lib/timeentry-census.ts
26057
26149
  var TAG48 = "[timeentry-census]";
@@ -26136,7 +26228,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
26136
26228
  }
26137
26229
 
26138
26230
  // app/lib/ledger-census.ts
26139
- import { readdirSync as readdirSync26, readFileSync as readFileSync43, statSync as statSync16 } from "fs";
26231
+ import { readdirSync as readdirSync26, readFileSync as readFileSync43, statSync as statSync18 } from "fs";
26140
26232
  import { join as join45 } from "path";
26141
26233
 
26142
26234
  // ../lib/ledger-core/dist/reconcile.js
@@ -26193,7 +26285,7 @@ function countWriteRejects24h(logDir, now) {
26193
26285
  for (const name of entries) {
26194
26286
  const path3 = join45(logDir, name);
26195
26287
  try {
26196
- if (now - statSync16(path3).mtimeMs > DAY_MS) continue;
26288
+ if (now - statSync18(path3).mtimeMs > DAY_MS) continue;
26197
26289
  for (const line of readFileSync43(path3, "utf8").split("\n")) {
26198
26290
  if (line.includes("[graph-write] reject")) total += 1;
26199
26291
  }
@@ -26463,13 +26555,13 @@ function startGraphHealthTimer() {
26463
26555
 
26464
26556
  // app/lib/file-watcher.ts
26465
26557
  import * as fsp2 from "fs/promises";
26466
- import { resolve as resolve36, sep as sep10 } from "path";
26558
+ import { resolve as resolve37, sep as sep11 } from "path";
26467
26559
  var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26468
26560
  var DEFAULT_COALESCE_MS = 500;
26469
26561
  var ROOTS = ["accounts"];
26470
26562
  function _routeEvent(rootName, filename) {
26471
26563
  if (!filename) return null;
26472
- const segs = filename.split(sep10).filter(Boolean);
26564
+ const segs = filename.split(sep11).filter(Boolean);
26473
26565
  if (segs.length < 2) return null;
26474
26566
  const accountId = segs[0];
26475
26567
  if (!ACCOUNT_UUID_RE4.test(accountId)) return null;
@@ -26482,7 +26574,7 @@ async function startFileWatcher(opts = {}) {
26482
26574
  const dropFn = opts.drop ?? dropFileIndex;
26483
26575
  for (const r of ROOTS) {
26484
26576
  try {
26485
- await fsp2.mkdir(resolve36(dataRoot, r), { recursive: true });
26577
+ await fsp2.mkdir(resolve37(dataRoot, r), { recursive: true });
26486
26578
  } catch (err) {
26487
26579
  console.error(
26488
26580
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -26503,7 +26595,7 @@ async function startFileWatcher(opts = {}) {
26503
26595
  timers.set(relativePath, t);
26504
26596
  }
26505
26597
  async function runHook(relativePath, accountId) {
26506
- const absolute = resolve36(dataRoot, relativePath);
26598
+ const absolute = resolve37(dataRoot, relativePath);
26507
26599
  let exists = false;
26508
26600
  try {
26509
26601
  const st = await fsp2.stat(absolute);
@@ -26527,7 +26619,7 @@ async function startFileWatcher(opts = {}) {
26527
26619
  }
26528
26620
  }
26529
26621
  async function watchRoot(rootName) {
26530
- const absRoot = resolve36(dataRoot, rootName);
26622
+ const absRoot = resolve37(dataRoot, rootName);
26531
26623
  try {
26532
26624
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
26533
26625
  for await (const event of iter) {
@@ -26566,7 +26658,7 @@ async function startFileWatcher(opts = {}) {
26566
26658
 
26567
26659
  // app/lib/migrate-uploads.ts
26568
26660
  import { mkdir as mkdir6, readdir as readdir6, rename as rename3, rm as rm3 } from "fs/promises";
26569
- import { dirname as dirname14, relative as relative7, resolve as resolve37 } from "path";
26661
+ import { dirname as dirname15, relative as relative7, resolve as resolve38 } from "path";
26570
26662
  var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26571
26663
  async function walkFiles(dir) {
26572
26664
  const out = [];
@@ -26577,7 +26669,7 @@ async function walkFiles(dir) {
26577
26669
  return out;
26578
26670
  }
26579
26671
  for (const e of entries) {
26580
- const abs = resolve37(dir, e.name);
26672
+ const abs = resolve38(dir, e.name);
26581
26673
  if (e.isDirectory()) {
26582
26674
  out.push(...await walkFiles(abs));
26583
26675
  } else if (e.isFile()) {
@@ -26597,8 +26689,8 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26597
26689
  let moved = 0;
26598
26690
  for (const oldAbs of files) {
26599
26691
  const suffix = relative7(srcDir, oldAbs);
26600
- const newAbs = resolve37(destDir, suffix);
26601
- await mkdir6(dirname14(newAbs), { recursive: true });
26692
+ const newAbs = resolve38(destDir, suffix);
26693
+ await mkdir6(dirname15(newAbs), { recursive: true });
26602
26694
  await rename3(oldAbs, newAbs);
26603
26695
  moved++;
26604
26696
  const oldRel = relative7(dataRoot, oldAbs);
@@ -26624,7 +26716,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26624
26716
  }
26625
26717
  async function migrateUploads(opts = {}) {
26626
26718
  const dataRoot = opts.dataRoot ?? DATA_ROOT;
26627
- const oldRoot = resolve37(dataRoot, "uploads");
26719
+ const oldRoot = resolve38(dataRoot, "uploads");
26628
26720
  let topEntries;
26629
26721
  try {
26630
26722
  topEntries = await readdir6(oldRoot, { withFileTypes: true });
@@ -26645,8 +26737,8 @@ async function migrateUploads(opts = {}) {
26645
26737
  const name = entry.name;
26646
26738
  if (ACCOUNT_UUID_RE5.test(name)) {
26647
26739
  moved += await relocateTree(
26648
- resolve37(oldRoot, name),
26649
- resolve37(dataRoot, "accounts", name, "uploads"),
26740
+ resolve38(oldRoot, name),
26741
+ resolve38(dataRoot, "accounts", name, "uploads"),
26650
26742
  dataRoot,
26651
26743
  name,
26652
26744
  session
@@ -26658,8 +26750,8 @@ async function migrateUploads(opts = {}) {
26658
26750
  continue;
26659
26751
  }
26660
26752
  moved += await relocateTree(
26661
- resolve37(oldRoot, "public"),
26662
- resolve37(dataRoot, "accounts", installAccountId, "uploads", "public"),
26753
+ resolve38(oldRoot, "public"),
26754
+ resolve38(dataRoot, "accounts", installAccountId, "uploads", "public"),
26663
26755
  dataRoot,
26664
26756
  null,
26665
26757
  // public uploads carry no graph nodes
@@ -26688,8 +26780,8 @@ async function migrateUploads(opts = {}) {
26688
26780
  }
26689
26781
 
26690
26782
  // app/lib/migrate-admin-webchat-sidecars.ts
26691
- import { readdir as readdir7, readFile as readFile9, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
26692
- import { existsSync as existsSync40 } from "fs";
26783
+ import { readdir as readdir7, readFile as readFile10, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
26784
+ import { existsSync as existsSync42 } from "fs";
26693
26785
  import { join as join46 } from "path";
26694
26786
  var ADMIN_ROLE2 = "admin";
26695
26787
  var WEBCHAT_CHANNEL2 = "webchat";
@@ -26701,7 +26793,7 @@ var defaultResolveName = async (_accountId, userId) => {
26701
26793
  async function readRaw3(path3) {
26702
26794
  let raw;
26703
26795
  try {
26704
- raw = await readFile9(path3, "utf8");
26796
+ raw = await readFile10(path3, "utf8");
26705
26797
  } catch {
26706
26798
  return null;
26707
26799
  }
@@ -26719,7 +26811,7 @@ async function writeRaw(path3, obj) {
26719
26811
  await rename4(tmp, path3);
26720
26812
  } catch (err) {
26721
26813
  try {
26722
- if (existsSync40(tmp)) await unlink4(tmp);
26814
+ if (existsSync42(tmp)) await unlink4(tmp);
26723
26815
  } catch {
26724
26816
  }
26725
26817
  throw err;
@@ -27108,8 +27200,8 @@ var streamSSE = (c, cb, onError) => {
27108
27200
 
27109
27201
  // app/lib/whatsapp/gateway/routes.ts
27110
27202
  function createWaChannelRoutes(deps) {
27111
- const app67 = new Hono();
27112
- app67.get("/wa-channel/inbound", (c) => {
27203
+ const app68 = new Hono();
27204
+ app68.get("/wa-channel/inbound", (c) => {
27113
27205
  const senderId = c.req.query("senderId");
27114
27206
  if (!senderId) return c.json({ error: "senderId required" }, 400);
27115
27207
  return streamSSE(c, async (stream2) => {
@@ -27127,7 +27219,7 @@ function createWaChannelRoutes(deps) {
27127
27219
  }
27128
27220
  });
27129
27221
  });
27130
- app67.post("/wa-channel/reply", async (c) => {
27222
+ app68.post("/wa-channel/reply", async (c) => {
27131
27223
  const body = await c.req.json().catch(() => null);
27132
27224
  const senderId = body?.senderId;
27133
27225
  const text = body?.text;
@@ -27148,7 +27240,7 @@ function createWaChannelRoutes(deps) {
27148
27240
  console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
27149
27241
  return c.json({ ok: true });
27150
27242
  });
27151
- app67.post("/wa-channel/reply-document", async (c) => {
27243
+ app68.post("/wa-channel/reply-document", async (c) => {
27152
27244
  const body = await c.req.json().catch(() => null);
27153
27245
  const senderId = body?.senderId;
27154
27246
  const files = body?.files;
@@ -27187,7 +27279,7 @@ function createWaChannelRoutes(deps) {
27187
27279
  }
27188
27280
  return c.json({ ok: true, results });
27189
27281
  });
27190
- app67.post("/wa-channel/ready", async (c) => {
27282
+ app68.post("/wa-channel/ready", async (c) => {
27191
27283
  const body = await c.req.json().catch(() => null);
27192
27284
  const senderId = body?.senderId;
27193
27285
  if (typeof senderId !== "string") {
@@ -27196,7 +27288,7 @@ function createWaChannelRoutes(deps) {
27196
27288
  deps.onReady?.(senderId);
27197
27289
  return c.json({ ok: true });
27198
27290
  });
27199
- app67.post("/wa-channel/received", async (c) => {
27291
+ app68.post("/wa-channel/received", async (c) => {
27200
27292
  const body = await c.req.json().catch(() => null);
27201
27293
  const senderId = body?.senderId;
27202
27294
  const waMessageId = body?.waMessageId;
@@ -27206,7 +27298,7 @@ function createWaChannelRoutes(deps) {
27206
27298
  deps.onReceived?.(senderId, waMessageId);
27207
27299
  return c.json({ ok: true });
27208
27300
  });
27209
- app67.post("/wa-channel/turn-end", async (c) => {
27301
+ app68.post("/wa-channel/turn-end", async (c) => {
27210
27302
  const body = await c.req.json().catch(() => null);
27211
27303
  const senderId = body?.senderId;
27212
27304
  const sessionId = body?.sessionId;
@@ -27239,7 +27331,7 @@ function createWaChannelRoutes(deps) {
27239
27331
  console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
27240
27332
  return c.json({ ok: true, delivered: "none" });
27241
27333
  });
27242
- return app67;
27334
+ return app68;
27243
27335
  }
27244
27336
 
27245
27337
  // app/lib/whatsapp/gateway/wa-gateway.ts
@@ -27654,8 +27746,8 @@ var InboundHub2 = class {
27654
27746
 
27655
27747
  // app/lib/webchat/gateway/routes.ts
27656
27748
  function createWebchatChannelRoutes(deps) {
27657
- const app67 = new Hono();
27658
- app67.get("/webchat-channel/inbound", (c) => {
27749
+ const app68 = new Hono();
27750
+ app68.get("/webchat-channel/inbound", (c) => {
27659
27751
  const key = c.req.query("key");
27660
27752
  if (!key) return c.json({ error: "key required" }, 400);
27661
27753
  return streamSSE(c, async (stream2) => {
@@ -27673,7 +27765,7 @@ function createWebchatChannelRoutes(deps) {
27673
27765
  }
27674
27766
  });
27675
27767
  });
27676
- app67.post("/webchat-channel/reply", async (c) => {
27768
+ app68.post("/webchat-channel/reply", async (c) => {
27677
27769
  const body = await c.req.json().catch(() => null);
27678
27770
  const key = body?.key;
27679
27771
  const text = body?.text;
@@ -27683,7 +27775,7 @@ function createWebchatChannelRoutes(deps) {
27683
27775
  deps.onReply?.(key, text);
27684
27776
  return c.json({ ok: true });
27685
27777
  });
27686
- app67.post("/webchat-channel/connector-auth", async (c) => {
27778
+ app68.post("/webchat-channel/connector-auth", async (c) => {
27687
27779
  const body = await c.req.json().catch(() => null);
27688
27780
  const key = body?.key;
27689
27781
  const sessionId = body?.sessionId;
@@ -27696,7 +27788,7 @@ function createWebchatChannelRoutes(deps) {
27696
27788
  const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
27697
27789
  return c.json(result);
27698
27790
  });
27699
- app67.post("/webchat-channel/ready", async (c) => {
27791
+ app68.post("/webchat-channel/ready", async (c) => {
27700
27792
  const body = await c.req.json().catch(() => null);
27701
27793
  const key = body?.key;
27702
27794
  if (typeof key !== "string") {
@@ -27705,7 +27797,7 @@ function createWebchatChannelRoutes(deps) {
27705
27797
  deps.onReady?.(key);
27706
27798
  return c.json({ ok: true });
27707
27799
  });
27708
- app67.post("/webchat-channel/permission-request", async (c) => {
27800
+ app68.post("/webchat-channel/permission-request", async (c) => {
27709
27801
  const body = await c.req.json().catch(() => null);
27710
27802
  const key = body?.key;
27711
27803
  const requestId = body?.request_id;
@@ -27719,7 +27811,7 @@ function createWebchatChannelRoutes(deps) {
27719
27811
  const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
27720
27812
  return c.json(verdict);
27721
27813
  });
27722
- app67.post("/webchat-channel/received", async (c) => {
27814
+ app68.post("/webchat-channel/received", async (c) => {
27723
27815
  const body = await c.req.json().catch(() => null);
27724
27816
  const key = body?.key;
27725
27817
  const messageId = body?.messageId;
@@ -27729,7 +27821,7 @@ function createWebchatChannelRoutes(deps) {
27729
27821
  deps.onReceived?.(key, messageId);
27730
27822
  return c.json({ ok: true });
27731
27823
  });
27732
- app67.post("/webchat-channel/turn-end", async (c) => {
27824
+ app68.post("/webchat-channel/turn-end", async (c) => {
27733
27825
  const body = await c.req.json().catch(() => null);
27734
27826
  const key = body?.key;
27735
27827
  const sessionId = body?.sessionId;
@@ -27743,7 +27835,7 @@ function createWebchatChannelRoutes(deps) {
27743
27835
  console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=${replied ? "yes" : "no"} trailing=${finalBytes}`);
27744
27836
  return c.json({ ok: true });
27745
27837
  });
27746
- return app67;
27838
+ return app68;
27747
27839
  }
27748
27840
 
27749
27841
  // app/lib/webchat/gateway/webchat-gateway.ts
@@ -27801,16 +27893,16 @@ var WebchatGateway = class _WebchatGateway {
27801
27893
  * The public /api/chat route awaits this to return the reply on the same SSE
27802
27894
  * response, preserving the pre-756 POST→single-blob browser contract. */
27803
27895
  awaitReply(key, timeoutMs) {
27804
- return new Promise((resolve43) => {
27896
+ return new Promise((resolve44) => {
27805
27897
  const timer = setTimeout(() => {
27806
27898
  this.replyAwaiters.delete(key);
27807
- resolve43({ timeout: true });
27899
+ resolve44({ timeout: true });
27808
27900
  }, timeoutMs);
27809
27901
  if (timer.unref) timer.unref();
27810
27902
  this.replyAwaiters.set(key, (r) => {
27811
27903
  clearTimeout(timer);
27812
27904
  this.replyAwaiters.delete(key);
27813
- resolve43(r);
27905
+ resolve44(r);
27814
27906
  });
27815
27907
  });
27816
27908
  }
@@ -27821,11 +27913,11 @@ var WebchatGateway = class _WebchatGateway {
27821
27913
  * terminal dialog stays answerable). */
27822
27914
  awaitPermissionVerdict(p, timeoutMs) {
27823
27915
  const k = _WebchatGateway.promptKey(p.key, p.requestId);
27824
- return new Promise((resolve43) => {
27916
+ return new Promise((resolve44) => {
27825
27917
  this.pendingPrompts.get(k)?.resolve({ timeout: true });
27826
27918
  const timer = setTimeout(() => {
27827
27919
  this.pendingPrompts.delete(k);
27828
- resolve43({ timeout: true });
27920
+ resolve44({ timeout: true });
27829
27921
  }, timeoutMs);
27830
27922
  if (timer.unref) timer.unref();
27831
27923
  this.pendingPrompts.set(k, {
@@ -27834,7 +27926,7 @@ var WebchatGateway = class _WebchatGateway {
27834
27926
  resolve: (r) => {
27835
27927
  clearTimeout(timer);
27836
27928
  this.pendingPrompts.delete(k);
27837
- resolve43(r);
27929
+ resolve44(r);
27838
27930
  }
27839
27931
  });
27840
27932
  console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
@@ -28398,8 +28490,8 @@ async function fanOut(subscribers, text, onError, tag) {
28398
28490
  }
28399
28491
 
28400
28492
  // app/lib/webchat/file-delivery.ts
28401
- import { realpathSync as realpathSync8 } from "fs";
28402
- import { resolve as resolve38 } from "path";
28493
+ import { realpathSync as realpathSync9 } from "fs";
28494
+ import { resolve as resolve39 } from "path";
28403
28495
 
28404
28496
  // app/lib/channel-pty-bridge/file-delivery.ts
28405
28497
  var SEND_USER_FILE = "SendUserFile";
@@ -28500,10 +28592,10 @@ function makeWebchatSendFile(entry) {
28500
28592
  console.error(`${TAG51} file-delivery reject reason=no-account sender=${entry.senderId}`);
28501
28593
  return { ok: false, error: "no-account" };
28502
28594
  }
28503
- const accountDir = resolve38(platformRoot2(), "..", "data/accounts", entry.accountId);
28595
+ const accountDir = resolve39(platformRoot2(), "..", "data/accounts", entry.accountId);
28504
28596
  try {
28505
- const resolved = realpathSync8(filePath);
28506
- const accountResolved = realpathSync8(accountDir);
28597
+ const resolved = realpathSync9(filePath);
28598
+ const accountResolved = realpathSync9(accountDir);
28507
28599
  if (!resolved.startsWith(accountResolved + "/")) {
28508
28600
  console.error(`${TAG51} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
28509
28601
  return { ok: false, error: "outside-account" };
@@ -28827,8 +28919,8 @@ var InboundHub3 = class {
28827
28919
 
28828
28920
  // app/lib/telegram/gateway/routes.ts
28829
28921
  function createTelegramChannelRoutes(deps) {
28830
- const app67 = new Hono();
28831
- app67.get("/tg-channel/inbound", (c) => {
28922
+ const app68 = new Hono();
28923
+ app68.get("/tg-channel/inbound", (c) => {
28832
28924
  const key = c.req.query("key");
28833
28925
  if (!key) return c.json({ error: "key required" }, 400);
28834
28926
  return streamSSE(c, async (stream2) => {
@@ -28846,7 +28938,7 @@ function createTelegramChannelRoutes(deps) {
28846
28938
  }
28847
28939
  });
28848
28940
  });
28849
- app67.post("/tg-channel/reply", async (c) => {
28941
+ app68.post("/tg-channel/reply", async (c) => {
28850
28942
  const body = await c.req.json().catch(() => null);
28851
28943
  const key = body?.key;
28852
28944
  const text = body?.text;
@@ -28862,7 +28954,7 @@ function createTelegramChannelRoutes(deps) {
28862
28954
  console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
28863
28955
  return c.json({ ok: true });
28864
28956
  });
28865
- app67.post("/tg-channel/ready", async (c) => {
28957
+ app68.post("/tg-channel/ready", async (c) => {
28866
28958
  const body = await c.req.json().catch(() => null);
28867
28959
  const key = body?.key;
28868
28960
  if (typeof key !== "string") {
@@ -28871,7 +28963,7 @@ function createTelegramChannelRoutes(deps) {
28871
28963
  deps.onReady?.(key);
28872
28964
  return c.json({ ok: true });
28873
28965
  });
28874
- app67.post("/tg-channel/received", async (c) => {
28966
+ app68.post("/tg-channel/received", async (c) => {
28875
28967
  const body = await c.req.json().catch(() => null);
28876
28968
  const key = body?.key;
28877
28969
  const messageId = body?.messageId;
@@ -28881,7 +28973,7 @@ function createTelegramChannelRoutes(deps) {
28881
28973
  deps.onReceived?.(key, messageId);
28882
28974
  return c.json({ ok: true });
28883
28975
  });
28884
- app67.post("/tg-channel/turn-end", async (c) => {
28976
+ app68.post("/tg-channel/turn-end", async (c) => {
28885
28977
  const body = await c.req.json().catch(() => null);
28886
28978
  const key = body?.key;
28887
28979
  const sessionId = body?.sessionId;
@@ -28914,7 +29006,7 @@ function createTelegramChannelRoutes(deps) {
28914
29006
  console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
28915
29007
  return c.json({ ok: true, delivered: "none" });
28916
29008
  });
28917
- return app67;
29009
+ return app68;
28918
29010
  }
28919
29011
 
28920
29012
  // app/lib/telegram/gateway/telegram-gateway.ts
@@ -29062,9 +29154,9 @@ function buildTelegramSpawnRequest(input) {
29062
29154
  }
29063
29155
 
29064
29156
  // app/lib/telegram/outbound/send-document.ts
29065
- import { realpathSync as realpathSync9 } from "fs";
29066
- import { readFile as readFile10, stat as stat10 } from "fs/promises";
29067
- import { resolve as resolve39, basename as basename12 } from "path";
29157
+ import { realpathSync as realpathSync10 } from "fs";
29158
+ import { readFile as readFile11, stat as stat10 } from "fs/promises";
29159
+ import { resolve as resolve40, basename as basename13 } from "path";
29068
29160
  var TAG53 = "[telegram:outbound]";
29069
29161
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
29070
29162
  async function sendTelegramDocument(input) {
@@ -29075,10 +29167,10 @@ async function sendTelegramDocument(input) {
29075
29167
  if (!maxyAccountId || !platformRoot5) {
29076
29168
  return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
29077
29169
  }
29078
- const accountDir = resolve39(platformRoot5, "..", "data/accounts", maxyAccountId);
29170
+ const accountDir = resolve40(platformRoot5, "..", "data/accounts", maxyAccountId);
29079
29171
  let accountResolved;
29080
29172
  try {
29081
- accountResolved = realpathSync9(accountDir);
29173
+ accountResolved = realpathSync10(accountDir);
29082
29174
  } catch (err) {
29083
29175
  const code = err.code;
29084
29176
  if (code === "ENOENT") {
@@ -29090,7 +29182,7 @@ async function sendTelegramDocument(input) {
29090
29182
  }
29091
29183
  let resolvedPath;
29092
29184
  try {
29093
- resolvedPath = realpathSync9(filePath);
29185
+ resolvedPath = realpathSync10(filePath);
29094
29186
  } catch (err) {
29095
29187
  const code = err.code;
29096
29188
  if (code === "ENOENT") {
@@ -29112,8 +29204,8 @@ async function sendTelegramDocument(input) {
29112
29204
  error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
29113
29205
  };
29114
29206
  }
29115
- const filename = basename12(resolvedPath);
29116
- const buffer = Buffer.from(await readFile10(resolvedPath));
29207
+ const filename = basename13(resolvedPath);
29208
+ const buffer = Buffer.from(await readFile11(resolvedPath));
29117
29209
  const form = new FormData();
29118
29210
  form.append("chat_id", String(chatId));
29119
29211
  if (caption) form.append("caption", caption);
@@ -29467,12 +29559,12 @@ function warnOnChannelAdminBindingDrift() {
29467
29559
  }
29468
29560
 
29469
29561
  // server/lib/booking-site-accounts.ts
29470
- import { existsSync as existsSync41, readFileSync as readFileSync44 } from "fs";
29471
- import { resolve as resolve40 } from "path";
29562
+ import { existsSync as existsSync43, readFileSync as readFileSync44 } from "fs";
29563
+ import { resolve as resolve41 } from "path";
29472
29564
  function listBookingSiteAccounts(accounts) {
29473
29565
  return accounts.filter((a) => {
29474
- const availPath = resolve40(a.accountDir, "calendar-availability.json");
29475
- if (!existsSync41(availPath)) return false;
29566
+ const availPath = resolve41(a.accountDir, "calendar-availability.json");
29567
+ if (!existsSync43(availPath)) return false;
29476
29568
  try {
29477
29569
  const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
29478
29570
  return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
@@ -29512,8 +29604,8 @@ function broadcastAdminShutdown(reason) {
29512
29604
 
29513
29605
  // ../lib/entitlement/src/index.ts
29514
29606
  import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
29515
- import { existsSync as existsSync42, readFileSync as readFileSync45, statSync as statSync17 } from "fs";
29516
- import { resolve as resolve41 } from "path";
29607
+ import { existsSync as existsSync44, readFileSync as readFileSync45, statSync as statSync19 } from "fs";
29608
+ import { resolve as resolve42 } from "path";
29517
29609
 
29518
29610
  // ../lib/entitlement/src/canonicalize.ts
29519
29611
  function canonicalize(value) {
@@ -29548,7 +29640,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
29548
29640
  var GRACE_DAYS = 7;
29549
29641
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
29550
29642
  function pubkeyPath(brand) {
29551
- return resolve41(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29643
+ return resolve42(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29552
29644
  }
29553
29645
  var memo = null;
29554
29646
  function memoKey(mtimeMs, account) {
@@ -29560,11 +29652,11 @@ function resolveEntitlement(brand, account) {
29560
29652
  if (brand.commercialMode !== true) {
29561
29653
  return logResolved(implicitTrust(account), null);
29562
29654
  }
29563
- const entitlementPath = resolve41(brand.configDir, "entitlement.json");
29564
- if (!existsSync42(entitlementPath)) {
29655
+ const entitlementPath = resolve42(brand.configDir, "entitlement.json");
29656
+ if (!existsSync44(entitlementPath)) {
29565
29657
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
29566
29658
  }
29567
- const stat11 = statSync17(entitlementPath);
29659
+ const stat11 = statSync19(entitlementPath);
29568
29660
  const key = memoKey(stat11.mtimeMs, account);
29569
29661
  if (memo && memo.key === key) {
29570
29662
  return memo.result;
@@ -29754,10 +29846,10 @@ installMediaDownloadGuard();
29754
29846
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
29755
29847
  var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join47(PLATFORM_ROOT8, "config", "brand.json") : "";
29756
29848
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
29757
- if (BRAND_JSON_PATH && !existsSync43(BRAND_JSON_PATH)) {
29849
+ if (BRAND_JSON_PATH && !existsSync45(BRAND_JSON_PATH)) {
29758
29850
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
29759
29851
  }
29760
- if (BRAND_JSON_PATH && existsSync43(BRAND_JSON_PATH)) {
29852
+ if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
29761
29853
  try {
29762
29854
  const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
29763
29855
  BRAND = { ...BRAND, ...parsed };
@@ -29794,7 +29886,7 @@ var brandLoginOpts = {
29794
29886
  var ALIAS_DOMAINS_PATH = join47(homedir4(), BRAND.configDir, "alias-domains.json");
29795
29887
  function loadAliasDomains() {
29796
29888
  try {
29797
- if (!existsSync43(ALIAS_DOMAINS_PATH)) return null;
29889
+ if (!existsSync45(ALIAS_DOMAINS_PATH)) return null;
29798
29890
  const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
29799
29891
  if (!Array.isArray(parsed)) {
29800
29892
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
@@ -29819,7 +29911,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
29819
29911
  function isPublicHost(host) {
29820
29912
  return host.startsWith("public.") || aliasDomains.has(host);
29821
29913
  }
29822
- var app66 = new Hono();
29914
+ var app67 = new Hono();
29823
29915
  function resolveChannelOverride(accountId, channel, senderId) {
29824
29916
  try {
29825
29917
  const dir = listValidAccounts().find((a) => a.accountId === accountId)?.accountDir;
@@ -29868,7 +29960,7 @@ var waGateway = new WaGateway({
29868
29960
  fetchStandingRules: fetchAccountStandingRules,
29869
29961
  resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
29870
29962
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
29871
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve42(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
29963
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
29872
29964
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
29873
29965
  // path-validation scope) is the sender's effective SESSION account, resolved
29874
29966
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -29883,7 +29975,7 @@ var waGateway = new WaGateway({
29883
29975
  caption,
29884
29976
  accountId,
29885
29977
  maxyAccountId,
29886
- platformRoot: resolve42(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
29978
+ platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
29887
29979
  });
29888
29980
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
29889
29981
  },
@@ -29995,7 +30087,7 @@ var waGateway = new WaGateway({
29995
30087
  nativeFileFollowers.set(senderId, ac);
29996
30088
  }
29997
30089
  });
29998
- app66.route("/", waGateway.routes());
30090
+ app67.route("/", waGateway.routes());
29999
30091
  waGateway.startSweeper();
30000
30092
  function runDuplicateSenderAudit() {
30001
30093
  try {
@@ -30118,7 +30210,7 @@ var webchatGateway = new WebchatGateway({
30118
30210
  firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
30119
30211
  });
30120
30212
  setWebchatGateway(webchatGateway);
30121
- app66.route("/", webchatGateway.routes());
30213
+ app67.route("/", webchatGateway.routes());
30122
30214
  webchatGateway.startSweeper();
30123
30215
  webchatGateway.startPublicReaper();
30124
30216
  var telegramFileFollowers = /* @__PURE__ */ new Map();
@@ -30162,7 +30254,7 @@ var telegramGateway = new TelegramGateway({
30162
30254
  }
30163
30255
  });
30164
30256
  setTelegramGateway(telegramGateway);
30165
- app66.route("/", telegramGateway.routes());
30257
+ app67.route("/", telegramGateway.routes());
30166
30258
  telegramGateway.startSweeper();
30167
30259
  var chatRoutes = createChatRoutes({
30168
30260
  handleInbound: (input) => webchatGateway.handleInbound(input),
@@ -30196,19 +30288,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
30196
30288
  return managed.account;
30197
30289
  }
30198
30290
  });
30199
- app66.route("/api/channel/schedule-inject", scheduleInjectRoutes);
30200
- app66.use("*", clientIpMiddleware);
30291
+ app67.route("/api/channel/schedule-inject", scheduleInjectRoutes);
30292
+ app67.use("*", clientIpMiddleware);
30201
30293
  function allowsSameOriginFraming(path3) {
30202
- return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download";
30294
+ return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download" || path3 === "/api/admin/session-upload";
30203
30295
  }
30204
- app66.use("*", async (c, next) => {
30296
+ app67.use("*", async (c, next) => {
30205
30297
  await next();
30206
30298
  c.header("X-Content-Type-Options", "nosniff");
30207
30299
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
30208
30300
  c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
30209
30301
  });
30210
30302
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
30211
- app66.use("*", async (c, next) => {
30303
+ app67.use("*", async (c, next) => {
30212
30304
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
30213
30305
  await next();
30214
30306
  return;
@@ -30226,7 +30318,7 @@ app66.use("*", async (c, next) => {
30226
30318
  });
30227
30319
  }
30228
30320
  });
30229
- app66.use("*", async (c, next) => {
30321
+ app67.use("*", async (c, next) => {
30230
30322
  const host = (c.req.header("host") ?? "").split(":")[0];
30231
30323
  if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
30232
30324
  await next();
@@ -30264,7 +30356,7 @@ function resolveRemoteAuthOpts(c) {
30264
30356
  return { ...brandLoginOpts, origin };
30265
30357
  }
30266
30358
  var MAX_LOGIN_BODY = 8 * 1024;
30267
- app66.post("/__remote-auth/login", async (c) => {
30359
+ app67.post("/__remote-auth/login", async (c) => {
30268
30360
  const client = clientFrom(c);
30269
30361
  const clientIp = client.ip || "unknown";
30270
30362
  if (!requestIsTlsTerminated(c)) {
@@ -30309,7 +30401,7 @@ app66.post("/__remote-auth/login", async (c) => {
30309
30401
  }
30310
30402
  });
30311
30403
  });
30312
- app66.get("/__remote-auth/logout", (c) => {
30404
+ app67.get("/__remote-auth/logout", (c) => {
30313
30405
  const client = clientFrom(c);
30314
30406
  const clientIp = client.ip || "unknown";
30315
30407
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -30322,7 +30414,7 @@ app66.get("/__remote-auth/logout", (c) => {
30322
30414
  }
30323
30415
  });
30324
30416
  });
30325
- app66.post("/__remote-auth/change-password", async (c) => {
30417
+ app67.post("/__remote-auth/change-password", async (c) => {
30326
30418
  const client = clientFrom(c);
30327
30419
  const clientIp = client.ip || "unknown";
30328
30420
  const rateLimited = checkRateLimit(client);
@@ -30381,13 +30473,13 @@ app66.post("/__remote-auth/change-password", async (c) => {
30381
30473
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
30382
30474
  }
30383
30475
  });
30384
- app66.get("/__remote-auth/setup", (c) => {
30476
+ app67.get("/__remote-auth/setup", (c) => {
30385
30477
  if (isRemoteAuthConfigured()) {
30386
30478
  return c.redirect("/");
30387
30479
  }
30388
30480
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
30389
30481
  });
30390
- app66.post("/__remote-auth/set-initial-password", async (c) => {
30482
+ app67.post("/__remote-auth/set-initial-password", async (c) => {
30391
30483
  if (isRemoteAuthConfigured()) {
30392
30484
  return c.redirect("/");
30393
30485
  }
@@ -30425,10 +30517,10 @@ app66.post("/__remote-auth/set-initial-password", async (c) => {
30425
30517
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
30426
30518
  }
30427
30519
  });
30428
- app66.get("/api/remote-auth/status", (c) => {
30520
+ app67.get("/api/remote-auth/status", (c) => {
30429
30521
  return c.json({ configured: isRemoteAuthConfigured() });
30430
30522
  });
30431
- app66.post("/api/remote-auth/set-password", async (c) => {
30523
+ app67.post("/api/remote-auth/set-password", async (c) => {
30432
30524
  let body;
30433
30525
  try {
30434
30526
  body = await c.req.json();
@@ -30467,10 +30559,10 @@ app66.post("/api/remote-auth/set-password", async (c) => {
30467
30559
  return c.json({ error: "Failed to save password" }, 500);
30468
30560
  }
30469
30561
  });
30470
- app66.route("/api/_client-error", client_error_default);
30562
+ app67.route("/api/_client-error", client_error_default);
30471
30563
  console.log("[client-error-route] mounted");
30472
30564
  var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
30473
- app66.use("*", async (c, next) => {
30565
+ app67.use("*", async (c, next) => {
30474
30566
  const host = (c.req.header("host") ?? "").split(":")[0];
30475
30567
  const path3 = c.req.path;
30476
30568
  if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
@@ -30514,28 +30606,28 @@ app66.use("*", async (c, next) => {
30514
30606
  }
30515
30607
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
30516
30608
  });
30517
- app66.route("/api/health", health_default);
30518
- app66.route("/api/chat", chatRoutes);
30519
- app66.route("/api/whatsapp", whatsapp_default);
30520
- app66.route("/api/storage", storage_broker_default);
30521
- app66.route("/api/whatsapp-reader", whatsapp_reader_default);
30522
- app66.route("/api/public-reader", public_reader_default);
30523
- app66.route("/api/webchat", createWebchatRoutes({
30609
+ app67.route("/api/health", health_default);
30610
+ app67.route("/api/chat", chatRoutes);
30611
+ app67.route("/api/whatsapp", whatsapp_default);
30612
+ app67.route("/api/storage", storage_broker_default);
30613
+ app67.route("/api/whatsapp-reader", whatsapp_reader_default);
30614
+ app67.route("/api/public-reader", public_reader_default);
30615
+ app67.route("/api/webchat", createWebchatRoutes({
30524
30616
  handleInbound: (input) => webchatGateway.handleInbound(input),
30525
30617
  // Task 940 — the permission relay's pointer read + verdict write.
30526
30618
  pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
30527
30619
  deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
30528
30620
  resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
30529
30621
  }));
30530
- app66.route("/api/webchat/greeting", webchat_greeting_default);
30531
- app66.route("/api/telegram", telegram_default);
30532
- app66.route("/api/quickbooks", quickbooks_default);
30533
- app66.route("/api/onboarding", onboarding_default);
30534
- app66.route("/api/admin", admin_default);
30535
- app66.route("/api/access", access_default);
30536
- app66.route("/api/session", session_default2);
30537
- app66.route("/api/calendar", calendar_public_default);
30538
- app66.route("/api/portal", portal_fetch_default);
30622
+ app67.route("/api/webchat/greeting", webchat_greeting_default);
30623
+ app67.route("/api/telegram", telegram_default);
30624
+ app67.route("/api/quickbooks", quickbooks_default);
30625
+ app67.route("/api/onboarding", onboarding_default);
30626
+ app67.route("/api/admin", admin_default);
30627
+ app67.route("/api/access", access_default);
30628
+ app67.route("/api/session", session_default2);
30629
+ app67.route("/api/calendar", calendar_public_default);
30630
+ app67.route("/api/portal", portal_fetch_default);
30539
30631
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
30540
30632
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
30541
30633
  var IMAGE_MIME = {
@@ -30547,7 +30639,7 @@ var IMAGE_MIME = {
30547
30639
  ".svg": "image/svg+xml",
30548
30640
  ".ico": "image/x-icon"
30549
30641
  };
30550
- app66.get("/agent-assets/:slug/:filename", (c) => {
30642
+ app67.get("/agent-assets/:slug/:filename", (c) => {
30551
30643
  const slug = c.req.param("slug");
30552
30644
  const filename = c.req.param("filename");
30553
30645
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -30563,13 +30655,13 @@ app66.get("/agent-assets/:slug/:filename", (c) => {
30563
30655
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
30564
30656
  return c.text("Not found", 404);
30565
30657
  }
30566
- const filePath = resolve42(account.accountDir, "agents", slug, "assets", filename);
30567
- const expectedDir = resolve42(account.accountDir, "agents", slug, "assets");
30658
+ const filePath = resolve43(account.accountDir, "agents", slug, "assets", filename);
30659
+ const expectedDir = resolve43(account.accountDir, "agents", slug, "assets");
30568
30660
  if (!filePath.startsWith(expectedDir + "/")) {
30569
30661
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
30570
30662
  return c.text("Forbidden", 403);
30571
30663
  }
30572
- if (!existsSync43(filePath)) {
30664
+ if (!existsSync45(filePath)) {
30573
30665
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
30574
30666
  return c.text("Not found", 404);
30575
30667
  }
@@ -30582,7 +30674,7 @@ app66.get("/agent-assets/:slug/:filename", (c) => {
30582
30674
  "Cache-Control": "public, max-age=3600"
30583
30675
  });
30584
30676
  });
30585
- app66.get("/generated/:filename", (c) => {
30677
+ app67.get("/generated/:filename", (c) => {
30586
30678
  const filename = c.req.param("filename");
30587
30679
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
30588
30680
  console.error(`[generated] serve file=${filename} status=403`);
@@ -30593,13 +30685,13 @@ app66.get("/generated/:filename", (c) => {
30593
30685
  console.error(`[generated] serve file=${filename} status=404`);
30594
30686
  return c.text("Not found", 404);
30595
30687
  }
30596
- const filePath = resolve42(account.accountDir, "generated", filename);
30597
- const expectedDir = resolve42(account.accountDir, "generated");
30688
+ const filePath = resolve43(account.accountDir, "generated", filename);
30689
+ const expectedDir = resolve43(account.accountDir, "generated");
30598
30690
  if (!filePath.startsWith(expectedDir + "/")) {
30599
30691
  console.error(`[generated] serve file=${filename} status=403`);
30600
30692
  return c.text("Forbidden", 403);
30601
30693
  }
30602
- if (!existsSync43(filePath)) {
30694
+ if (!existsSync45(filePath)) {
30603
30695
  console.error(`[generated] serve file=${filename} status=404`);
30604
30696
  return c.text("Not found", 404);
30605
30697
  }
@@ -30612,14 +30704,14 @@ app66.get("/generated/:filename", (c) => {
30612
30704
  "Cache-Control": "public, max-age=86400"
30613
30705
  });
30614
30706
  });
30615
- app66.route("/sites", sites_default);
30616
- app66.route("/listings", listings_default);
30617
- app66.route("/v", visitor_event_default);
30618
- app66.route("/v", visitor_consent_default);
30707
+ app67.route("/sites", sites_default);
30708
+ app67.route("/listings", listings_default);
30709
+ app67.route("/v", visitor_event_default);
30710
+ app67.route("/v", visitor_consent_default);
30619
30711
  var htmlCache = /* @__PURE__ */ new Map();
30620
30712
  var brandLogoPath = "/brand/maxy-monochrome.png";
30621
30713
  var brandIconPath = "/brand/maxy-monochrome.png";
30622
- if (BRAND_JSON_PATH && existsSync43(BRAND_JSON_PATH)) {
30714
+ if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
30623
30715
  try {
30624
30716
  const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
30625
30717
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
@@ -30648,11 +30740,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
30648
30740
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
30649
30741
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
30650
30742
  var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
30651
- (p) => existsSync43(resolve42(process.cwd(), "public", p.replace(/^\//, "")))
30743
+ (p) => existsSync45(resolve43(process.cwd(), "public", p.replace(/^\//, "")))
30652
30744
  );
30653
30745
  var SW_SOURCE = (() => {
30654
30746
  try {
30655
- return readFileSync46(resolve42(process.cwd(), "public", "sw.js"), "utf-8");
30747
+ return readFileSync46(resolve43(process.cwd(), "public", "sw.js"), "utf-8");
30656
30748
  } catch {
30657
30749
  return null;
30658
30750
  }
@@ -30661,7 +30753,7 @@ function readInstalledVersion() {
30661
30753
  try {
30662
30754
  if (!PLATFORM_ROOT8) return "unknown";
30663
30755
  const versionFile = join47(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
30664
- if (!existsSync43(versionFile)) return "unknown";
30756
+ if (!existsSync45(versionFile)) return "unknown";
30665
30757
  const content = readFileSync46(versionFile, "utf-8").trim();
30666
30758
  return content || "unknown";
30667
30759
  } catch {
@@ -30703,7 +30795,7 @@ var clientErrorReporterScript = `<script>
30703
30795
  function cachedHtml(file) {
30704
30796
  let html = htmlCache.get(file);
30705
30797
  if (!html) {
30706
- html = readFileSync46(resolve42(process.cwd(), "public", file), "utf-8");
30798
+ html = readFileSync46(resolve43(process.cwd(), "public", file), "utf-8");
30707
30799
  const productNameEsc = escapeHtml(BRAND.productName);
30708
30800
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
30709
30801
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -30725,7 +30817,7 @@ function loadBrandingCache(agentSlug) {
30725
30817
  const accountId = getDefaultAccountId();
30726
30818
  if (!accountId) return null;
30727
30819
  const cachePath = join47(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
30728
- if (!existsSync43(cachePath)) return null;
30820
+ if (!existsSync45(cachePath)) return null;
30729
30821
  return JSON.parse(readFileSync46(cachePath, "utf-8"));
30730
30822
  } catch {
30731
30823
  return null;
@@ -30770,7 +30862,7 @@ function brandedPublicHtml(agentSlug) {
30770
30862
  function agentUnavailableHtml() {
30771
30863
  return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
30772
30864
  }
30773
- app66.get("/", (c) => {
30865
+ app67.get("/", (c) => {
30774
30866
  const host = (c.req.header("host") ?? "").split(":")[0];
30775
30867
  const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
30776
30868
  if (klass === "operator") {
@@ -30792,12 +30884,12 @@ app66.get("/", (c) => {
30792
30884
  console.log(`[host-class] host=${host} class=admin served=index.html`);
30793
30885
  return c.html(cachedHtml("index.html"));
30794
30886
  });
30795
- app66.get("/public", (c) => {
30887
+ app67.get("/public", (c) => {
30796
30888
  const host = (c.req.header("host") ?? "").split(":")[0];
30797
30889
  if (isPublicHost(host)) return c.text("Not found", 404);
30798
30890
  return c.html(cachedHtml("public.html"));
30799
30891
  });
30800
- app66.get("/public-chat", (c) => {
30892
+ app67.get("/public-chat", (c) => {
30801
30893
  const host = (c.req.header("host") ?? "").split(":")[0];
30802
30894
  if (isPublicHost(host)) return c.text("Not found", 404);
30803
30895
  return c.html(cachedHtml("public.html"));
@@ -30816,12 +30908,12 @@ async function logViewerFetch(c, next) {
30816
30908
  duration_ms: Date.now() - start
30817
30909
  });
30818
30910
  }
30819
- app66.use("/vnc-viewer.html", logViewerFetch);
30820
- app66.use("/vnc-popout.html", logViewerFetch);
30821
- app66.get("/vnc-popout.html", (c) => {
30911
+ app67.use("/vnc-viewer.html", logViewerFetch);
30912
+ app67.use("/vnc-popout.html", logViewerFetch);
30913
+ app67.get("/vnc-popout.html", (c) => {
30822
30914
  let html = htmlCache.get("vnc-popout.html");
30823
30915
  if (!html) {
30824
- html = readFileSync46(resolve42(process.cwd(), "public", "vnc-popout.html"), "utf-8");
30916
+ html = readFileSync46(resolve43(process.cwd(), "public", "vnc-popout.html"), "utf-8");
30825
30917
  const name = escapeHtml(BRAND.productName);
30826
30918
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
30827
30919
  html = html.replace("</head>", ` ${brandScript}
@@ -30831,7 +30923,7 @@ app66.get("/vnc-popout.html", (c) => {
30831
30923
  }
30832
30924
  return c.html(html);
30833
30925
  });
30834
- app66.post("/api/vnc/client-event", async (c) => {
30926
+ app67.post("/api/vnc/client-event", async (c) => {
30835
30927
  let body;
30836
30928
  try {
30837
30929
  body = await c.req.json();
@@ -30852,11 +30944,11 @@ app66.post("/api/vnc/client-event", async (c) => {
30852
30944
  });
30853
30945
  return c.json({ ok: true });
30854
30946
  });
30855
- app66.get("/g/:slug", (c) => {
30947
+ app67.get("/g/:slug", (c) => {
30856
30948
  return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
30857
30949
  });
30858
30950
  for (const pwa of PWA_SURFACES) {
30859
- app66.get(pwa.manifestPath, (c) => {
30951
+ app67.get(pwa.manifestPath, (c) => {
30860
30952
  const manifest = buildManifest(pwa, {
30861
30953
  productName: BRAND.productName,
30862
30954
  appIcon192: brandAppIcon192Path,
@@ -30872,7 +30964,7 @@ for (const pwa of PWA_SURFACES) {
30872
30964
  return c.body(JSON.stringify(manifest));
30873
30965
  });
30874
30966
  }
30875
- app66.get("/sw.js", (c) => {
30967
+ app67.get("/sw.js", (c) => {
30876
30968
  if (SW_SOURCE == null) {
30877
30969
  console.error("[pwa] op=sw status=500 reason=sw-source-missing");
30878
30970
  return c.text("Service worker unavailable", 500);
@@ -30881,12 +30973,12 @@ app66.get("/sw.js", (c) => {
30881
30973
  console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
30882
30974
  return c.body(SW_SOURCE);
30883
30975
  });
30884
- app66.get("/graph", (c) => {
30976
+ app67.get("/graph", (c) => {
30885
30977
  const host = (c.req.header("host") ?? "").split(":")[0];
30886
30978
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
30887
30979
  return c.html(cachedHtml("graph.html"));
30888
30980
  });
30889
- app66.get("/chat", (c) => {
30981
+ app67.get("/chat", (c) => {
30890
30982
  const host = (c.req.header("host") ?? "").split(":")[0];
30891
30983
  if (isOperatorHost(host, getOperatorDomains())) {
30892
30984
  console.log(`[host-class] host=${host} class=operator served=operator.html`);
@@ -30895,42 +30987,42 @@ app66.get("/chat", (c) => {
30895
30987
  if (isPublicHost(host)) return c.text("Not found", 404);
30896
30988
  return c.html(cachedHtml("chat.html"));
30897
30989
  });
30898
- app66.get("/data", (c) => {
30990
+ app67.get("/data", (c) => {
30899
30991
  const host = (c.req.header("host") ?? "").split(":")[0];
30900
30992
  if (isPublicHost(host)) return c.text("Not found", 404);
30901
30993
  return c.html(cachedHtml("data.html"));
30902
30994
  });
30903
- app66.get("/tasks", (c) => {
30995
+ app67.get("/tasks", (c) => {
30904
30996
  const host = (c.req.header("host") ?? "").split(":")[0];
30905
30997
  if (isPublicHost(host)) return c.text("Not found", 404);
30906
30998
  return c.html(cachedHtml("tasks.html"));
30907
30999
  });
30908
- app66.get("/activity", (c) => {
31000
+ app67.get("/activity", (c) => {
30909
31001
  const host = (c.req.header("host") ?? "").split(":")[0];
30910
31002
  if (isPublicHost(host)) return c.text("Not found", 404);
30911
31003
  return c.html(cachedHtml("activity.html"));
30912
31004
  });
30913
- app66.get("/calendar", (c) => {
31005
+ app67.get("/calendar", (c) => {
30914
31006
  const host = (c.req.header("host") ?? "").split(":")[0];
30915
31007
  if (isPublicHost(host)) return c.text("Not found", 404);
30916
31008
  return c.html(cachedHtml("calendar.html"));
30917
31009
  });
30918
- app66.get("/routines", (c) => {
31010
+ app67.get("/routines", (c) => {
30919
31011
  const host = (c.req.header("host") ?? "").split(":")[0];
30920
31012
  if (isPublicHost(host)) return c.text("Not found", 404);
30921
31013
  return c.html(cachedHtml("routines.html"));
30922
31014
  });
30923
- app66.get("/skills", (c) => {
31015
+ app67.get("/skills", (c) => {
30924
31016
  const host = (c.req.header("host") ?? "").split(":")[0];
30925
31017
  if (isPublicHost(host)) return c.text("Not found", 404);
30926
31018
  return c.html(cachedHtml("skills.html"));
30927
31019
  });
30928
- app66.get("/browser", (c) => {
31020
+ app67.get("/browser", (c) => {
30929
31021
  const host = (c.req.header("host") ?? "").split(":")[0];
30930
31022
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
30931
31023
  return c.html(cachedHtml("browser.html"));
30932
31024
  });
30933
- app66.get("/:slug", async (c, next) => {
31025
+ app67.get("/:slug", async (c, next) => {
30934
31026
  const slug = c.req.param("slug");
30935
31027
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
30936
31028
  const account = resolveAccount();
@@ -30945,13 +31037,13 @@ app66.get("/:slug", async (c, next) => {
30945
31037
  await next();
30946
31038
  });
30947
31039
  if (brandFaviconPath !== "/favicon.ico") {
30948
- app66.get("/favicon.ico", (c) => {
31040
+ app67.get("/favicon.ico", (c) => {
30949
31041
  c.header("Cache-Control", "public, max-age=300");
30950
31042
  return c.redirect(brandFaviconPath, 302);
30951
31043
  });
30952
31044
  }
30953
- app66.use("/*", serveStatic({ root: "./public" }));
30954
- app66.all("*", (c) => {
31045
+ app67.use("/*", serveStatic({ root: "./public" }));
31046
+ app67.all("*", (c) => {
30955
31047
  const host = (c.req.header("host") ?? "").split(":")[0];
30956
31048
  const path3 = c.req.path;
30957
31049
  if (isPublicHost(host)) {
@@ -30965,13 +31057,13 @@ app66.all("*", (c) => {
30965
31057
  });
30966
31058
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
30967
31059
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
30968
- var httpServer = serve({ fetch: app66.fetch, port, hostname });
31060
+ var httpServer = serve({ fetch: app67.fetch, port, hostname });
30969
31061
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
30970
31062
  {
30971
31063
  const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
30972
- const reconcileScript = resolve42(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
31064
+ const reconcileScript = resolve43(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
30973
31065
  const runReconcile = (ctx) => {
30974
- if (!existsSync43(reconcileScript)) return;
31066
+ if (!existsSync45(reconcileScript)) return;
30975
31067
  try {
30976
31068
  const child = spawn3(process.execPath, [reconcileScript], {
30977
31069
  env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
@@ -31010,14 +31102,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31010
31102
  {
31011
31103
  const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
31012
31104
  const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31013
- const dreamSweepScript = resolve42(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31105
+ const dreamSweepScript = resolve43(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31014
31106
  registerLoop({
31015
31107
  name: "dream-cycle-sweep",
31016
31108
  intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
31017
31109
  firstRunDelayMs: 3e4,
31018
31110
  detached: true,
31019
31111
  run: (ctx) => {
31020
- if (!existsSync43(dreamSweepScript)) return;
31112
+ if (!existsSync45(dreamSweepScript)) return;
31021
31113
  try {
31022
31114
  const child = spawn3(process.execPath, [dreamSweepScript], {
31023
31115
  env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
@@ -31034,10 +31126,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31034
31126
  }
31035
31127
  {
31036
31128
  const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31037
- const outlookScript = resolve42(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31129
+ const outlookScript = resolve43(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31038
31130
  const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
31039
31131
  const runOutlookComplete = (ctx) => {
31040
- if (!existsSync43(outlookScript)) return;
31132
+ if (!existsSync45(outlookScript)) return;
31041
31133
  try {
31042
31134
  const child = spawn3(process.execPath, [outlookScript], {
31043
31135
  env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
@@ -31060,19 +31152,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31060
31152
  }
31061
31153
  {
31062
31154
  const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31063
- const strandedAccountsDir = resolve42(auditRoot, "..", "data/accounts");
31155
+ const strandedAccountsDir = resolve43(auditRoot, "..", "data/accounts");
31064
31156
  const STRANDED_AUDIT_INTERVAL_MS = 3e5;
31065
31157
  const STRANDED_AGE_MS = 16 * 6e4;
31066
31158
  const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31067
31159
  const runStrandedAudit = () => {
31068
31160
  try {
31069
- if (!existsSync43(strandedAccountsDir)) return;
31161
+ if (!existsSync45(strandedAccountsDir)) return;
31070
31162
  const now = Date.now();
31071
31163
  for (const name of readdirSync27(strandedAccountsDir)) {
31072
31164
  if (!STRANDED_UUID_RE.test(name)) continue;
31073
- const pendingPath2 = resolve42(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31074
- if (!existsSync43(pendingPath2)) continue;
31075
- const ageMs2 = now - statSync18(pendingPath2).mtimeMs;
31165
+ const pendingPath2 = resolve43(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31166
+ if (!existsSync45(pendingPath2)) continue;
31167
+ const ageMs2 = now - statSync20(pendingPath2).mtimeMs;
31076
31168
  if (ageMs2 > STRANDED_AGE_MS) {
31077
31169
  console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
31078
31170
  }
@@ -31090,7 +31182,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31090
31182
  }
31091
31183
  {
31092
31184
  const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31093
- const googleAccountsDir = resolve42(googleRoot, "..", "data/accounts");
31185
+ const googleAccountsDir = resolve43(googleRoot, "..", "data/accounts");
31094
31186
  const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
31095
31187
  const runGooglePendingAuditSafe = () => {
31096
31188
  try {
@@ -31105,10 +31197,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31105
31197
  firstRunDelayMs: 27e3,
31106
31198
  run: runGooglePendingAuditSafe
31107
31199
  });
31108
- const googleAuditScript = resolve42(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31200
+ const googleAuditScript = resolve43(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31109
31201
  const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
31110
31202
  const runGoogleAccountAudit = (ctx) => {
31111
- if (!existsSync43(googleAuditScript)) return;
31203
+ if (!existsSync45(googleAuditScript)) return;
31112
31204
  try {
31113
31205
  const child = spawn3(process.execPath, [googleAuditScript], {
31114
31206
  env: { ...process.env, PLATFORM_ROOT: googleRoot },
@@ -31180,7 +31272,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31180
31272
  }
31181
31273
  {
31182
31274
  const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31183
- const publishScript = resolve42(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31275
+ const publishScript = resolve43(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31184
31276
  const PUBLISH_INTERVAL_MS = 3e5;
31185
31277
  const bookingAccounts = () => {
31186
31278
  try {
@@ -31191,7 +31283,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31191
31283
  }
31192
31284
  };
31193
31285
  const spawnPublish = (account, ctx) => {
31194
- if (!existsSync43(publishScript)) return;
31286
+ if (!existsSync45(publishScript)) return;
31195
31287
  try {
31196
31288
  const child = spawn3(process.execPath, [publishScript], {
31197
31289
  env: {
@@ -31210,19 +31302,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31210
31302
  }
31211
31303
  };
31212
31304
  const auditSnapshotAge = (account) => {
31213
- const availPath = resolve42(account.accountDir, "calendar-availability.json");
31305
+ const availPath = resolve43(account.accountDir, "calendar-availability.json");
31214
31306
  let hasBookingSite = false;
31215
31307
  try {
31216
- if (existsSync43(availPath)) {
31308
+ if (existsSync45(availPath)) {
31217
31309
  const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
31218
31310
  hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
31219
31311
  }
31220
31312
  } catch {
31221
31313
  }
31222
31314
  if (!hasBookingSite) return;
31223
- const statePath = resolve42(account.accountDir, "state", "booking-availability", "last-publish.json");
31315
+ const statePath = resolve43(account.accountDir, "state", "booking-availability", "last-publish.json");
31224
31316
  let lastSuccessAt = null;
31225
- if (existsSync43(statePath)) {
31317
+ if (existsSync45(statePath)) {
31226
31318
  try {
31227
31319
  const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
31228
31320
  lastSuccessAt = rec.lastSuccessAt ?? null;
@@ -31257,11 +31349,11 @@ startTimeEntryCensus(() => getSession());
31257
31349
  startLedgerCensus(() => getSession());
31258
31350
  {
31259
31351
  const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31260
- const auditScript = resolve42(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31352
+ const auditScript = resolve43(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31261
31353
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
31262
31354
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
31263
31355
  const runConnectorAudit = (ctx) => {
31264
- if (!existsSync43(auditScript)) return;
31356
+ if (!existsSync45(auditScript)) return;
31265
31357
  try {
31266
31358
  const child = spawn3(process.execPath, [auditScript], {
31267
31359
  env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
@@ -31341,7 +31433,7 @@ for (const m of SUBAPP_MANIFEST) {
31341
31433
  }
31342
31434
  try {
31343
31435
  const registered = [];
31344
- for (const r of app66.routes ?? []) {
31436
+ for (const r of app67.routes ?? []) {
31345
31437
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
31346
31438
  if (AGENT_SLUG_PATTERN.test(r.path)) {
31347
31439
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -31381,7 +31473,7 @@ try {
31381
31473
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31382
31474
  async function runAdminUserReconcileTick() {
31383
31475
  try {
31384
- if (!existsSync43(USERS_FILE)) {
31476
+ if (!existsSync45(USERS_FILE)) {
31385
31477
  console.error("[adminuser-self-heal] skip reason=no-users-file");
31386
31478
  return;
31387
31479
  }
@@ -31432,7 +31524,7 @@ registerLoop({
31432
31524
  });
31433
31525
  var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31434
31526
  function countUsersRows() {
31435
- if (!existsSync43(USERS_FILE)) return 0;
31527
+ if (!existsSync45(USERS_FILE)) return 0;
31436
31528
  const raw = readFileSync46(USERS_FILE, "utf-8").trim();
31437
31529
  if (!raw) return 0;
31438
31530
  const users = JSON.parse(raw);
@@ -31502,7 +31594,7 @@ try {
31502
31594
  } catch (err) {
31503
31595
  console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
31504
31596
  }
31505
- var configDirForWhatsApp = basename13(MAXY_DIR) || ".maxy";
31597
+ var configDirForWhatsApp = basename14(MAXY_DIR) || ".maxy";
31506
31598
  var bootAccount = resolveAccount();
31507
31599
  if (bootAccount) {
31508
31600
  migrateRemovedConfigKeys(bootAccount.accountDir);
@@ -31566,7 +31658,7 @@ if (bootAccountConfig?.whatsapp) {
31566
31658
  }
31567
31659
  init({
31568
31660
  configDir: configDirForWhatsApp,
31569
- platformRoot: resolve42(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
31661
+ platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
31570
31662
  accountConfig: bootAccountConfig,
31571
31663
  onMessage: async (msg) => {
31572
31664
  if (isObserveAccount(msg.accountId)) {