@rubytech/create-maxy-code 0.1.198 → 0.1.200

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 (84) hide show
  1. package/package.json +2 -2
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3736 -0
  3. package/payload/platform/plugins/docs/references/admin-ui.md +3 -1
  4. package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +67 -0
  5. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  6. package/payload/platform/services/claude-session-manager/dist/http-server.js +56 -0
  7. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +18 -0
  9. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  10. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +25 -15
  11. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  12. package/payload/platform/templates/agents/admin/IDENTITY.md +4 -0
  13. package/payload/platform/templates/agents/public/IDENTITY.md +1 -1
  14. package/payload/server/public/assets/AdminShell-OJlDJakR.js +1 -0
  15. package/payload/server/public/assets/{Checkbox-Bh3kwzxP.js → Checkbox-DE_tsDq_.js} +1 -1
  16. package/payload/server/public/assets/{admin-BWzKAudL.js → admin-DbQw1TyC.js} +1 -1
  17. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Boys2mT1.js → architectureDiagram-Q4EWVU46-DfZVWJVr.js} +1 -1
  18. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CvHqp46r.js → blockDiagram-DXYQGD6D-Cd9vcTYg.js} +1 -1
  19. package/payload/server/public/assets/{brand-VQtREmts.css → brand-Ed5R2W5J.css} +1 -1
  20. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DiNQ95F6.js → c4Diagram-AHTNJAMY-zmNCfJ5F.js} +1 -1
  21. package/payload/server/public/assets/channel-DCJza6li.js +1 -0
  22. package/payload/server/public/assets/{chunk-336JU56O-9nS9-05M.js → chunk-336JU56O-DvHeoV7B.js} +2 -2
  23. package/payload/server/public/assets/{chunk-426QAEUC-B2__9lRY.js → chunk-426QAEUC-IZknbXMM.js} +1 -1
  24. package/payload/server/public/assets/{chunk-4TB4RGXK-R5F8rS0Z.js → chunk-4TB4RGXK-DN_qw6Oi.js} +1 -1
  25. package/payload/server/public/assets/{chunk-5FUZZQ4R-B8HhJce-.js → chunk-5FUZZQ4R-tt-46Rcq.js} +1 -1
  26. package/payload/server/public/assets/{chunk-5PVQY5BW-Bjb08lbL.js → chunk-5PVQY5BW-Bl0mxmQP.js} +1 -1
  27. package/payload/server/public/assets/{chunk-EDXVE4YY-he0qCF3s.js → chunk-EDXVE4YY-v31HwKDb.js} +1 -1
  28. package/payload/server/public/assets/{chunk-ENJZ2VHE-BTArFW5l.js → chunk-ENJZ2VHE-D6T1RStj.js} +1 -1
  29. package/payload/server/public/assets/{chunk-ICPOFSXX-CoyIL4q_.js → chunk-ICPOFSXX-DVnIs_5A.js} +1 -1
  30. package/payload/server/public/assets/{chunk-OYMX7WX6-DjLEhNFe.js → chunk-OYMX7WX6-DiZNprr1.js} +1 -1
  31. package/payload/server/public/assets/{chunk-U2HBQHQK-tac2uvW1.js → chunk-U2HBQHQK-Cy0qH3H0.js} +1 -1
  32. package/payload/server/public/assets/{chunk-X2U36JSP-DIWD9i88.js → chunk-X2U36JSP-wR3wBPyu.js} +1 -1
  33. package/payload/server/public/assets/{chunk-YZCP3GAM-Ac7ogADz.js → chunk-YZCP3GAM-BGOVJLky.js} +1 -1
  34. package/payload/server/public/assets/{chunk-ZZ45TVLE-QgqDaY9-.js → chunk-ZZ45TVLE-14vtIjRh.js} +1 -1
  35. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DEo4goqG.js +1 -0
  36. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CoAVCeH7.js +1 -0
  37. package/payload/server/public/assets/clone-CLnBlH9n.js +1 -0
  38. package/payload/server/public/assets/{dagre-D6qN4nkK.js → dagre-CG1l6rfK.js} +1 -1
  39. package/payload/server/public/assets/{dagre-KV5264BT-C6TRKOg0.js → dagre-KV5264BT-DKFDl1Nz.js} +1 -1
  40. package/payload/server/public/assets/{data-CaZbNF-j.js → data-b1v7Pjly.js} +1 -1
  41. package/payload/server/public/assets/{diagram-5BDNPKRD-BVk_J8Pt.js → diagram-5BDNPKRD-PJd29fkg.js} +1 -1
  42. package/payload/server/public/assets/{diagram-G4DWMVQ6-BdV1IgwS.js → diagram-G4DWMVQ6-Bz7_SWJH.js} +1 -1
  43. package/payload/server/public/assets/{diagram-MMDJMWI5-OsvBkN6u.js → diagram-MMDJMWI5-CmWknm9v.js} +1 -1
  44. package/payload/server/public/assets/{diagram-TYMM5635-BQmKPyrb.js → diagram-TYMM5635-CLYRluM2.js} +1 -1
  45. package/payload/server/public/assets/{erDiagram-SMLLAGMA-ChEx5_3C.js → erDiagram-SMLLAGMA-EWVKGrgT.js} +1 -1
  46. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B7sf6AG3.js → flowDiagram-DWJPFMVM-CNtfJIG7.js} +1 -1
  47. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DbpSraax.js → ganttDiagram-T4ZO3ILL-SIlymJ6A.js} +1 -1
  48. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BnxDElDh.js → gitGraphDiagram-UUTBAWPF-DWVl6CUl.js} +1 -1
  49. package/payload/server/public/assets/{graph-CBP5yppq.js → graph-BOcblKu9.js} +1 -1
  50. package/payload/server/public/assets/{graph-labels-BsZNScfa.js → graph-labels-CH-Tffon.js} +1 -1
  51. package/payload/server/public/assets/{graphlib-Dux06enE.js → graphlib-i-qJjJM7.js} +1 -1
  52. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BLWb6oKx.js → infoDiagram-42DDH7IO-D66Yr_7b.js} +1 -1
  53. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-AFiRuE6G.js → ishikawaDiagram-UXIWVN3A-C4mQi7AB.js} +1 -1
  54. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CxHBRGGu.js → journeyDiagram-VCZTEJTY-7Vp2UBlF.js} +1 -1
  55. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CGugF0N8.js → kanban-definition-6JOO6SKY-nEDANSe9.js} +1 -1
  56. package/payload/server/public/assets/{line-COFloj-X.js → line-BxGbTwly.js} +1 -1
  57. package/payload/server/public/assets/{mermaid-parser.core-CxXuCDQf.js → mermaid-parser.core-CAG4AdDd.js} +1 -1
  58. package/payload/server/public/assets/{mermaid.core-BRBNvNup.js → mermaid.core-prtUaAsI.js} +3 -3
  59. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DarW5Wwq.js → mindmap-definition-QFDTVHPH-Dvcph8zi.js} +1 -1
  60. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CTokFAkN.js → pieDiagram-DEJITSTG-C4qHs6Vb.js} +1 -1
  61. package/payload/server/public/assets/{public-Bq-eOUu9.js → public-DIyn-De4.js} +3 -3
  62. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BNawkg3I.js → quadrantDiagram-34T5L4WZ-I9Et2l2H.js} +1 -1
  63. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CWnO56oR.js → requirementDiagram-MS252O5E-DLKlY81v.js} +1 -1
  64. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-D9c-EZfV.js → sankeyDiagram-XADWPNL6-dX3pgMv_.js} +1 -1
  65. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-In5lxCT5.js → sequenceDiagram-FGHM5R23-C4qTAl3F.js} +1 -1
  66. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CYb5js-u.js → stateDiagram-FHFEXIEX-DzA0NObk.js} +1 -1
  67. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Dsgd5hEe.js +1 -0
  68. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Cje-BY9v.js → timeline-definition-GMOUNBTQ-D-DPUQCU.js} +1 -1
  69. package/payload/server/public/assets/{useSelectionMode-B_2EQ2CC.js → useSelectionMode-C4HDuwDT.js} +1 -1
  70. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BqeuoPr1.js → vennDiagram-DHZGUBPP-C_RwTsUi.js} +1 -1
  71. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DE7xAnoq.js → wardleyDiagram-NUSXRM2D-BAftlsC2.js} +1 -1
  72. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JE4x8YEZ.js → xychartDiagram-5P7HB3ND-C_tKMCMd.js} +1 -1
  73. package/payload/server/public/data.html +5 -5
  74. package/payload/server/public/graph.html +6 -6
  75. package/payload/server/public/index.html +6 -6
  76. package/payload/server/public/public.html +5 -5
  77. package/payload/server/server.js +399 -245
  78. package/payload/server/public/assets/AdminShell-DPk5UgEJ.js +0 -1
  79. package/payload/server/public/assets/channel-BgwH_qhE.js +0 -1
  80. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CwdV1-c8.js +0 -1
  81. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CS_jtevB.js +0 -1
  82. package/payload/server/public/assets/clone-BTishuSs.js +0 -1
  83. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-z-TVJfRt.js +0 -1
  84. /package/payload/server/public/assets/{brand-CzeO4m4J.js → brand-CCOPpjM4.js} +0 -0
@@ -816,8 +816,8 @@ var serveStatic = (options = { root: "" }) => {
816
816
  };
817
817
 
818
818
  // server/index.ts
819
- import { readFileSync as readFileSync21, existsSync as existsSync21, watchFile } from "fs";
820
- import { resolve as resolve22, join as join16, basename as basename6 } from "path";
819
+ import { readFileSync as readFileSync22, existsSync as existsSync22, watchFile } from "fs";
820
+ import { resolve as resolve23, join as join17, basename as basename6 } from "path";
821
821
  import { homedir as homedir2 } from "os";
822
822
  import { monitorEventLoopDelay } from "perf_hooks";
823
823
 
@@ -1275,7 +1275,7 @@ var credsSaveQueue = Promise.resolve();
1275
1275
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1276
1276
  console.error(`${TAG2} draining credential save queue\u2026`);
1277
1277
  const timer2 = new Promise(
1278
- (resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
1278
+ (resolve24) => setTimeout(() => resolve24("timeout"), timeoutMs)
1279
1279
  );
1280
1280
  const result = await Promise.race([
1281
1281
  credsSaveQueue.then(() => "drained"),
@@ -1403,11 +1403,11 @@ async function createWaSocket(opts) {
1403
1403
  return sock;
1404
1404
  }
1405
1405
  async function waitForConnection(sock) {
1406
- return new Promise((resolve23, reject) => {
1406
+ return new Promise((resolve24, reject) => {
1407
1407
  const handler = (update) => {
1408
1408
  if (update.connection === "open") {
1409
1409
  sock.ev.off("connection.update", handler);
1410
- resolve23();
1410
+ resolve24();
1411
1411
  }
1412
1412
  if (update.connection === "close") {
1413
1413
  sock.ev.off("connection.update", handler);
@@ -1521,14 +1521,14 @@ ${inspected}`;
1521
1521
  return inspect2(err, INSPECT_OPTS2);
1522
1522
  }
1523
1523
  function withTimeout(label, promise, timeoutMs) {
1524
- return new Promise((resolve23, reject) => {
1524
+ return new Promise((resolve24, reject) => {
1525
1525
  const timer2 = setTimeout(() => {
1526
1526
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1527
1527
  }, timeoutMs);
1528
1528
  promise.then(
1529
1529
  (value) => {
1530
1530
  clearTimeout(timer2);
1531
- resolve23(value);
1531
+ resolve24(value);
1532
1532
  },
1533
1533
  (err) => {
1534
1534
  clearTimeout(timer2);
@@ -2063,8 +2063,8 @@ async function persistWhatsAppMessage(input) {
2063
2063
  const { givenName, familyName } = splitName(input.pushName);
2064
2064
  const prev = sessionWriteLocks.get(input.cacheKey);
2065
2065
  let release;
2066
- const mine = new Promise((resolve23) => {
2067
- release = resolve23;
2066
+ const mine = new Promise((resolve24) => {
2067
+ release = resolve24;
2068
2068
  });
2069
2069
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2070
2070
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3100,11 +3100,11 @@ async function connectWithReconnect(conn) {
3100
3100
  console.error(
3101
3101
  `${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3102
3102
  );
3103
- await new Promise((resolve23) => {
3104
- const timer2 = setTimeout(resolve23, delay);
3103
+ await new Promise((resolve24) => {
3104
+ const timer2 = setTimeout(resolve24, delay);
3105
3105
  conn.abortController.signal.addEventListener("abort", () => {
3106
3106
  clearTimeout(timer2);
3107
- resolve23();
3107
+ resolve24();
3108
3108
  }, { once: true });
3109
3109
  });
3110
3110
  }
@@ -3112,16 +3112,16 @@ async function connectWithReconnect(conn) {
3112
3112
  }
3113
3113
  }
3114
3114
  function waitForDisconnectEvent(conn) {
3115
- return new Promise((resolve23) => {
3115
+ return new Promise((resolve24) => {
3116
3116
  if (!conn.sock) {
3117
- resolve23();
3117
+ resolve24();
3118
3118
  return;
3119
3119
  }
3120
3120
  const sock = conn.sock;
3121
3121
  const handler = (update) => {
3122
3122
  if (update.connection === "close") {
3123
3123
  sock.ev.off("connection.update", handler);
3124
- resolve23();
3124
+ resolve24();
3125
3125
  }
3126
3126
  };
3127
3127
  sock.ev.on("connection.update", handler);
@@ -3383,8 +3383,8 @@ async function handleInboundMessage(conn, msg) {
3383
3383
  const conversationKey = isGroup ? remoteJid : senderPhone;
3384
3384
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
3385
3385
  let resolvePending;
3386
- const sttPending = new Promise((resolve23) => {
3387
- resolvePending = resolve23;
3386
+ const sttPending = new Promise((resolve24) => {
3387
+ resolvePending = resolve24;
3388
3388
  });
3389
3389
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
3390
3390
  try {
@@ -3788,20 +3788,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
3788
3788
 
3789
3789
  // server/routes/health.ts
3790
3790
  function checkPort(port2, timeoutMs = 500) {
3791
- return new Promise((resolve23) => {
3791
+ return new Promise((resolve24) => {
3792
3792
  const socket = createConnection2(port2, "127.0.0.1");
3793
3793
  socket.setTimeout(timeoutMs);
3794
3794
  socket.once("connect", () => {
3795
3795
  socket.destroy();
3796
- resolve23(true);
3796
+ resolve24(true);
3797
3797
  });
3798
3798
  socket.once("error", () => {
3799
3799
  socket.destroy();
3800
- resolve23(false);
3800
+ resolve24(false);
3801
3801
  });
3802
3802
  socket.once("timeout", () => {
3803
3803
  socket.destroy();
3804
- resolve23(false);
3804
+ resolve24(false);
3805
3805
  });
3806
3806
  });
3807
3807
  }
@@ -4537,12 +4537,12 @@ async function dispatchOnce(input) {
4537
4537
  });
4538
4538
  if (!entry) return { error: "spawn-failed" };
4539
4539
  entry.lastInboundAt = Date.now();
4540
- let resolve23;
4540
+ let resolve24;
4541
4541
  const turnPromise = new Promise((r) => {
4542
- resolve23 = r;
4542
+ resolve24 = r;
4543
4543
  });
4544
4544
  const listener = (text) => {
4545
- resolve23(text);
4545
+ resolve24(text);
4546
4546
  };
4547
4547
  entry.subscribers.add(listener);
4548
4548
  const writeOk = await writeInput(entry, input.text);
@@ -4984,8 +4984,8 @@ async function startLogin(opts) {
4984
4984
  resetActiveLogin(accountId);
4985
4985
  let resolveQr = null;
4986
4986
  let rejectQr = null;
4987
- const qrPromise = new Promise((resolve23, reject) => {
4988
- resolveQr = resolve23;
4987
+ const qrPromise = new Promise((resolve24, reject) => {
4988
+ resolveQr = resolve24;
4989
4989
  rejectQr = reject;
4990
4990
  });
4991
4991
  const qrTimer = setTimeout(
@@ -7458,11 +7458,11 @@ app11.delete("/:id", requireAdminSession, async (c) => {
7458
7458
  const owned = await verifyConversationOwnership(sessionId, accountId);
7459
7459
  if (!owned) return c.json({ error: "Conversation not found" }, 404);
7460
7460
  const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-conversation-delete" });
7461
- const managerBase4 = `http://127.0.0.1:${managerPort}`;
7461
+ const managerBase5 = `http://127.0.0.1:${managerPort}`;
7462
7462
  const outcome = await cascadeAdminConversationDelete({
7463
7463
  sessionId,
7464
7464
  accountId,
7465
- managerBase: managerBase4
7465
+ managerBase: managerBase5
7466
7466
  });
7467
7467
  if (outcome.ok) return c.json({ ok: true, claudeSessionIds: outcome.claudeSessionIds });
7468
7468
  if (outcome.reason === "pty-still-alive") {
@@ -11159,7 +11159,7 @@ app18.post("/", requireAdminSession, async (c) => {
11159
11159
  return c.json({ error: "AdminConversation node is missing sessionId" }, 500);
11160
11160
  }
11161
11161
  const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "graph-page-cascade" });
11162
- const managerBase4 = `http://127.0.0.1:${managerPort}`;
11162
+ const managerBase5 = `http://127.0.0.1:${managerPort}`;
11163
11163
  try {
11164
11164
  await session.close();
11165
11165
  } catch {
@@ -11167,7 +11167,7 @@ app18.post("/", requireAdminSession, async (c) => {
11167
11167
  const outcome = await cascadeAdminConversationDelete({
11168
11168
  sessionId,
11169
11169
  accountId,
11170
- managerBase: managerBase4
11170
+ managerBase: managerBase5
11171
11171
  });
11172
11172
  const elapsed2 = Date.now() - started;
11173
11173
  const labelSummary2 = preflightLabels.join(",");
@@ -11723,8 +11723,8 @@ var sidebar_artefacts_default = app22;
11723
11723
  // server/routes/admin/sidebar-sessions.ts
11724
11724
  import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
11725
11725
  import { join as join13 } from "path";
11726
- var RC_URL_RE = /https:\/\/claude\.ai\/code\/session_[A-Za-z0-9_-]+/;
11727
11726
  var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
11727
+ var PID_FILE_RE = /^([0-9]+)\.json$/;
11728
11728
  var TITLE_MAX = 80;
11729
11729
  var app23 = new Hono();
11730
11730
  function claudeConfigDir() {
@@ -11772,8 +11772,8 @@ function enumerateJsonls(projectsRoot) {
11772
11772
  }
11773
11773
  return out;
11774
11774
  }
11775
- function liveSessionIdSet(configDir2) {
11776
- const out = /* @__PURE__ */ new Set();
11775
+ function sessionIdToPidMap(configDir2) {
11776
+ const out = /* @__PURE__ */ new Map();
11777
11777
  const sessionsDir = join13(configDir2, "sessions");
11778
11778
  let entries;
11779
11779
  try {
@@ -11782,7 +11782,11 @@ function liveSessionIdSet(configDir2) {
11782
11782
  return out;
11783
11783
  }
11784
11784
  for (const entry of entries) {
11785
- if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
11785
+ if (!entry.isFile()) continue;
11786
+ const m = entry.name.match(PID_FILE_RE);
11787
+ if (!m) continue;
11788
+ const pid = Number(m[1]);
11789
+ if (!Number.isFinite(pid) || pid <= 0) continue;
11786
11790
  let body;
11787
11791
  try {
11788
11792
  body = readFileSync14(join13(sessionsDir, entry.name), "utf8");
@@ -11797,7 +11801,7 @@ function liveSessionIdSet(configDir2) {
11797
11801
  }
11798
11802
  if (!parsed || typeof parsed !== "object") continue;
11799
11803
  const sid = parsed.sessionId;
11800
- if (typeof sid === "string" && sid.length > 0) out.add(sid);
11804
+ if (typeof sid === "string" && sid.length > 0) out.set(sid, pid);
11801
11805
  }
11802
11806
  return out;
11803
11807
  }
@@ -11822,21 +11826,23 @@ function firstUserMessage(body) {
11822
11826
  return null;
11823
11827
  }
11824
11828
  app23.get("/", requireAdminSession, async (c) => {
11829
+ const accountId = process.env.ACCOUNT_ID ?? null;
11825
11830
  const configDir2 = claudeConfigDir();
11826
11831
  if (!configDir2) {
11827
11832
  console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
11828
- return c.json({ sessions: [] });
11833
+ return c.json({ sessions: [], accountId });
11829
11834
  }
11830
11835
  const projectsRoot = join13(configDir2, "projects");
11831
11836
  const jsonls = enumerateJsonls(projectsRoot);
11832
- const liveIds = liveSessionIdSet(configDir2);
11837
+ const pidsBySession = sessionIdToPidMap(configDir2);
11833
11838
  const rows = [];
11834
11839
  const seenIds = /* @__PURE__ */ new Set();
11835
11840
  let liveCount = 0;
11836
- let rcCount = 0;
11837
11841
  let subagentCount = 0;
11838
11842
  for (const { path: path2, isSubagent } of jsonls) {
11839
- const base = path2.slice(path2.lastIndexOf("/") + 1);
11843
+ const lastSlash = path2.lastIndexOf("/");
11844
+ const base = path2.slice(lastSlash + 1);
11845
+ const projectDir = path2.slice(0, lastSlash);
11840
11846
  const sessionId = base.slice(0, -".jsonl".length);
11841
11847
  if (seenIds.has(sessionId)) {
11842
11848
  console.error(`[admin-sessions-list] duplicate-sessionId sessionId=${sessionId} path=${path2}`);
@@ -11851,30 +11857,176 @@ app23.get("/", requireAdminSession, async (c) => {
11851
11857
  } catch {
11852
11858
  continue;
11853
11859
  }
11854
- const urlMatch = body.match(RC_URL_RE);
11855
- const live = liveIds.has(sessionId);
11860
+ const pid = pidsBySession.get(sessionId) ?? null;
11861
+ const live = pid !== null;
11856
11862
  const title = firstUserMessage(body) ?? sessionId.slice(0, 8);
11857
- const row = {
11863
+ rows.push({
11858
11864
  sessionId,
11859
11865
  title,
11860
11866
  startedAt: new Date(mtimeMs).toISOString(),
11861
11867
  live,
11862
- isSubagent
11863
- };
11864
- if (urlMatch) row.rcUrl = urlMatch[0];
11865
- rows.push(row);
11868
+ isSubagent,
11869
+ pid,
11870
+ projectDir
11871
+ });
11866
11872
  if (live) liveCount += 1;
11867
- if (urlMatch) rcCount += 1;
11868
11873
  if (isSubagent) subagentCount += 1;
11869
11874
  }
11870
11875
  rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
11871
11876
  console.log(
11872
- `[admin-sessions-list] rows=${rows.length} live=${liveCount} rc=${rcCount} subagents=${subagentCount}`
11877
+ `[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
11873
11878
  );
11874
- return c.json({ sessions: rows });
11879
+ return c.json({ sessions: rows, accountId });
11875
11880
  });
11876
11881
  var sidebar_sessions_default = app23;
11877
11882
 
11883
+ // server/routes/admin/session-delete.ts
11884
+ import { existsSync as existsSync17, readdirSync as readdirSync9, readFileSync as readFileSync15, unlinkSync as unlinkSync2 } from "fs";
11885
+ import { join as join14, resolve as resolve16 } from "path";
11886
+ var app24 = new Hono();
11887
+ var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11888
+ var PID_FILE_RE2 = /^([0-9]+)\.json$/;
11889
+ function findPidForSession(configDir2, sessionId) {
11890
+ const sessionsDir = join14(configDir2, "sessions");
11891
+ let entries;
11892
+ try {
11893
+ entries = readdirSync9(sessionsDir, { withFileTypes: true });
11894
+ } catch {
11895
+ return null;
11896
+ }
11897
+ for (const entry of entries) {
11898
+ if (!entry.isFile()) continue;
11899
+ const m = entry.name.match(PID_FILE_RE2);
11900
+ if (!m) continue;
11901
+ const pid = Number(m[1]);
11902
+ if (!Number.isFinite(pid) || pid <= 0) continue;
11903
+ let body;
11904
+ try {
11905
+ body = readFileSync15(join14(sessionsDir, entry.name), "utf8");
11906
+ } catch {
11907
+ continue;
11908
+ }
11909
+ let parsed;
11910
+ try {
11911
+ parsed = JSON.parse(body);
11912
+ } catch {
11913
+ continue;
11914
+ }
11915
+ if (!parsed || typeof parsed !== "object") continue;
11916
+ if (parsed.sessionId === sessionId) return pid;
11917
+ }
11918
+ return null;
11919
+ }
11920
+ function killBestEffort(pid) {
11921
+ try {
11922
+ process.kill(pid, "SIGTERM");
11923
+ return true;
11924
+ } catch {
11925
+ return false;
11926
+ }
11927
+ }
11928
+ app24.post("/", requireAdminSession, async (c) => {
11929
+ let body;
11930
+ try {
11931
+ body = await c.req.json();
11932
+ } catch {
11933
+ return c.json({ error: "invalid JSON body" }, 400);
11934
+ }
11935
+ const sessionId = typeof body.sessionId === "string" ? body.sessionId : "";
11936
+ const projectDir = typeof body.projectDir === "string" ? body.projectDir : "";
11937
+ if (!SESSION_ID_RE2.test(sessionId)) {
11938
+ return c.json({ error: "sessionId must be a v4 UUID" }, 400);
11939
+ }
11940
+ if (!projectDir) {
11941
+ return c.json({ error: "projectDir is required" }, 400);
11942
+ }
11943
+ const configDir2 = process.env.CLAUDE_CONFIG_DIR;
11944
+ if (!configDir2) {
11945
+ return c.json({ error: "CLAUDE_CONFIG_DIR not set" }, 500);
11946
+ }
11947
+ const projectsRoot = resolve16(join14(configDir2, "projects")) + "/";
11948
+ const resolvedProject = resolve16(projectDir) + "/";
11949
+ if (!resolvedProject.startsWith(projectsRoot)) {
11950
+ console.error(`[sessions-delete] reject reason=projectDir-outside-tree projectDir=${projectDir}`);
11951
+ return c.json({ error: "projectDir is not under CLAUDE_CONFIG_DIR/projects/" }, 400);
11952
+ }
11953
+ const jsonlPath = join14(projectDir, `${sessionId}.jsonl`);
11954
+ const sidecarPath = join14(projectDir, `${sessionId}.meta.json`);
11955
+ const pid = findPidForSession(configDir2, sessionId);
11956
+ let pidKilled;
11957
+ if (pid === null) {
11958
+ pidKilled = "absent";
11959
+ } else {
11960
+ pidKilled = killBestEffort(pid) ? "true" : "false";
11961
+ }
11962
+ let deleted = false;
11963
+ try {
11964
+ if (existsSync17(jsonlPath)) {
11965
+ unlinkSync2(jsonlPath);
11966
+ deleted = true;
11967
+ }
11968
+ } catch (err) {
11969
+ const msg = err instanceof Error ? err.message : String(err);
11970
+ console.error(`[sessions-delete] unlink-failed path=${jsonlPath} err=${msg}`);
11971
+ console.log(
11972
+ `[sessions-delete] sessionId=${sessionId} pidKilled=${pidKilled} jsonlPath=${jsonlPath} deleted=false`
11973
+ );
11974
+ return c.json({ error: `unlink failed: ${msg}` }, 500);
11975
+ }
11976
+ try {
11977
+ if (existsSync17(sidecarPath)) unlinkSync2(sidecarPath);
11978
+ } catch {
11979
+ }
11980
+ console.log(
11981
+ `[sessions-delete] sessionId=${sessionId} pidKilled=${pidKilled} jsonlPath=${jsonlPath} deleted=${deleted}`
11982
+ );
11983
+ return c.json({ deleted, pidKilled, jsonlPath });
11984
+ });
11985
+ var session_delete_default = app24;
11986
+
11987
+ // server/routes/admin/session-rc-spawn.ts
11988
+ var app25 = new Hono();
11989
+ function managerBase4() {
11990
+ const port2 = process.env.CLAUDE_SESSION_MANAGER_PORT;
11991
+ if (!port2) throw new Error("CLAUDE_SESSION_MANAGER_PORT is not set");
11992
+ return `http://127.0.0.1:${port2}`;
11993
+ }
11994
+ app25.post("/", requireAdminSession, async (c) => {
11995
+ let body;
11996
+ try {
11997
+ body = await c.req.json();
11998
+ } catch {
11999
+ body = {};
12000
+ }
12001
+ const payload = {};
12002
+ if (typeof body.sessionId === "string" && body.sessionId.length > 0) payload.sessionId = body.sessionId;
12003
+ if (typeof body.name === "string" && body.name.length > 0) payload.name = body.name;
12004
+ let res;
12005
+ try {
12006
+ res = await fetch(`${managerBase4()}/rc-spawn`, {
12007
+ method: "POST",
12008
+ headers: { "content-type": "application/json" },
12009
+ body: JSON.stringify(payload)
12010
+ });
12011
+ } catch (err) {
12012
+ const msg = err instanceof Error ? err.message : String(err);
12013
+ console.error(`[session-rc-spawn] manager-unreachable err=${msg}`);
12014
+ return c.json({ error: `session manager unreachable: ${msg}` }, 502);
12015
+ }
12016
+ const text = await res.text();
12017
+ let parsed = null;
12018
+ try {
12019
+ parsed = JSON.parse(text);
12020
+ } catch {
12021
+ }
12022
+ if (!res.ok) {
12023
+ console.error(`[session-rc-spawn] manager-error status=${res.status} body=${text.slice(0, 200)}`);
12024
+ return c.json(parsed ?? { error: text }, res.status);
12025
+ }
12026
+ return c.json(parsed ?? {});
12027
+ });
12028
+ var session_rc_spawn_default = app25;
12029
+
11878
12030
  // server/routes/admin/system-stats.ts
11879
12031
  import { readFile as readFile5 } from "fs/promises";
11880
12032
  import { cpus, loadavg, totalmem, freemem } from "os";
@@ -11970,8 +12122,8 @@ async function sample() {
11970
12122
  if (process.platform === "linux") return sampleLinux();
11971
12123
  return sampleOsFallback();
11972
12124
  }
11973
- var app24 = new Hono();
11974
- app24.get("/", async (c) => {
12125
+ var app26 = new Hono();
12126
+ app26.get("/", async (c) => {
11975
12127
  const started = Date.now();
11976
12128
  if (!inflight) {
11977
12129
  inflight = sample().finally(() => {
@@ -11994,27 +12146,27 @@ app24.get("/", async (c) => {
11994
12146
  return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
11995
12147
  }
11996
12148
  });
11997
- var system_stats_default = app24;
12149
+ var system_stats_default = app26;
11998
12150
 
11999
12151
  // server/routes/admin/health.ts
12000
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
12001
- import { resolve as resolve16, join as join14 } from "path";
12002
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
12152
+ import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
12153
+ import { resolve as resolve17, join as join15 } from "path";
12154
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
12003
12155
  var brandHostname = "maxy";
12004
- var brandJsonPath = join14(PLATFORM_ROOT6, "config", "brand.json");
12005
- if (existsSync17(brandJsonPath)) {
12156
+ var brandJsonPath = join15(PLATFORM_ROOT6, "config", "brand.json");
12157
+ if (existsSync18(brandJsonPath)) {
12006
12158
  try {
12007
- const brand = JSON.parse(readFileSync15(brandJsonPath, "utf-8"));
12159
+ const brand = JSON.parse(readFileSync16(brandJsonPath, "utf-8"));
12008
12160
  if (brand.hostname) brandHostname = brand.hostname;
12009
12161
  } catch {
12010
12162
  }
12011
12163
  }
12012
- var VERSION_FILE = resolve16(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
12164
+ var VERSION_FILE = resolve17(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
12013
12165
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
12014
12166
  var PROBE_TIMEOUT_MS = 1e3;
12015
12167
  function readVersion() {
12016
- if (!existsSync17(VERSION_FILE)) return "unknown";
12017
- return readFileSync15(VERSION_FILE, "utf-8").trim() || "unknown";
12168
+ if (!existsSync18(VERSION_FILE)) return "unknown";
12169
+ return readFileSync16(VERSION_FILE, "utf-8").trim() || "unknown";
12018
12170
  }
12019
12171
  async function probeConversationDb() {
12020
12172
  let session;
@@ -12039,8 +12191,8 @@ async function probeConversationDb() {
12039
12191
  });
12040
12192
  }
12041
12193
  }
12042
- var app25 = new Hono();
12043
- app25.get("/", async (c) => {
12194
+ var app27 = new Hono();
12195
+ app27.get("/", async (c) => {
12044
12196
  const version = readVersion();
12045
12197
  const probe = await probeConversationDb();
12046
12198
  const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
@@ -12062,7 +12214,7 @@ app25.get("/", async (c) => {
12062
12214
  uptimeMs
12063
12215
  });
12064
12216
  });
12065
- var health_default2 = app25;
12217
+ var health_default2 = app27;
12066
12218
 
12067
12219
  // server/routes/admin/linkedin-ingest.ts
12068
12220
  var TAG20 = "[linkedin-ingest-route]";
@@ -12158,8 +12310,8 @@ function buildInitialMessage(env) {
12158
12310
  }
12159
12311
  return header;
12160
12312
  }
12161
- var app26 = new Hono();
12162
- app26.post("/", requireAdminSession, async (c) => {
12313
+ var app28 = new Hono();
12314
+ app28.post("/", requireAdminSession, async (c) => {
12163
12315
  let body;
12164
12316
  try {
12165
12317
  body = await c.req.json();
@@ -12213,7 +12365,7 @@ app26.post("/", requireAdminSession, async (c) => {
12213
12365
  );
12214
12366
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: claudeSessionId }, 202);
12215
12367
  });
12216
- var linkedin_ingest_default = app26;
12368
+ var linkedin_ingest_default = app28;
12217
12369
 
12218
12370
  // server/routes/admin/post-turn-context.ts
12219
12371
  import neo4j2 from "neo4j-driver";
@@ -12255,8 +12407,8 @@ function pruneProperties(raw) {
12255
12407
  }
12256
12408
  return out;
12257
12409
  }
12258
- var app27 = new Hono();
12259
- app27.get("/", async (c) => {
12410
+ var app29 = new Hono();
12411
+ app29.get("/", async (c) => {
12260
12412
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12261
12413
  if (!isLoopbackAddr2(remoteAddr)) {
12262
12414
  console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12316,7 +12468,7 @@ app27.get("/", async (c) => {
12316
12468
  await session.close();
12317
12469
  }
12318
12470
  });
12319
- var post_turn_context_default = app27;
12471
+ var post_turn_context_default = app29;
12320
12472
 
12321
12473
  // server/routes/admin/public-session-context.ts
12322
12474
  import neo4j3 from "neo4j-driver";
@@ -12358,8 +12510,8 @@ function pruneProperties2(raw) {
12358
12510
  }
12359
12511
  return out;
12360
12512
  }
12361
- var app28 = new Hono();
12362
- app28.get("/", async (c) => {
12513
+ var app30 = new Hono();
12514
+ app30.get("/", async (c) => {
12363
12515
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12364
12516
  if (!isLoopbackAddr3(remoteAddr)) {
12365
12517
  console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12418,15 +12570,15 @@ app28.get("/", async (c) => {
12418
12570
  await session.close();
12419
12571
  }
12420
12572
  });
12421
- var public_session_context_default = app28;
12573
+ var public_session_context_default = app30;
12422
12574
 
12423
12575
  // server/routes/admin/public-session-exit.ts
12424
12576
  var TAG23 = "[public-session-exit-route]";
12425
12577
  function isLoopbackAddr4(addr) {
12426
12578
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
12427
12579
  }
12428
- var app29 = new Hono();
12429
- app29.post("/", async (c) => {
12580
+ var app31 = new Hono();
12581
+ app31.post("/", async (c) => {
12430
12582
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12431
12583
  if (!isLoopbackAddr4(remoteAddr)) {
12432
12584
  console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12453,15 +12605,15 @@ app29.post("/", async (c) => {
12453
12605
  handlePublicSessionExit(sessionId);
12454
12606
  return c.json({ ok: true });
12455
12607
  });
12456
- var public_session_exit_default = app29;
12608
+ var public_session_exit_default = app31;
12457
12609
 
12458
12610
  // server/routes/admin/access-session-evict.ts
12459
12611
  var TAG24 = "[access-session-evict]";
12460
12612
  function isLoopbackAddr5(addr) {
12461
12613
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
12462
12614
  }
12463
- var app30 = new Hono();
12464
- app30.post("/", async (c) => {
12615
+ var app32 = new Hono();
12616
+ app32.post("/", async (c) => {
12465
12617
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12466
12618
  if (!isLoopbackAddr5(remoteAddr)) {
12467
12619
  console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12489,49 +12641,51 @@ app30.post("/", async (c) => {
12489
12641
  console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
12490
12642
  return c.json({ ok: true, dropped });
12491
12643
  });
12492
- var access_session_evict_default = app30;
12644
+ var access_session_evict_default = app32;
12493
12645
 
12494
12646
  // server/routes/admin/index.ts
12495
- var app31 = new Hono();
12496
- app31.route("/session", session_default);
12497
- app31.route("/logs", logs_default);
12498
- app31.route("/claude-info", claude_info_default);
12499
- app31.route("/attachment", attachment_default);
12500
- app31.route("/agents", agents_default);
12501
- app31.route("/sessions", sessions_default);
12502
- app31.route("/claude-sessions", claude_sessions_default);
12503
- app31.route("/log-ingest", log_ingest_default);
12504
- app31.route("/events", events_default);
12505
- app31.route("/files", files_default);
12506
- app31.route("/graph-search", graph_search_default);
12507
- app31.route("/graph-subgraph", graph_subgraph_default);
12508
- app31.route("/graph-delete", graph_delete_default);
12509
- app31.route("/graph-restore", graph_restore_default);
12510
- app31.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12511
- app31.route("/graph-default-view", graph_default_view_default);
12512
- app31.route("/sidebar-artefacts", sidebar_artefacts_default);
12513
- app31.route("/sidebar-sessions", sidebar_sessions_default);
12514
- app31.route("/system-stats", system_stats_default);
12515
- app31.route("/health-brand", health_default2);
12516
- app31.route("/linkedin-ingest", linkedin_ingest_default);
12517
- app31.route("/post-turn-context", post_turn_context_default);
12518
- app31.route("/public-session-context", public_session_context_default);
12519
- app31.route("/public-session-exit", public_session_exit_default);
12520
- app31.route("/access-session-evict", access_session_evict_default);
12521
- var admin_default = app31;
12647
+ var app33 = new Hono();
12648
+ app33.route("/session", session_default);
12649
+ app33.route("/logs", logs_default);
12650
+ app33.route("/claude-info", claude_info_default);
12651
+ app33.route("/attachment", attachment_default);
12652
+ app33.route("/agents", agents_default);
12653
+ app33.route("/sessions", sessions_default);
12654
+ app33.route("/claude-sessions", claude_sessions_default);
12655
+ app33.route("/log-ingest", log_ingest_default);
12656
+ app33.route("/events", events_default);
12657
+ app33.route("/files", files_default);
12658
+ app33.route("/graph-search", graph_search_default);
12659
+ app33.route("/graph-subgraph", graph_subgraph_default);
12660
+ app33.route("/graph-delete", graph_delete_default);
12661
+ app33.route("/graph-restore", graph_restore_default);
12662
+ app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12663
+ app33.route("/graph-default-view", graph_default_view_default);
12664
+ app33.route("/sidebar-artefacts", sidebar_artefacts_default);
12665
+ app33.route("/sidebar-sessions", sidebar_sessions_default);
12666
+ app33.route("/session-delete", session_delete_default);
12667
+ app33.route("/session-rc-spawn", session_rc_spawn_default);
12668
+ app33.route("/system-stats", system_stats_default);
12669
+ app33.route("/health-brand", health_default2);
12670
+ app33.route("/linkedin-ingest", linkedin_ingest_default);
12671
+ app33.route("/post-turn-context", post_turn_context_default);
12672
+ app33.route("/public-session-context", public_session_context_default);
12673
+ app33.route("/public-session-exit", public_session_exit_default);
12674
+ app33.route("/access-session-evict", access_session_evict_default);
12675
+ var admin_default = app33;
12522
12676
 
12523
12677
  // app/lib/access-gate.ts
12524
12678
  import neo4j4 from "neo4j-driver";
12525
- import { readFileSync as readFileSync16 } from "fs";
12526
- import { resolve as resolve17 } from "path";
12679
+ import { readFileSync as readFileSync17 } from "fs";
12680
+ import { resolve as resolve18 } from "path";
12527
12681
  import { randomUUID as randomUUID8 } from "crypto";
12528
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
12682
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
12529
12683
  var driver = null;
12530
12684
  function readPassword() {
12531
12685
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
12532
- const passwordFile = resolve17(PLATFORM_ROOT7, "config/.neo4j-password");
12686
+ const passwordFile = resolve18(PLATFORM_ROOT7, "config/.neo4j-password");
12533
12687
  try {
12534
- return readFileSync16(passwordFile, "utf-8").trim();
12688
+ return readFileSync17(passwordFile, "utf-8").trim();
12535
12689
  } catch {
12536
12690
  throw new Error(
12537
12691
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -12732,8 +12886,8 @@ async function generateNewMagicToken(grantId) {
12732
12886
  var TAG25 = "[access-verify]";
12733
12887
  var MINT_TAG = "[access-session-mint]";
12734
12888
  var COOKIE_NAME = "__access_session";
12735
- var app32 = new Hono();
12736
- app32.post("/", async (c) => {
12889
+ var app34 = new Hono();
12890
+ app34.post("/", async (c) => {
12737
12891
  const ip = c.var.clientIp || "unknown";
12738
12892
  let body;
12739
12893
  try {
@@ -12815,13 +12969,13 @@ app32.post("/", async (c) => {
12815
12969
  displayName: grant.displayName
12816
12970
  });
12817
12971
  });
12818
- var verify_token_default = app32;
12972
+ var verify_token_default = app34;
12819
12973
 
12820
12974
  // app/lib/access-email.ts
12821
12975
  import { spawn as spawn2 } from "child_process";
12822
- import { resolve as resolve18 } from "path";
12823
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
12824
- var SEND_SCRIPT = resolve18(
12976
+ import { resolve as resolve19 } from "path";
12977
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
12978
+ var SEND_SCRIPT = resolve19(
12825
12979
  PLATFORM_ROOT8,
12826
12980
  "plugins",
12827
12981
  "email",
@@ -12878,9 +13032,9 @@ async function sendMagicLinkEmail(payload) {
12878
13032
 
12879
13033
  // server/routes/access/request-magic-link.ts
12880
13034
  var TAG26 = "[access-request-link]";
12881
- var app33 = new Hono();
13035
+ var app35 = new Hono();
12882
13036
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
12883
- app33.post("/", async (c) => {
13037
+ app35.post("/", async (c) => {
12884
13038
  let body;
12885
13039
  try {
12886
13040
  body = await c.req.json();
@@ -12954,17 +13108,17 @@ app33.post("/", async (c) => {
12954
13108
  );
12955
13109
  return c.json({ message: VISITOR_MESSAGE }, 200);
12956
13110
  });
12957
- var request_magic_link_default = app33;
13111
+ var request_magic_link_default = app35;
12958
13112
 
12959
13113
  // server/routes/access/index.ts
12960
- var app34 = new Hono();
12961
- app34.route("/verify-token", verify_token_default);
12962
- app34.route("/request-magic-link", request_magic_link_default);
12963
- var access_default = app34;
13114
+ var app36 = new Hono();
13115
+ app36.route("/verify-token", verify_token_default);
13116
+ app36.route("/request-magic-link", request_magic_link_default);
13117
+ var access_default = app36;
12964
13118
 
12965
13119
  // server/routes/sites.ts
12966
- import { existsSync as existsSync18, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
12967
- import { resolve as resolve19 } from "path";
13120
+ import { existsSync as existsSync19, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
13121
+ import { resolve as resolve20 } from "path";
12968
13122
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12969
13123
  var MIME = {
12970
13124
  ".html": "text/html; charset=utf-8",
@@ -12995,8 +13149,8 @@ function getExt(p) {
12995
13149
  if (idx < p.lastIndexOf("/")) return "";
12996
13150
  return p.slice(idx).toLowerCase();
12997
13151
  }
12998
- var app35 = new Hono();
12999
- app35.get("/:rel{.*}", (c) => {
13152
+ var app37 = new Hono();
13153
+ app37.get("/:rel{.*}", (c) => {
13000
13154
  const reqPath = c.req.path;
13001
13155
  const rawRel = c.req.param("rel") ?? "";
13002
13156
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -13021,15 +13175,15 @@ app35.get("/:rel{.*}", (c) => {
13021
13175
  }
13022
13176
  segments.push(seg);
13023
13177
  }
13024
- const rootDir = resolve19(account.accountDir, "sites");
13025
- let filePath = segments.length === 0 ? rootDir : resolve19(rootDir, ...segments);
13178
+ const rootDir = resolve20(account.accountDir, "sites");
13179
+ let filePath = segments.length === 0 ? rootDir : resolve20(rootDir, ...segments);
13026
13180
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
13027
13181
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
13028
13182
  return c.text("Forbidden", 403);
13029
13183
  }
13030
13184
  let stat7;
13031
13185
  try {
13032
- stat7 = existsSync18(filePath) ? statSync8(filePath) : null;
13186
+ stat7 = existsSync19(filePath) ? statSync8(filePath) : null;
13033
13187
  } catch {
13034
13188
  stat7 = null;
13035
13189
  }
@@ -13042,13 +13196,13 @@ app35.get("/:rel{.*}", (c) => {
13042
13196
  return c.redirect(target, 301);
13043
13197
  }
13044
13198
  if (stat7?.isDirectory()) {
13045
- filePath = resolve19(filePath, "index.html");
13199
+ filePath = resolve20(filePath, "index.html");
13046
13200
  }
13047
13201
  if (!filePath.startsWith(rootDir + "/")) {
13048
13202
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
13049
13203
  return c.text("Forbidden", 403);
13050
13204
  }
13051
- if (!existsSync18(filePath)) {
13205
+ if (!existsSync19(filePath)) {
13052
13206
  console.error(`[sites] not-found path=${reqPath} status=404`);
13053
13207
  return c.text("Not found", 404);
13054
13208
  }
@@ -13067,7 +13221,7 @@ app35.get("/:rel{.*}", (c) => {
13067
13221
  }
13068
13222
  let body;
13069
13223
  try {
13070
- body = readFileSync17(realPath);
13224
+ body = readFileSync18(realPath);
13071
13225
  } catch (err) {
13072
13226
  const code = err?.code;
13073
13227
  if (code === "EISDIR") {
@@ -13099,11 +13253,11 @@ app35.get("/:rel{.*}", (c) => {
13099
13253
  "X-Content-Type-Options": "nosniff"
13100
13254
  });
13101
13255
  });
13102
- var sites_default = app35;
13256
+ var sites_default = app37;
13103
13257
 
13104
13258
  // app/lib/visitor-token.ts
13105
13259
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
13106
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "fs";
13260
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync19, writeFileSync as writeFileSync6 } from "fs";
13107
13261
  import { dirname as dirname4 } from "path";
13108
13262
  var TOKEN_PREFIX = "v1.";
13109
13263
  var SECRET_BYTES = 32;
@@ -13112,7 +13266,7 @@ var cachedSecret = null;
13112
13266
  function getSecret() {
13113
13267
  if (cachedSecret) return cachedSecret;
13114
13268
  try {
13115
- const hex2 = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13269
+ const hex2 = readFileSync19(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13116
13270
  if (hex2.length === SECRET_BYTES * 2) {
13117
13271
  cachedSecret = Buffer.from(hex2, "hex");
13118
13272
  return cachedSecret;
@@ -13126,7 +13280,7 @@ function getSecret() {
13126
13280
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
13127
13281
  } catch {
13128
13282
  }
13129
- const hex = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13283
+ const hex = readFileSync19(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13130
13284
  cachedSecret = Buffer.from(hex, "hex");
13131
13285
  return cachedSecret;
13132
13286
  }
@@ -13179,8 +13333,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
13179
13333
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
13180
13334
 
13181
13335
  // app/lib/brand-config.ts
13182
- import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
13183
- import { join as join15 } from "path";
13336
+ import { existsSync as existsSync20, readFileSync as readFileSync20 } from "fs";
13337
+ import { join as join16 } from "path";
13184
13338
  var cached2 = null;
13185
13339
  var cachedAttempted = false;
13186
13340
  function readBrandConfig() {
@@ -13188,10 +13342,10 @@ function readBrandConfig() {
13188
13342
  cachedAttempted = true;
13189
13343
  const platformRoot = process.env.MAXY_PLATFORM_ROOT;
13190
13344
  if (!platformRoot) return null;
13191
- const brandPath = join15(platformRoot, "config", "brand.json");
13192
- if (!existsSync19(brandPath)) return null;
13345
+ const brandPath = join16(platformRoot, "config", "brand.json");
13346
+ if (!existsSync20(brandPath)) return null;
13193
13347
  try {
13194
- cached2 = JSON.parse(readFileSync19(brandPath, "utf-8"));
13348
+ cached2 = JSON.parse(readFileSync20(brandPath, "utf-8"));
13195
13349
  return cached2;
13196
13350
  } catch {
13197
13351
  return null;
@@ -13199,7 +13353,7 @@ function readBrandConfig() {
13199
13353
  }
13200
13354
 
13201
13355
  // server/routes/visitor-consent.ts
13202
- var app36 = new Hono();
13356
+ var app38 = new Hono();
13203
13357
  var CONSENT_COOKIE_NAME = "mxy_consent";
13204
13358
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
13205
13359
  var DEFAULT_CONSENT_COPY = {
@@ -13244,17 +13398,17 @@ function siteSlugFromReferer(referer) {
13244
13398
  return "";
13245
13399
  }
13246
13400
  }
13247
- app36.options("/consent", (c) => {
13401
+ app38.options("/consent", (c) => {
13248
13402
  const origin = getOrigin(c);
13249
13403
  setCorsHeaders(c, origin);
13250
13404
  return c.body(null, 204);
13251
13405
  });
13252
- app36.options("/brand-config", (c) => {
13406
+ app38.options("/brand-config", (c) => {
13253
13407
  const origin = getOrigin(c);
13254
13408
  setCorsHeaders(c, origin);
13255
13409
  return c.body(null, 204);
13256
13410
  });
13257
- app36.post("/consent", async (c) => {
13411
+ app38.post("/consent", async (c) => {
13258
13412
  const origin = getOrigin(c);
13259
13413
  setCorsHeaders(c, origin);
13260
13414
  let raw;
@@ -13294,7 +13448,7 @@ app36.post("/consent", async (c) => {
13294
13448
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
13295
13449
  return c.body(null, 204);
13296
13450
  });
13297
- app36.get("/brand-config", (c) => {
13451
+ app38.get("/brand-config", (c) => {
13298
13452
  const origin = getOrigin(c);
13299
13453
  setCorsHeaders(c, origin);
13300
13454
  const brand = readBrandConfig();
@@ -13304,7 +13458,7 @@ app36.get("/brand-config", (c) => {
13304
13458
  c.header("Cache-Control", "public, max-age=300");
13305
13459
  return c.json({ consent: { copy, palette } });
13306
13460
  });
13307
- var visitor_consent_default = app36;
13461
+ var visitor_consent_default = app38;
13308
13462
 
13309
13463
  // server/routes/listings.ts
13310
13464
  function getCookie(headerValue, name) {
@@ -13331,8 +13485,8 @@ function appendConsentParams(pageUrl, token) {
13331
13485
  }
13332
13486
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
13333
13487
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
13334
- var app37 = new Hono();
13335
- app37.get("/:slug/click", async (c) => {
13488
+ var app39 = new Hono();
13489
+ app39.get("/:slug/click", async (c) => {
13336
13490
  const slug = c.req.param("slug") ?? "";
13337
13491
  const rawSession = c.req.query("session") ?? "";
13338
13492
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -13396,10 +13550,10 @@ app37.get("/:slug/click", async (c) => {
13396
13550
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
13397
13551
  return c.redirect(redirectUrl, 302);
13398
13552
  });
13399
- var listings_default = app37;
13553
+ var listings_default = app39;
13400
13554
 
13401
13555
  // server/routes/visitor-event.ts
13402
- var app38 = new Hono();
13556
+ var app40 = new Hono();
13403
13557
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
13404
13558
  var buckets = /* @__PURE__ */ new Map();
13405
13559
  var RATE_LIMIT = 60;
@@ -13466,12 +13620,12 @@ function originAllowed(origin, allowlist) {
13466
13620
  return false;
13467
13621
  }
13468
13622
  }
13469
- app38.options("/event", (c) => {
13623
+ app40.options("/event", (c) => {
13470
13624
  const origin = getOrigin2(c);
13471
13625
  setCorsHeaders2(c, origin);
13472
13626
  return c.body(null, 204);
13473
13627
  });
13474
- app38.post("/event", async (c) => {
13628
+ app40.post("/event", async (c) => {
13475
13629
  const origin = getOrigin2(c);
13476
13630
  setCorsHeaders2(c, origin);
13477
13631
  const ua = c.req.header("user-agent") ?? "";
@@ -13676,7 +13830,7 @@ async function writeEvent(opts) {
13676
13830
  );
13677
13831
  }
13678
13832
  }
13679
- var visitor_event_default = app38;
13833
+ var visitor_event_default = app40;
13680
13834
 
13681
13835
  // app/lib/graph-health.ts
13682
13836
  var HOUR_MS = 60 * 60 * 1e3;
@@ -13761,7 +13915,7 @@ function startGraphHealthTimer() {
13761
13915
 
13762
13916
  // app/lib/file-watcher.ts
13763
13917
  import * as fsp2 from "fs/promises";
13764
- import { resolve as resolve20, sep as sep6 } from "path";
13918
+ import { resolve as resolve21, sep as sep6 } from "path";
13765
13919
  var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13766
13920
  var DEFAULT_COALESCE_MS = 500;
13767
13921
  var ROOTS = ["uploads", "accounts"];
@@ -13780,7 +13934,7 @@ async function startFileWatcher(opts = {}) {
13780
13934
  const dropFn = opts.drop ?? dropFileIndex;
13781
13935
  for (const r of ROOTS) {
13782
13936
  try {
13783
- await fsp2.mkdir(resolve20(dataRoot, r), { recursive: true });
13937
+ await fsp2.mkdir(resolve21(dataRoot, r), { recursive: true });
13784
13938
  } catch (err) {
13785
13939
  console.error(
13786
13940
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -13801,7 +13955,7 @@ async function startFileWatcher(opts = {}) {
13801
13955
  timers.set(relativePath, t);
13802
13956
  }
13803
13957
  async function runHook(relativePath, accountId) {
13804
- const absolute = resolve20(dataRoot, relativePath);
13958
+ const absolute = resolve21(dataRoot, relativePath);
13805
13959
  let exists = false;
13806
13960
  try {
13807
13961
  const st = await fsp2.stat(absolute);
@@ -13825,7 +13979,7 @@ async function startFileWatcher(opts = {}) {
13825
13979
  }
13826
13980
  }
13827
13981
  async function watchRoot(rootName) {
13828
- const absRoot = resolve20(dataRoot, rootName);
13982
+ const absRoot = resolve21(dataRoot, rootName);
13829
13983
  try {
13830
13984
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
13831
13985
  for await (const event of iter) {
@@ -13923,8 +14077,8 @@ function broadcastAdminShutdown(reason) {
13923
14077
 
13924
14078
  // ../lib/entitlement/src/index.ts
13925
14079
  import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
13926
- import { existsSync as existsSync20, readFileSync as readFileSync20, statSync as statSync9 } from "fs";
13927
- import { resolve as resolve21 } from "path";
14080
+ import { existsSync as existsSync21, readFileSync as readFileSync21, statSync as statSync9 } from "fs";
14081
+ import { resolve as resolve22 } from "path";
13928
14082
 
13929
14083
  // ../lib/entitlement/src/canonicalize.ts
13930
14084
  function canonicalize(value) {
@@ -13959,7 +14113,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
13959
14113
  var GRACE_DAYS = 7;
13960
14114
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
13961
14115
  function pubkeyPath(brand) {
13962
- return resolve21(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
14116
+ return resolve22(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
13963
14117
  }
13964
14118
  var memo = null;
13965
14119
  function memoKey(mtimeMs, account) {
@@ -13971,8 +14125,8 @@ function resolveEntitlement(brand, account) {
13971
14125
  if (brand.commercialMode !== true) {
13972
14126
  return logResolved(implicitTrust(account), null);
13973
14127
  }
13974
- const entitlementPath = resolve21(brand.configDir, "entitlement.json");
13975
- if (!existsSync20(entitlementPath)) {
14128
+ const entitlementPath = resolve22(brand.configDir, "entitlement.json");
14129
+ if (!existsSync21(entitlementPath)) {
13976
14130
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
13977
14131
  }
13978
14132
  const stat7 = statSync9(entitlementPath);
@@ -13987,7 +14141,7 @@ function resolveEntitlement(brand, account) {
13987
14141
  function verifyAndResolve(brand, entitlementPath, account) {
13988
14142
  let pubkeyPem;
13989
14143
  try {
13990
- pubkeyPem = readFileSync20(pubkeyPath(brand), "utf-8");
14144
+ pubkeyPem = readFileSync21(pubkeyPath(brand), "utf-8");
13991
14145
  } catch (err) {
13992
14146
  return logResolved(anonymousFallback("pubkey-missing"), {
13993
14147
  reason: "pubkey-missing"
@@ -14001,7 +14155,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
14001
14155
  }
14002
14156
  let envelope;
14003
14157
  try {
14004
- envelope = JSON.parse(readFileSync20(entitlementPath, "utf-8"));
14158
+ envelope = JSON.parse(readFileSync21(entitlementPath, "utf-8"));
14005
14159
  } catch {
14006
14160
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
14007
14161
  }
@@ -14162,14 +14316,14 @@ function clientFrom(c) {
14162
14316
  );
14163
14317
  }
14164
14318
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
14165
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join16(PLATFORM_ROOT9, "config", "brand.json") : "";
14319
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join17(PLATFORM_ROOT9, "config", "brand.json") : "";
14166
14320
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
14167
- if (BRAND_JSON_PATH && !existsSync21(BRAND_JSON_PATH)) {
14321
+ if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
14168
14322
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
14169
14323
  }
14170
- if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
14324
+ if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
14171
14325
  try {
14172
- const parsed = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
14326
+ const parsed = JSON.parse(readFileSync22(BRAND_JSON_PATH, "utf-8"));
14173
14327
  BRAND = { ...BRAND, ...parsed };
14174
14328
  } catch (err) {
14175
14329
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -14188,11 +14342,11 @@ var brandLoginOpts = {
14188
14342
  bodyFont: BRAND.defaultFonts?.body,
14189
14343
  logoContainsName: !!BRAND.logoContainsName
14190
14344
  };
14191
- var ALIAS_DOMAINS_PATH = join16(homedir2(), BRAND.configDir, "alias-domains.json");
14345
+ var ALIAS_DOMAINS_PATH = join17(homedir2(), BRAND.configDir, "alias-domains.json");
14192
14346
  function loadAliasDomains() {
14193
14347
  try {
14194
- if (!existsSync21(ALIAS_DOMAINS_PATH)) return null;
14195
- const parsed = JSON.parse(readFileSync21(ALIAS_DOMAINS_PATH, "utf-8"));
14348
+ if (!existsSync22(ALIAS_DOMAINS_PATH)) return null;
14349
+ const parsed = JSON.parse(readFileSync22(ALIAS_DOMAINS_PATH, "utf-8"));
14196
14350
  if (!Array.isArray(parsed)) {
14197
14351
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
14198
14352
  return null;
@@ -14216,9 +14370,9 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
14216
14370
  function isPublicHost(host) {
14217
14371
  return host.startsWith("public.") || aliasDomains.has(host);
14218
14372
  }
14219
- var app39 = new Hono();
14220
- app39.use("*", clientIpMiddleware);
14221
- app39.use("*", async (c, next) => {
14373
+ var app41 = new Hono();
14374
+ app41.use("*", clientIpMiddleware);
14375
+ app41.use("*", async (c, next) => {
14222
14376
  await next();
14223
14377
  c.header("X-Content-Type-Options", "nosniff");
14224
14378
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -14228,7 +14382,7 @@ app39.use("*", async (c, next) => {
14228
14382
  );
14229
14383
  });
14230
14384
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
14231
- app39.use("*", async (c, next) => {
14385
+ app41.use("*", async (c, next) => {
14232
14386
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
14233
14387
  await next();
14234
14388
  return;
@@ -14261,7 +14415,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
14261
14415
  "/sites/"
14262
14416
  ];
14263
14417
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
14264
- app39.use("*", async (c, next) => {
14418
+ app41.use("*", async (c, next) => {
14265
14419
  const host = (c.req.header("host") ?? "").split(":")[0];
14266
14420
  if (!isPublicHost(host)) {
14267
14421
  await next();
@@ -14301,7 +14455,7 @@ function resolveRemoteAuthOpts() {
14301
14455
  return brandLoginOpts;
14302
14456
  }
14303
14457
  var MAX_LOGIN_BODY = 8 * 1024;
14304
- app39.post("/__remote-auth/login", async (c) => {
14458
+ app41.post("/__remote-auth/login", async (c) => {
14305
14459
  const client = clientFrom(c);
14306
14460
  const clientIp = client.ip || "unknown";
14307
14461
  if (!requestIsTlsTerminated(c)) {
@@ -14346,7 +14500,7 @@ app39.post("/__remote-auth/login", async (c) => {
14346
14500
  }
14347
14501
  });
14348
14502
  });
14349
- app39.get("/__remote-auth/logout", (c) => {
14503
+ app41.get("/__remote-auth/logout", (c) => {
14350
14504
  const client = clientFrom(c);
14351
14505
  const clientIp = client.ip || "unknown";
14352
14506
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -14359,7 +14513,7 @@ app39.get("/__remote-auth/logout", (c) => {
14359
14513
  }
14360
14514
  });
14361
14515
  });
14362
- app39.post("/__remote-auth/change-password", async (c) => {
14516
+ app41.post("/__remote-auth/change-password", async (c) => {
14363
14517
  const client = clientFrom(c);
14364
14518
  const clientIp = client.ip || "unknown";
14365
14519
  const rateLimited = checkRateLimit(client);
@@ -14410,13 +14564,13 @@ app39.post("/__remote-auth/change-password", async (c) => {
14410
14564
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
14411
14565
  }
14412
14566
  });
14413
- app39.get("/__remote-auth/setup", (c) => {
14567
+ app41.get("/__remote-auth/setup", (c) => {
14414
14568
  if (isRemoteAuthConfigured()) {
14415
14569
  return c.redirect("/");
14416
14570
  }
14417
14571
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
14418
14572
  });
14419
- app39.post("/__remote-auth/set-initial-password", async (c) => {
14573
+ app41.post("/__remote-auth/set-initial-password", async (c) => {
14420
14574
  if (isRemoteAuthConfigured()) {
14421
14575
  return c.redirect("/");
14422
14576
  }
@@ -14454,10 +14608,10 @@ app39.post("/__remote-auth/set-initial-password", async (c) => {
14454
14608
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
14455
14609
  }
14456
14610
  });
14457
- app39.get("/api/remote-auth/status", (c) => {
14611
+ app41.get("/api/remote-auth/status", (c) => {
14458
14612
  return c.json({ configured: isRemoteAuthConfigured() });
14459
14613
  });
14460
- app39.post("/api/remote-auth/set-password", async (c) => {
14614
+ app41.post("/api/remote-auth/set-password", async (c) => {
14461
14615
  let body;
14462
14616
  try {
14463
14617
  body = await c.req.json();
@@ -14488,9 +14642,9 @@ app39.post("/api/remote-auth/set-password", async (c) => {
14488
14642
  return c.json({ error: "Failed to save password" }, 500);
14489
14643
  }
14490
14644
  });
14491
- app39.route("/api/_client-error", client_error_default);
14645
+ app41.route("/api/_client-error", client_error_default);
14492
14646
  console.log("[client-error-route] mounted");
14493
- app39.use("*", async (c, next) => {
14647
+ app41.use("*", async (c, next) => {
14494
14648
  const host = (c.req.header("host") ?? "").split(":")[0];
14495
14649
  const path2 = c.req.path;
14496
14650
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -14523,12 +14677,12 @@ app39.use("*", async (c, next) => {
14523
14677
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
14524
14678
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
14525
14679
  });
14526
- app39.route("/api/health", health_default);
14527
- app39.route("/api/chat", chat_default);
14528
- app39.route("/api/whatsapp", whatsapp_default);
14529
- app39.route("/api/onboarding", onboarding_default);
14530
- app39.route("/api/admin", admin_default);
14531
- app39.route("/api/access", access_default);
14680
+ app41.route("/api/health", health_default);
14681
+ app41.route("/api/chat", chat_default);
14682
+ app41.route("/api/whatsapp", whatsapp_default);
14683
+ app41.route("/api/onboarding", onboarding_default);
14684
+ app41.route("/api/admin", admin_default);
14685
+ app41.route("/api/access", access_default);
14532
14686
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
14533
14687
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
14534
14688
  var IMAGE_MIME = {
@@ -14540,7 +14694,7 @@ var IMAGE_MIME = {
14540
14694
  ".svg": "image/svg+xml",
14541
14695
  ".ico": "image/x-icon"
14542
14696
  };
14543
- app39.get("/agent-assets/:slug/:filename", (c) => {
14697
+ app41.get("/agent-assets/:slug/:filename", (c) => {
14544
14698
  const slug = c.req.param("slug");
14545
14699
  const filename = c.req.param("filename");
14546
14700
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -14556,26 +14710,26 @@ app39.get("/agent-assets/:slug/:filename", (c) => {
14556
14710
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
14557
14711
  return c.text("Not found", 404);
14558
14712
  }
14559
- const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
14560
- const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
14713
+ const filePath = resolve23(account.accountDir, "agents", slug, "assets", filename);
14714
+ const expectedDir = resolve23(account.accountDir, "agents", slug, "assets");
14561
14715
  if (!filePath.startsWith(expectedDir + "/")) {
14562
14716
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
14563
14717
  return c.text("Forbidden", 403);
14564
14718
  }
14565
- if (!existsSync21(filePath)) {
14719
+ if (!existsSync22(filePath)) {
14566
14720
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
14567
14721
  return c.text("Not found", 404);
14568
14722
  }
14569
14723
  const ext = "." + filename.split(".").pop()?.toLowerCase();
14570
14724
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
14571
14725
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
14572
- const body = readFileSync21(filePath);
14726
+ const body = readFileSync22(filePath);
14573
14727
  return c.body(body, 200, {
14574
14728
  "Content-Type": contentType,
14575
14729
  "Cache-Control": "public, max-age=3600"
14576
14730
  });
14577
14731
  });
14578
- app39.get("/generated/:filename", (c) => {
14732
+ app41.get("/generated/:filename", (c) => {
14579
14733
  const filename = c.req.param("filename");
14580
14734
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
14581
14735
  console.error(`[generated] serve file=${filename} status=403`);
@@ -14586,35 +14740,35 @@ app39.get("/generated/:filename", (c) => {
14586
14740
  console.error(`[generated] serve file=${filename} status=404`);
14587
14741
  return c.text("Not found", 404);
14588
14742
  }
14589
- const filePath = resolve22(account.accountDir, "generated", filename);
14590
- const expectedDir = resolve22(account.accountDir, "generated");
14743
+ const filePath = resolve23(account.accountDir, "generated", filename);
14744
+ const expectedDir = resolve23(account.accountDir, "generated");
14591
14745
  if (!filePath.startsWith(expectedDir + "/")) {
14592
14746
  console.error(`[generated] serve file=${filename} status=403`);
14593
14747
  return c.text("Forbidden", 403);
14594
14748
  }
14595
- if (!existsSync21(filePath)) {
14749
+ if (!existsSync22(filePath)) {
14596
14750
  console.error(`[generated] serve file=${filename} status=404`);
14597
14751
  return c.text("Not found", 404);
14598
14752
  }
14599
14753
  const ext = "." + filename.split(".").pop()?.toLowerCase();
14600
14754
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
14601
14755
  console.log(`[generated] serve file=${filename} status=200`);
14602
- const body = readFileSync21(filePath);
14756
+ const body = readFileSync22(filePath);
14603
14757
  return c.body(body, 200, {
14604
14758
  "Content-Type": contentType,
14605
14759
  "Cache-Control": "public, max-age=86400"
14606
14760
  });
14607
14761
  });
14608
- app39.route("/sites", sites_default);
14609
- app39.route("/listings", listings_default);
14610
- app39.route("/v", visitor_event_default);
14611
- app39.route("/v", visitor_consent_default);
14762
+ app41.route("/sites", sites_default);
14763
+ app41.route("/listings", listings_default);
14764
+ app41.route("/v", visitor_event_default);
14765
+ app41.route("/v", visitor_consent_default);
14612
14766
  var htmlCache = /* @__PURE__ */ new Map();
14613
14767
  var brandLogoPath = "/brand/maxy-monochrome.png";
14614
14768
  var brandIconPath = "/brand/maxy-monochrome.png";
14615
- if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
14769
+ if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
14616
14770
  try {
14617
- const fullBrand = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
14771
+ const fullBrand = JSON.parse(readFileSync22(BRAND_JSON_PATH, "utf-8"));
14618
14772
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
14619
14773
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
14620
14774
  } catch {
@@ -14631,9 +14785,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
14631
14785
  function readInstalledVersion() {
14632
14786
  try {
14633
14787
  if (!PLATFORM_ROOT9) return "unknown";
14634
- const versionFile = join16(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
14635
- if (!existsSync21(versionFile)) return "unknown";
14636
- const content = readFileSync21(versionFile, "utf-8").trim();
14788
+ const versionFile = join17(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
14789
+ if (!existsSync22(versionFile)) return "unknown";
14790
+ const content = readFileSync22(versionFile, "utf-8").trim();
14637
14791
  return content || "unknown";
14638
14792
  } catch {
14639
14793
  return "unknown";
@@ -14674,7 +14828,7 @@ var clientErrorReporterScript = `<script>
14674
14828
  function cachedHtml(file) {
14675
14829
  let html = htmlCache.get(file);
14676
14830
  if (!html) {
14677
- html = readFileSync21(resolve22(process.cwd(), "public", file), "utf-8");
14831
+ html = readFileSync22(resolve23(process.cwd(), "public", file), "utf-8");
14678
14832
  const productNameEsc = escapeHtml(BRAND.productName);
14679
14833
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
14680
14834
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -14690,26 +14844,26 @@ ${clientErrorReporterScript}
14690
14844
  }
14691
14845
  var brandedHtmlCache = /* @__PURE__ */ new Map();
14692
14846
  function loadBrandingCache(agentSlug) {
14693
- const configDir2 = join16(homedir2(), BRAND.configDir);
14847
+ const configDir2 = join17(homedir2(), BRAND.configDir);
14694
14848
  try {
14695
- const accountJsonPath = join16(configDir2, "account.json");
14696
- if (!existsSync21(accountJsonPath)) return null;
14697
- const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
14849
+ const accountJsonPath = join17(configDir2, "account.json");
14850
+ if (!existsSync22(accountJsonPath)) return null;
14851
+ const account = JSON.parse(readFileSync22(accountJsonPath, "utf-8"));
14698
14852
  const accountId = account.accountId;
14699
14853
  if (!accountId) return null;
14700
- const cachePath = join16(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
14701
- if (!existsSync21(cachePath)) return null;
14702
- return JSON.parse(readFileSync21(cachePath, "utf-8"));
14854
+ const cachePath = join17(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
14855
+ if (!existsSync22(cachePath)) return null;
14856
+ return JSON.parse(readFileSync22(cachePath, "utf-8"));
14703
14857
  } catch {
14704
14858
  return null;
14705
14859
  }
14706
14860
  }
14707
14861
  function resolveDefaultSlug() {
14708
14862
  try {
14709
- const configDir2 = join16(homedir2(), BRAND.configDir);
14710
- const accountJsonPath = join16(configDir2, "account.json");
14711
- if (!existsSync21(accountJsonPath)) return null;
14712
- const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
14863
+ const configDir2 = join17(homedir2(), BRAND.configDir);
14864
+ const accountJsonPath = join17(configDir2, "account.json");
14865
+ if (!existsSync22(accountJsonPath)) return null;
14866
+ const account = JSON.parse(readFileSync22(accountJsonPath, "utf-8"));
14713
14867
  return account.defaultAgent || null;
14714
14868
  } catch {
14715
14869
  return null;
@@ -14745,7 +14899,7 @@ function brandedPublicHtml(agentSlug) {
14745
14899
  function escapeHtml(s) {
14746
14900
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
14747
14901
  }
14748
- app39.get("/", (c) => {
14902
+ app41.get("/", (c) => {
14749
14903
  const host = (c.req.header("host") ?? "").split(":")[0];
14750
14904
  if (isPublicHost(host)) {
14751
14905
  const defaultSlug = resolveDefaultSlug();
@@ -14753,12 +14907,12 @@ app39.get("/", (c) => {
14753
14907
  }
14754
14908
  return c.html(cachedHtml("index.html"));
14755
14909
  });
14756
- app39.get("/public", (c) => {
14910
+ app41.get("/public", (c) => {
14757
14911
  const host = (c.req.header("host") ?? "").split(":")[0];
14758
14912
  if (isPublicHost(host)) return c.text("Not found", 404);
14759
14913
  return c.html(cachedHtml("public.html"));
14760
14914
  });
14761
- app39.get("/chat", (c) => {
14915
+ app41.get("/chat", (c) => {
14762
14916
  const host = (c.req.header("host") ?? "").split(":")[0];
14763
14917
  if (isPublicHost(host)) return c.text("Not found", 404);
14764
14918
  return c.html(cachedHtml("public.html"));
@@ -14777,12 +14931,12 @@ async function logViewerFetch(c, next) {
14777
14931
  duration_ms: Date.now() - start
14778
14932
  });
14779
14933
  }
14780
- app39.use("/vnc-viewer.html", logViewerFetch);
14781
- app39.use("/vnc-popout.html", logViewerFetch);
14782
- app39.get("/vnc-popout.html", (c) => {
14934
+ app41.use("/vnc-viewer.html", logViewerFetch);
14935
+ app41.use("/vnc-popout.html", logViewerFetch);
14936
+ app41.get("/vnc-popout.html", (c) => {
14783
14937
  let html = htmlCache.get("vnc-popout.html");
14784
14938
  if (!html) {
14785
- html = readFileSync21(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14939
+ html = readFileSync22(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14786
14940
  const name = escapeHtml(BRAND.productName);
14787
14941
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
14788
14942
  html = html.replace("</head>", ` ${brandScript}
@@ -14792,7 +14946,7 @@ app39.get("/vnc-popout.html", (c) => {
14792
14946
  }
14793
14947
  return c.html(html);
14794
14948
  });
14795
- app39.post("/api/vnc/client-event", async (c) => {
14949
+ app41.post("/api/vnc/client-event", async (c) => {
14796
14950
  let body;
14797
14951
  try {
14798
14952
  body = await c.req.json();
@@ -14813,25 +14967,25 @@ app39.post("/api/vnc/client-event", async (c) => {
14813
14967
  });
14814
14968
  return c.json({ ok: true });
14815
14969
  });
14816
- app39.get("/g/:slug", (c) => {
14970
+ app41.get("/g/:slug", (c) => {
14817
14971
  return c.html(brandedPublicHtml());
14818
14972
  });
14819
- app39.get("/graph", (c) => {
14973
+ app41.get("/graph", (c) => {
14820
14974
  const host = (c.req.header("host") ?? "").split(":")[0];
14821
14975
  if (isPublicHost(host)) return c.text("Not found", 404);
14822
14976
  return c.html(cachedHtml("graph.html"));
14823
14977
  });
14824
- app39.get("/sessions", (c) => {
14978
+ app41.get("/sessions", (c) => {
14825
14979
  const host = (c.req.header("host") ?? "").split(":")[0];
14826
14980
  if (isPublicHost(host)) return c.text("Not found", 404);
14827
14981
  return c.html(cachedHtml("sessions.html"));
14828
14982
  });
14829
- app39.get("/data", (c) => {
14983
+ app41.get("/data", (c) => {
14830
14984
  const host = (c.req.header("host") ?? "").split(":")[0];
14831
14985
  if (isPublicHost(host)) return c.text("Not found", 404);
14832
14986
  return c.html(cachedHtml("data.html"));
14833
14987
  });
14834
- app39.get("/:slug", async (c, next) => {
14988
+ app41.get("/:slug", async (c, next) => {
14835
14989
  const slug = c.req.param("slug");
14836
14990
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
14837
14991
  const branding = loadBrandingCache(slug);
@@ -14841,15 +14995,15 @@ app39.get("/:slug", async (c, next) => {
14841
14995
  await next();
14842
14996
  });
14843
14997
  if (brandFaviconPath !== "/favicon.ico") {
14844
- app39.get("/favicon.ico", (c) => {
14998
+ app41.get("/favicon.ico", (c) => {
14845
14999
  c.header("Cache-Control", "public, max-age=300");
14846
15000
  return c.redirect(brandFaviconPath, 302);
14847
15001
  });
14848
15002
  }
14849
- app39.use("/*", serveStatic({ root: "./public" }));
15003
+ app41.use("/*", serveStatic({ root: "./public" }));
14850
15004
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
14851
15005
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
14852
- var httpServer = serve({ fetch: app39.fetch, port, hostname });
15006
+ var httpServer = serve({ fetch: app41.fetch, port, hostname });
14853
15007
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
14854
15008
  {
14855
15009
  const loopHist = monitorEventLoopDelay({ resolution: 50 });
@@ -14885,7 +15039,7 @@ for (const m of SUBAPP_MANIFEST) {
14885
15039
  }
14886
15040
  try {
14887
15041
  const registered = [];
14888
- for (const r of app39.routes ?? []) {
15042
+ for (const r of app41.routes ?? []) {
14889
15043
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
14890
15044
  if (AGENT_SLUG_PATTERN.test(r.path)) {
14891
15045
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -14907,8 +15061,8 @@ try {
14907
15061
  }
14908
15062
  (async () => {
14909
15063
  try {
14910
- if (!existsSync21(USERS_FILE)) return;
14911
- const usersRaw = readFileSync21(USERS_FILE, "utf-8").trim();
15064
+ if (!existsSync22(USERS_FILE)) return;
15065
+ const usersRaw = readFileSync22(USERS_FILE, "utf-8").trim();
14912
15066
  if (!usersRaw) return;
14913
15067
  const users = JSON.parse(usersRaw);
14914
15068
  const userId = users[0]?.userId;
@@ -15003,7 +15157,7 @@ if (bootAccountConfig?.whatsapp) {
15003
15157
  }
15004
15158
  init({
15005
15159
  configDir: configDirForWhatsApp,
15006
- platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join16(__dirname, "..")),
15160
+ platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
15007
15161
  accountConfig: bootAccountConfig,
15008
15162
  onMessage: async (msg) => {
15009
15163
  if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {