@rubytech/create-maxy-code 0.1.192 → 0.1.194

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 (82) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/docs/references/deployment.md +6 -4
  3. package/payload/platform/plugins/docs/references/projects-guide.md +21 -0
  4. package/payload/platform/plugins/work/PLUGIN.md +2 -0
  5. package/payload/platform/plugins/work/skills/execute-task/SKILL.md +101 -0
  6. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  7. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +12 -1
  8. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  9. package/payload/server/{chunk-WWD4TCJJ.js → chunk-EXIPYITB.js} +2 -0
  10. package/payload/server/maxy-edge.js +1 -1
  11. package/payload/server/public/assets/AdminShell-BoJbnn6d.js +1 -0
  12. package/payload/server/public/assets/{Checkbox-DsHqjzGj.js → Checkbox-G-kyM1P1.js} +1 -1
  13. package/payload/server/public/assets/{admin-CWOprOdW.js → admin-B-GDNkoN.js} +1 -1
  14. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DROzw8rH.js → architectureDiagram-Q4EWVU46-BGgdXdD2.js} +1 -1
  15. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Dw9sieJu.js → blockDiagram-DXYQGD6D-DKWoL4Rp.js} +1 -1
  16. package/payload/server/public/assets/{brand-BQW2DYy_.css → brand-MbpD2Bhr.css} +1 -1
  17. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-fnwntjFK.js → c4Diagram-AHTNJAMY-Ca6rs6F4.js} +1 -1
  18. package/payload/server/public/assets/channel-BwsV7WTV.js +1 -0
  19. package/payload/server/public/assets/{chunk-336JU56O-DVpyamlA.js → chunk-336JU56O-DcdMZImV.js} +2 -2
  20. package/payload/server/public/assets/{chunk-426QAEUC-yiGugjCx.js → chunk-426QAEUC-9FSP-c1z.js} +1 -1
  21. package/payload/server/public/assets/{chunk-4TB4RGXK-BAPL_MqI.js → chunk-4TB4RGXK-CC1QpEvA.js} +1 -1
  22. package/payload/server/public/assets/{chunk-5FUZZQ4R-Ba-5D35r.js → chunk-5FUZZQ4R-o1b70dEE.js} +1 -1
  23. package/payload/server/public/assets/{chunk-5PVQY5BW-BtDS8-t9.js → chunk-5PVQY5BW-C7VCYRz9.js} +1 -1
  24. package/payload/server/public/assets/{chunk-EDXVE4YY-CqcdpDg_.js → chunk-EDXVE4YY-B8d5xj_4.js} +1 -1
  25. package/payload/server/public/assets/{chunk-ENJZ2VHE-CaBy9U1e.js → chunk-ENJZ2VHE-SSbr4n2X.js} +1 -1
  26. package/payload/server/public/assets/{chunk-ICPOFSXX-BdPjOce4.js → chunk-ICPOFSXX-Cgj9YSpX.js} +1 -1
  27. package/payload/server/public/assets/{chunk-OYMX7WX6-CK6wx_FD.js → chunk-OYMX7WX6-DNEEcCqI.js} +1 -1
  28. package/payload/server/public/assets/{chunk-U2HBQHQK-DyZFy43o.js → chunk-U2HBQHQK-DuaoK83q.js} +1 -1
  29. package/payload/server/public/assets/{chunk-X2U36JSP-CMTofLbX.js → chunk-X2U36JSP-CzMp0dpq.js} +1 -1
  30. package/payload/server/public/assets/{chunk-YZCP3GAM-YfFrkYbQ.js → chunk-YZCP3GAM-B2wBDwSa.js} +1 -1
  31. package/payload/server/public/assets/{chunk-ZZ45TVLE-BVfvS5n3.js → chunk-ZZ45TVLE-DkyF7XKW.js} +1 -1
  32. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CEWNfHVo.js +1 -0
  33. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BBjzRxux.js +1 -0
  34. package/payload/server/public/assets/clone-CXtSonnn.js +1 -0
  35. package/payload/server/public/assets/{dagre-ComHkUs6.js → dagre-AGj1P0p4.js} +1 -1
  36. package/payload/server/public/assets/{dagre-KV5264BT-BB-QqzpF.js → dagre-KV5264BT-Cnrxcu6A.js} +1 -1
  37. package/payload/server/public/assets/data-Bg0Frxt3.js +1 -0
  38. package/payload/server/public/assets/{diagram-5BDNPKRD-CpQQszhw.js → diagram-5BDNPKRD-gyFYSx73.js} +1 -1
  39. package/payload/server/public/assets/{diagram-G4DWMVQ6-DLdElVzs.js → diagram-G4DWMVQ6-DFmZEv5C.js} +1 -1
  40. package/payload/server/public/assets/{diagram-MMDJMWI5-JQ3ceLSO.js → diagram-MMDJMWI5-DA4qbuEW.js} +1 -1
  41. package/payload/server/public/assets/{diagram-TYMM5635-D_-AtVPR.js → diagram-TYMM5635-D4n-8gig.js} +1 -1
  42. package/payload/server/public/assets/{erDiagram-SMLLAGMA-Dq50MKD-.js → erDiagram-SMLLAGMA-CigRMjF1.js} +1 -1
  43. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CEdKm-zL.js → flowDiagram-DWJPFMVM-ClS27acA.js} +1 -1
  44. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CpTomdNN.js → ganttDiagram-T4ZO3ILL-Dr1IulXe.js} +1 -1
  45. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-VU-gjbee.js → gitGraphDiagram-UUTBAWPF-lwLibdPs.js} +1 -1
  46. package/payload/server/public/assets/{graph-BXaY_xoS.js → graph-CpozZ74I.js} +2 -2
  47. package/payload/server/public/assets/{graph-labels-EqZyoU25.js → graph-labels-C2y666R0.js} +1 -1
  48. package/payload/server/public/assets/{graphlib-nLzyerxi.js → graphlib-DBvoJMrc.js} +1 -1
  49. package/payload/server/public/assets/{infoDiagram-42DDH7IO-ThwX5Xgr.js → infoDiagram-42DDH7IO-D4kReEIV.js} +1 -1
  50. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DaKxxHLW.js → ishikawaDiagram-UXIWVN3A-BnteQRQ0.js} +1 -1
  51. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DtMAHpWz.js → journeyDiagram-VCZTEJTY-CXu6hLyJ.js} +1 -1
  52. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-s898dJRu.js → kanban-definition-6JOO6SKY-CGDW2jle.js} +1 -1
  53. package/payload/server/public/assets/{line-D96q2CLD.js → line-pdg5hxC3.js} +1 -1
  54. package/payload/server/public/assets/{mermaid-parser.core-CqFLtzz8.js → mermaid-parser.core-o3lIIK3Z.js} +1 -1
  55. package/payload/server/public/assets/{mermaid.core-o9rmBTu-.js → mermaid.core-DLR6Q3rV.js} +3 -3
  56. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BM8KKsaM.js → mindmap-definition-QFDTVHPH-CH4cB0Dn.js} +1 -1
  57. package/payload/server/public/assets/{pieDiagram-DEJITSTG-B66Y-dcU.js → pieDiagram-DEJITSTG-Ba4voL_Y.js} +1 -1
  58. package/payload/server/public/assets/{public-ClAaV52O.js → public-C8mil9h0.js} +3 -3
  59. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Bv4mojq8.js → quadrantDiagram-34T5L4WZ-Cqn2xehe.js} +1 -1
  60. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BNYdfEKS.js → requirementDiagram-MS252O5E-DLfNx99l.js} +1 -1
  61. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Do8BgX92.js → sankeyDiagram-XADWPNL6-uck_V-cb.js} +1 -1
  62. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-VN57FKth.js → sequenceDiagram-FGHM5R23-DmQalqud.js} +1 -1
  63. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CCtRfCg0.js → stateDiagram-FHFEXIEX-DUdWeVRa.js} +1 -1
  64. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DNTpFwdy.js +1 -0
  65. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-ja01S9Wd.js → timeline-definition-GMOUNBTQ-BgL1wM5n.js} +1 -1
  66. package/payload/server/public/assets/{useSelectionMode-ejMSaa52.js → useSelectionMode-BLpVlOgm.js} +1 -1
  67. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-wWbiL1f6.js → vennDiagram-DHZGUBPP-7FHjIqPi.js} +1 -1
  68. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BZgue-PK.js → wardleyDiagram-NUSXRM2D-BHzo4V1J.js} +1 -1
  69. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-B_ynYRnW.js → xychartDiagram-5P7HB3ND-DtuWhqwh.js} +1 -1
  70. package/payload/server/public/data.html +5 -5
  71. package/payload/server/public/graph.html +6 -6
  72. package/payload/server/public/index.html +6 -6
  73. package/payload/server/public/public.html +5 -5
  74. package/payload/server/server.js +309 -280
  75. package/payload/server/public/assets/AdminShell-CdgotOLV.js +0 -1
  76. package/payload/server/public/assets/channel-DEl-UCEn.js +0 -1
  77. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BZ9e1dmR.js +0 -1
  78. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B1_4kXdN.js +0 -1
  79. package/payload/server/public/assets/clone-CNXfxCnl.js +0 -1
  80. package/payload/server/public/assets/data-DEsRsfI1.js +0 -1
  81. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Cz319KBI.js +0 -1
  82. /package/payload/server/public/assets/{brand-DKUA91KU.js → brand-CYcGHhlS.js} +0 -0
@@ -9,6 +9,7 @@ import {
9
9
  COMMERCIAL_MODE,
10
10
  GREETING_DIRECTIVE,
11
11
  Hono,
12
+ INSTALL_OWNER_FILE,
12
13
  LOG_DIR,
13
14
  MAXY_DIR,
14
15
  PLATFORM_ROOT,
@@ -83,7 +84,7 @@ import {
83
84
  vncLog,
84
85
  walkPremiumBundles,
85
86
  writeAdminUserAndPerson
86
- } from "./chunk-WWD4TCJJ.js";
87
+ } from "./chunk-EXIPYITB.js";
87
88
  import {
88
89
  __commonJS,
89
90
  __toESM
@@ -815,8 +816,8 @@ var serveStatic = (options = { root: "" }) => {
815
816
  };
816
817
 
817
818
  // server/index.ts
818
- import { readFileSync as readFileSync20, existsSync as existsSync22, watchFile } from "fs";
819
- import { resolve as resolve23, join as join15, basename as basename6 } from "path";
819
+ import { readFileSync as readFileSync21, existsSync as existsSync21, watchFile } from "fs";
820
+ import { resolve as resolve23, join as join16, basename as basename6 } from "path";
820
821
  import { homedir as homedir2 } from "os";
821
822
  import { monitorEventLoopDelay } from "perf_hooks";
822
823
 
@@ -6325,19 +6326,32 @@ app4.post("/set-pin", async (c) => {
6325
6326
  }
6326
6327
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
6327
6328
  if (process.platform === "linux") {
6328
- const smbProc = spawnSync2("sudo", ["-n", "smbpasswd", "-a", "-s", "admin"], {
6329
- input: `${body.pin}
6329
+ let installOwner = null;
6330
+ if (existsSync6(INSTALL_OWNER_FILE)) {
6331
+ try {
6332
+ const raw = readFileSync8(INSTALL_OWNER_FILE, "utf-8").trim();
6333
+ if (raw.length > 0) installOwner = raw;
6334
+ } catch (err) {
6335
+ console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
6336
+ }
6337
+ }
6338
+ if (!installOwner) {
6339
+ console.error(`[set-pin] smbpasswd sync failed owner=<unknown> rc=-1 reason=install-owner-file-missing path=${INSTALL_OWNER_FILE}`);
6340
+ } else {
6341
+ const smbProc = spawnSync2("sudo", ["-n", "smbpasswd", "-a", "-s", installOwner], {
6342
+ input: `${body.pin}
6330
6343
  ${body.pin}
6331
6344
  `,
6332
- stdio: ["pipe", "pipe", "pipe"],
6333
- encoding: "utf-8",
6334
- timeout: 1e4
6335
- });
6336
- if (smbProc.status === 0) {
6337
- console.log(`[set-pin] smb-password-synced userId=${userId.slice(0, 8)}\u2026`);
6338
- } else {
6339
- const stderr = (smbProc.stderr ?? "").trim().slice(0, 200);
6340
- console.error(`[set-pin] smb-password-sync-failed exit=${smbProc.status} stderr=${JSON.stringify(stderr)}`);
6345
+ stdio: ["pipe", "pipe", "pipe"],
6346
+ encoding: "utf-8",
6347
+ timeout: 1e4
6348
+ });
6349
+ if (smbProc.status === 0) {
6350
+ console.log(`[set-pin] smbpasswd sync ok owner=${installOwner} userId=${userId.slice(0, 8)}\u2026`);
6351
+ } else {
6352
+ const stderr = (smbProc.stderr ?? "").trim().slice(0, 200);
6353
+ console.error(`[set-pin] smbpasswd sync failed owner=${installOwner} rc=${smbProc.status} stderr=${JSON.stringify(stderr)}`);
6354
+ }
6341
6355
  }
6342
6356
  } else {
6343
6357
  console.log(`[set-pin] smb-password-sync-skipped reason=non-linux platform=${process.platform}`);
@@ -7245,24 +7259,6 @@ function openResumeStreamLog(accountId, sessionId) {
7245
7259
  }
7246
7260
  return createWriteStream(resolvePath(dir, `${sessionId}.log`), { flags: "a" });
7247
7261
  }
7248
- var healPending = /* @__PURE__ */ new Map();
7249
- function markHealPending(accountId, attachmentId) {
7250
- let set = healPending.get(accountId);
7251
- if (!set) {
7252
- set = /* @__PURE__ */ new Set();
7253
- healPending.set(accountId, set);
7254
- }
7255
- set.add(attachmentId);
7256
- }
7257
- function clearHealPending(accountId, attachmentId) {
7258
- const set = healPending.get(accountId);
7259
- if (!set) return;
7260
- set.delete(attachmentId);
7261
- if (set.size === 0) healPending.delete(accountId);
7262
- }
7263
- function isHealPending(accountId, attachmentId) {
7264
- return healPending.get(accountId)?.has(attachmentId) ?? false;
7265
- }
7266
7262
  function validateAndShapeAttachments(raws, conversationAccountId, sessionId, messageId, streamLogPath) {
7267
7263
  const chips = [];
7268
7264
  let valid = 0;
@@ -7640,17 +7636,14 @@ app11.post("/:id/resume", async (c) => {
7640
7636
  textOffset: c2.textOffset
7641
7637
  };
7642
7638
  if (!c2.artefactAttachmentId || !c2.artefactMimeType || !c2.artefactTitle) return base;
7643
- markHealPending(accountId, c2.artefactAttachmentId);
7644
7639
  try {
7645
7640
  const dataObj = JSON.parse(c2.data);
7646
7641
  const bytesPick = pickComponentBytes(dataObj);
7647
7642
  if (!bytesPick) {
7648
- clearHealPending(accountId, c2.artefactAttachmentId);
7649
7643
  return base;
7650
7644
  }
7651
7645
  const filename = bytesPick.mimeType === "text/html" ? `${c2.artefactTitle}.html` : `${c2.artefactTitle}.md`;
7652
7646
  await storeComponentArtefact(accountId, c2.artefactAttachmentId, bytesPick.mimeType, bytesPick.content, filename);
7653
- clearHealPending(accountId, c2.artefactAttachmentId);
7654
7647
  streamLogPath.write(
7655
7648
  `[${(/* @__PURE__ */ new Date()).toISOString()}] [component-persist] heal componentName=${c2.name} attachmentId=${c2.artefactAttachmentId.slice(0, 8)} mimeType=${bytesPick.mimeType} bytes=${bytesPick.content.length} outcome=ok
7656
7649
  `
@@ -7662,7 +7655,6 @@ app11.post("/:id/resume", async (c) => {
7662
7655
  artefactTitle: c2.artefactTitle
7663
7656
  };
7664
7657
  } catch (writeErr) {
7665
- clearHealPending(accountId, c2.artefactAttachmentId);
7666
7658
  const reason2 = writeErr instanceof Error ? writeErr.message : String(writeErr);
7667
7659
  streamLogPath.write(
7668
7660
  `[${(/* @__PURE__ */ new Date()).toISOString()}] [component-persist] heal componentName=${c2.name} attachmentId=${c2.artefactAttachmentId.slice(0, 8)} outcome=disk-fail reason=${JSON.stringify(reason2.slice(0, 200))}
@@ -11733,11 +11725,9 @@ function isWithin(target, root) {
11733
11725
  var sidebar_artefacts_default = app22;
11734
11726
 
11735
11727
  // server/routes/admin/sidebar-artefact-save.ts
11736
- import { mkdir as mkdir4, readdir as readdir5, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11728
+ import { mkdir as mkdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11737
11729
  import { resolve as resolve16 } from "path";
11738
- import { existsSync as existsSync17 } from "fs";
11739
11730
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
11740
- var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11741
11731
  var app23 = new Hono();
11742
11732
  app23.post("/", requireAdminSession, async (c) => {
11743
11733
  const cacheKey = c.var.cacheKey;
@@ -11748,11 +11738,7 @@ app23.post("/", requireAdminSession, async (c) => {
11748
11738
  return c.json({ error: "id and content required" }, 400);
11749
11739
  }
11750
11740
  const accountDir = resolve16(ACCOUNTS_DIR, accountId);
11751
- const resolved = await resolveSavePath(body.id, accountId, accountDir);
11752
- if (resolved.kind === "heal-race") {
11753
- c.header("Retry-After", "2");
11754
- return c.json({ error: "heal-race", reason: resolved.reason }, 503);
11755
- }
11741
+ const resolved = await resolveSavePath(body.id, accountDir);
11756
11742
  if (resolved.kind === "reject") {
11757
11743
  console.error(
11758
11744
  `[admin/sidebar-artefact-save] auth-rejected reason=${resolved.reason} path=${body.id}`
@@ -11781,77 +11767,119 @@ app23.post("/", requireAdminSession, async (c) => {
11781
11767
  );
11782
11768
  return c.json({ updatedAt });
11783
11769
  });
11784
- async function resolveSavePath(id, accountId, accountDir) {
11785
- if (id.startsWith("agent-template:")) {
11786
- const parts = id.split(":");
11787
- if (parts.length !== 3) return { kind: "reject", status: 400, reason: "invalid-id" };
11788
- const [, role, filename] = parts;
11789
- if (role === "specialist") {
11790
- return { kind: "reject", status: 403, reason: "specialist-write-blocked" };
11791
- }
11792
- if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
11793
- return { kind: "reject", status: 400, reason: "invalid-id" };
11794
- }
11795
- const parent = resolve16(accountDir, "agents", "admin");
11796
- await mkdir4(parent, { recursive: true });
11770
+ async function resolveSavePath(id, accountDir) {
11771
+ if (!id.startsWith("agent-template:")) {
11772
+ return { kind: "reject", status: 400, reason: "invalid-id" };
11773
+ }
11774
+ const parts = id.split(":");
11775
+ if (parts.length !== 3) return { kind: "reject", status: 400, reason: "invalid-id" };
11776
+ const [, role, filename] = parts;
11777
+ if (role === "specialist") {
11778
+ return { kind: "reject", status: 403, reason: "specialist-write-blocked" };
11779
+ }
11780
+ if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
11781
+ return { kind: "reject", status: 400, reason: "invalid-id" };
11782
+ }
11783
+ const parent = resolve16(accountDir, "agents", "admin");
11784
+ await mkdir4(parent, { recursive: true });
11785
+ try {
11786
+ validateFilePathInAccount(parent, accountDir);
11787
+ } catch {
11788
+ return { kind: "reject", status: 400, reason: "containment-rejected" };
11789
+ }
11790
+ return { kind: "admin-template", path: resolve16(parent, filename) };
11791
+ }
11792
+ function relPath(absPath, root) {
11793
+ return absPath.startsWith(root) ? absPath.slice(root.length + 1) : absPath;
11794
+ }
11795
+ var sidebar_artefact_save_default = app23;
11796
+
11797
+ // server/routes/admin/sidebar-sessions.ts
11798
+ import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
11799
+ import { join as join13 } from "path";
11800
+ var RC_URL_RE = /https:\/\/claude\.ai\/code\/session_[A-Za-z0-9_-]+/;
11801
+ 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;
11802
+ var TITLE_MAX = 80;
11803
+ var app24 = new Hono();
11804
+ function projectsDirForAccount(accountId) {
11805
+ const configDir2 = process.env.CLAUDE_CONFIG_DIR;
11806
+ if (!configDir2) return null;
11807
+ const accountCwd = join13(DATA_ROOT, "accounts", accountId);
11808
+ const slug = accountCwd.replace(/\//g, "-");
11809
+ return join13(configDir2, "projects", slug);
11810
+ }
11811
+ function firstUserMessage(body) {
11812
+ for (const line of body.split("\n")) {
11813
+ if (!line || line[0] !== "{") continue;
11814
+ let parsed;
11797
11815
  try {
11798
- validateFilePathInAccount(parent, accountDir);
11816
+ parsed = JSON.parse(line);
11799
11817
  } catch {
11800
- return { kind: "reject", status: 400, reason: "containment-rejected" };
11818
+ continue;
11801
11819
  }
11802
- return { kind: "admin-template", path: resolve16(parent, filename) };
11820
+ if (!parsed || typeof parsed !== "object") continue;
11821
+ const row = parsed;
11822
+ if (row.type !== "user" || !row.message || row.message.role !== "user") continue;
11823
+ const content = row.message.content;
11824
+ if (typeof content !== "string") continue;
11825
+ const trimmed = content.trim().replace(/\s+/g, " ");
11826
+ if (!trimmed) continue;
11827
+ return trimmed.length > TITLE_MAX ? trimmed.slice(0, TITLE_MAX - 1) + "\u2026" : trimmed;
11803
11828
  }
11804
- if (UUID_RE4.test(id)) {
11805
- const dir = resolve16(ATTACHMENTS_ROOT, accountId, id);
11806
- if (!existsSync17(dir)) {
11807
- const attShort = id.slice(0, 8);
11808
- if (isHealPending(accountId, id)) {
11809
- console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=503-retry source=heal-pending`);
11810
- return { kind: "heal-race", reason: "dir-pending" };
11811
- }
11812
- const session = getSession();
11813
- try {
11814
- const result = await session.run(
11815
- `MATCH (k:KnowledgeDocument {accountId: $accountId, attachmentId: $attachmentId})
11816
- RETURN count(k) AS cnt`,
11817
- { accountId, attachmentId: id }
11818
- );
11819
- const cnt = result.records[0]?.get("cnt")?.toNumber?.() ?? 0;
11820
- if (cnt > 0) {
11821
- console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=503-retry source=neo4j-row`);
11822
- return { kind: "heal-race", reason: "dir-pending" };
11823
- }
11824
- console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=400-terminal`);
11825
- return { kind: "reject", status: 400, reason: "not-found" };
11826
- } catch (neoErr) {
11827
- const reason = neoErr instanceof Error ? neoErr.message.slice(0, 120) : String(neoErr).slice(0, 120);
11828
- console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=neo4j-fail reason="${reason}"`);
11829
- return { kind: "heal-race", reason: "neo4j-fail" };
11830
- } finally {
11831
- try {
11832
- await session.close();
11833
- } catch {
11834
- }
11835
- }
11829
+ return null;
11830
+ }
11831
+ app24.get("/", requireAdminSession, async (c) => {
11832
+ const cacheKey = c.var.cacheKey;
11833
+ const accountId = getAccountIdForSession(cacheKey);
11834
+ if (!accountId) {
11835
+ return c.json({ error: "Account not found for session" }, 401);
11836
+ }
11837
+ const projectsDir = projectsDirForAccount(accountId);
11838
+ if (!projectsDir) {
11839
+ console.error(`[admin-sessions-list] account=${accountId} no-claude-config-dir`);
11840
+ return c.json({ sessions: [] });
11841
+ }
11842
+ let entries;
11843
+ try {
11844
+ entries = readdirSync8(projectsDir);
11845
+ } catch (err) {
11846
+ const code = err.code;
11847
+ if (code === "ENOENT") {
11848
+ console.log(`[admin-sessions-list] account=${accountId} rows=0 reason=no-projects-dir`);
11849
+ return c.json({ sessions: [] });
11836
11850
  }
11851
+ const message = err instanceof Error ? err.message : String(err);
11852
+ console.error(`[admin-sessions-list] account=${accountId} readdir-failed error="${message}"`);
11853
+ return c.json({ error: "projects-dir-unreadable" }, 500);
11854
+ }
11855
+ const rows = [];
11856
+ for (const name of entries) {
11857
+ if (!SESSION_ID_RE.test(name)) continue;
11858
+ const sessionId = name.slice(0, -".jsonl".length);
11859
+ const path2 = join13(projectsDir, name);
11860
+ let body;
11861
+ let mtimeMs;
11837
11862
  try {
11838
- validateFilePathInAccount(dir, resolve16(ATTACHMENTS_ROOT, accountId));
11863
+ body = readFileSync14(path2, "utf8");
11864
+ mtimeMs = statSync7(path2).mtimeMs;
11839
11865
  } catch {
11840
- return { kind: "reject", status: 400, reason: "containment-rejected" };
11841
- }
11842
- const entries = await readdir5(dir);
11843
- const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
11844
- if (!dataFile) {
11845
- return { kind: "reject", status: 400, reason: "not-found" };
11866
+ continue;
11846
11867
  }
11847
- return { kind: "knowledge-doc", path: resolve16(dir, dataFile) };
11868
+ const urlMatch = body.match(RC_URL_RE);
11869
+ if (!urlMatch) continue;
11870
+ const title = firstUserMessage(body) ?? sessionId.slice(0, 8);
11871
+ rows.push({
11872
+ sessionId,
11873
+ title,
11874
+ url: urlMatch[0],
11875
+ capturedAt: new Date(mtimeMs).toISOString()
11876
+ });
11848
11877
  }
11849
- return { kind: "reject", status: 400, reason: "invalid-id" };
11850
- }
11851
- function relPath(absPath, root) {
11852
- return absPath.startsWith(root) ? absPath.slice(root.length + 1) : absPath;
11853
- }
11854
- var sidebar_artefact_save_default = app23;
11878
+ rows.sort((a, b) => a.capturedAt < b.capturedAt ? 1 : -1);
11879
+ console.log(`[admin-sessions-list] account=${accountId} rows=${rows.length}`);
11880
+ return c.json({ sessions: rows });
11881
+ });
11882
+ var sidebar_sessions_default = app24;
11855
11883
 
11856
11884
  // server/routes/admin/system-stats.ts
11857
11885
  import { readFile as readFile5 } from "fs/promises";
@@ -11948,8 +11976,8 @@ async function sample() {
11948
11976
  if (process.platform === "linux") return sampleLinux();
11949
11977
  return sampleOsFallback();
11950
11978
  }
11951
- var app24 = new Hono();
11952
- app24.get("/", async (c) => {
11979
+ var app25 = new Hono();
11980
+ app25.get("/", async (c) => {
11953
11981
  const started = Date.now();
11954
11982
  if (!inflight) {
11955
11983
  inflight = sample().finally(() => {
@@ -11972,17 +12000,17 @@ app24.get("/", async (c) => {
11972
12000
  return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
11973
12001
  }
11974
12002
  });
11975
- var system_stats_default = app24;
12003
+ var system_stats_default = app25;
11976
12004
 
11977
12005
  // server/routes/admin/health.ts
11978
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "fs";
11979
- import { resolve as resolve17, join as join13 } from "path";
12006
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
12007
+ import { resolve as resolve17, join as join14 } from "path";
11980
12008
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
11981
12009
  var brandHostname = "maxy";
11982
- var brandJsonPath = join13(PLATFORM_ROOT6, "config", "brand.json");
11983
- if (existsSync18(brandJsonPath)) {
12010
+ var brandJsonPath = join14(PLATFORM_ROOT6, "config", "brand.json");
12011
+ if (existsSync17(brandJsonPath)) {
11984
12012
  try {
11985
- const brand = JSON.parse(readFileSync14(brandJsonPath, "utf-8"));
12013
+ const brand = JSON.parse(readFileSync15(brandJsonPath, "utf-8"));
11986
12014
  if (brand.hostname) brandHostname = brand.hostname;
11987
12015
  } catch {
11988
12016
  }
@@ -11991,8 +12019,8 @@ var VERSION_FILE = resolve17(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
11991
12019
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11992
12020
  var PROBE_TIMEOUT_MS = 1e3;
11993
12021
  function readVersion() {
11994
- if (!existsSync18(VERSION_FILE)) return "unknown";
11995
- return readFileSync14(VERSION_FILE, "utf-8").trim() || "unknown";
12022
+ if (!existsSync17(VERSION_FILE)) return "unknown";
12023
+ return readFileSync15(VERSION_FILE, "utf-8").trim() || "unknown";
11996
12024
  }
11997
12025
  async function probeConversationDb() {
11998
12026
  let session;
@@ -12017,8 +12045,8 @@ async function probeConversationDb() {
12017
12045
  });
12018
12046
  }
12019
12047
  }
12020
- var app25 = new Hono();
12021
- app25.get("/", async (c) => {
12048
+ var app26 = new Hono();
12049
+ app26.get("/", async (c) => {
12022
12050
  const version = readVersion();
12023
12051
  const probe = await probeConversationDb();
12024
12052
  const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
@@ -12040,7 +12068,7 @@ app25.get("/", async (c) => {
12040
12068
  uptimeMs
12041
12069
  });
12042
12070
  });
12043
- var health_default2 = app25;
12071
+ var health_default2 = app26;
12044
12072
 
12045
12073
  // server/routes/admin/linkedin-ingest.ts
12046
12074
  var TAG20 = "[linkedin-ingest-route]";
@@ -12136,8 +12164,8 @@ function buildInitialMessage(env) {
12136
12164
  }
12137
12165
  return header;
12138
12166
  }
12139
- var app26 = new Hono();
12140
- app26.post("/", requireAdminSession, async (c) => {
12167
+ var app27 = new Hono();
12168
+ app27.post("/", requireAdminSession, async (c) => {
12141
12169
  let body;
12142
12170
  try {
12143
12171
  body = await c.req.json();
@@ -12191,7 +12219,7 @@ app26.post("/", requireAdminSession, async (c) => {
12191
12219
  );
12192
12220
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: claudeSessionId }, 202);
12193
12221
  });
12194
- var linkedin_ingest_default = app26;
12222
+ var linkedin_ingest_default = app27;
12195
12223
 
12196
12224
  // server/routes/admin/post-turn-context.ts
12197
12225
  import neo4j2 from "neo4j-driver";
@@ -12233,8 +12261,8 @@ function pruneProperties(raw) {
12233
12261
  }
12234
12262
  return out;
12235
12263
  }
12236
- var app27 = new Hono();
12237
- app27.get("/", async (c) => {
12264
+ var app28 = new Hono();
12265
+ app28.get("/", async (c) => {
12238
12266
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12239
12267
  if (!isLoopbackAddr2(remoteAddr)) {
12240
12268
  console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12294,7 +12322,7 @@ app27.get("/", async (c) => {
12294
12322
  await session.close();
12295
12323
  }
12296
12324
  });
12297
- var post_turn_context_default = app27;
12325
+ var post_turn_context_default = app28;
12298
12326
 
12299
12327
  // server/routes/admin/public-session-context.ts
12300
12328
  import neo4j3 from "neo4j-driver";
@@ -12336,8 +12364,8 @@ function pruneProperties2(raw) {
12336
12364
  }
12337
12365
  return out;
12338
12366
  }
12339
- var app28 = new Hono();
12340
- app28.get("/", async (c) => {
12367
+ var app29 = new Hono();
12368
+ app29.get("/", async (c) => {
12341
12369
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12342
12370
  if (!isLoopbackAddr3(remoteAddr)) {
12343
12371
  console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12396,15 +12424,15 @@ app28.get("/", async (c) => {
12396
12424
  await session.close();
12397
12425
  }
12398
12426
  });
12399
- var public_session_context_default = app28;
12427
+ var public_session_context_default = app29;
12400
12428
 
12401
12429
  // server/routes/admin/public-session-exit.ts
12402
12430
  var TAG23 = "[public-session-exit-route]";
12403
12431
  function isLoopbackAddr4(addr) {
12404
12432
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
12405
12433
  }
12406
- var app29 = new Hono();
12407
- app29.post("/", async (c) => {
12434
+ var app30 = new Hono();
12435
+ app30.post("/", async (c) => {
12408
12436
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12409
12437
  if (!isLoopbackAddr4(remoteAddr)) {
12410
12438
  console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12431,15 +12459,15 @@ app29.post("/", async (c) => {
12431
12459
  handlePublicSessionExit(sessionId);
12432
12460
  return c.json({ ok: true });
12433
12461
  });
12434
- var public_session_exit_default = app29;
12462
+ var public_session_exit_default = app30;
12435
12463
 
12436
12464
  // server/routes/admin/access-session-evict.ts
12437
12465
  var TAG24 = "[access-session-evict]";
12438
12466
  function isLoopbackAddr5(addr) {
12439
12467
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
12440
12468
  }
12441
- var app30 = new Hono();
12442
- app30.post("/", async (c) => {
12469
+ var app31 = new Hono();
12470
+ app31.post("/", async (c) => {
12443
12471
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
12444
12472
  if (!isLoopbackAddr5(remoteAddr)) {
12445
12473
  console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -12467,40 +12495,41 @@ app30.post("/", async (c) => {
12467
12495
  console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
12468
12496
  return c.json({ ok: true, dropped });
12469
12497
  });
12470
- var access_session_evict_default = app30;
12498
+ var access_session_evict_default = app31;
12471
12499
 
12472
12500
  // server/routes/admin/index.ts
12473
- var app31 = new Hono();
12474
- app31.route("/session", session_default);
12475
- app31.route("/logs", logs_default);
12476
- app31.route("/claude-info", claude_info_default);
12477
- app31.route("/attachment", attachment_default);
12478
- app31.route("/agents", agents_default);
12479
- app31.route("/sessions", sessions_default);
12480
- app31.route("/claude-sessions", claude_sessions_default);
12481
- app31.route("/log-ingest", log_ingest_default);
12482
- app31.route("/events", events_default);
12483
- app31.route("/files", files_default);
12484
- app31.route("/graph-search", graph_search_default);
12485
- app31.route("/graph-subgraph", graph_subgraph_default);
12486
- app31.route("/graph-delete", graph_delete_default);
12487
- app31.route("/graph-restore", graph_restore_default);
12488
- app31.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12489
- app31.route("/graph-default-view", graph_default_view_default);
12490
- app31.route("/sidebar-artefacts", sidebar_artefacts_default);
12491
- app31.route("/sidebar-artefact-save", sidebar_artefact_save_default);
12492
- app31.route("/system-stats", system_stats_default);
12493
- app31.route("/health-brand", health_default2);
12494
- app31.route("/linkedin-ingest", linkedin_ingest_default);
12495
- app31.route("/post-turn-context", post_turn_context_default);
12496
- app31.route("/public-session-context", public_session_context_default);
12497
- app31.route("/public-session-exit", public_session_exit_default);
12498
- app31.route("/access-session-evict", access_session_evict_default);
12499
- var admin_default = app31;
12501
+ var app32 = new Hono();
12502
+ app32.route("/session", session_default);
12503
+ app32.route("/logs", logs_default);
12504
+ app32.route("/claude-info", claude_info_default);
12505
+ app32.route("/attachment", attachment_default);
12506
+ app32.route("/agents", agents_default);
12507
+ app32.route("/sessions", sessions_default);
12508
+ app32.route("/claude-sessions", claude_sessions_default);
12509
+ app32.route("/log-ingest", log_ingest_default);
12510
+ app32.route("/events", events_default);
12511
+ app32.route("/files", files_default);
12512
+ app32.route("/graph-search", graph_search_default);
12513
+ app32.route("/graph-subgraph", graph_subgraph_default);
12514
+ app32.route("/graph-delete", graph_delete_default);
12515
+ app32.route("/graph-restore", graph_restore_default);
12516
+ app32.route("/graph-labels-in-graph", graph_labels_in_graph_default);
12517
+ app32.route("/graph-default-view", graph_default_view_default);
12518
+ app32.route("/sidebar-artefacts", sidebar_artefacts_default);
12519
+ app32.route("/sidebar-artefact-save", sidebar_artefact_save_default);
12520
+ app32.route("/sidebar-sessions", sidebar_sessions_default);
12521
+ app32.route("/system-stats", system_stats_default);
12522
+ app32.route("/health-brand", health_default2);
12523
+ app32.route("/linkedin-ingest", linkedin_ingest_default);
12524
+ app32.route("/post-turn-context", post_turn_context_default);
12525
+ app32.route("/public-session-context", public_session_context_default);
12526
+ app32.route("/public-session-exit", public_session_exit_default);
12527
+ app32.route("/access-session-evict", access_session_evict_default);
12528
+ var admin_default = app32;
12500
12529
 
12501
12530
  // app/lib/access-gate.ts
12502
12531
  import neo4j4 from "neo4j-driver";
12503
- import { readFileSync as readFileSync15 } from "fs";
12532
+ import { readFileSync as readFileSync16 } from "fs";
12504
12533
  import { resolve as resolve18 } from "path";
12505
12534
  import { randomUUID as randomUUID8 } from "crypto";
12506
12535
  var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
@@ -12509,7 +12538,7 @@ function readPassword() {
12509
12538
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
12510
12539
  const passwordFile = resolve18(PLATFORM_ROOT7, "config/.neo4j-password");
12511
12540
  try {
12512
- return readFileSync15(passwordFile, "utf-8").trim();
12541
+ return readFileSync16(passwordFile, "utf-8").trim();
12513
12542
  } catch {
12514
12543
  throw new Error(
12515
12544
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -12710,8 +12739,8 @@ async function generateNewMagicToken(grantId) {
12710
12739
  var TAG25 = "[access-verify]";
12711
12740
  var MINT_TAG = "[access-session-mint]";
12712
12741
  var COOKIE_NAME = "__access_session";
12713
- var app32 = new Hono();
12714
- app32.post("/", async (c) => {
12742
+ var app33 = new Hono();
12743
+ app33.post("/", async (c) => {
12715
12744
  const ip = c.var.clientIp || "unknown";
12716
12745
  let body;
12717
12746
  try {
@@ -12793,7 +12822,7 @@ app32.post("/", async (c) => {
12793
12822
  displayName: grant.displayName
12794
12823
  });
12795
12824
  });
12796
- var verify_token_default = app32;
12825
+ var verify_token_default = app33;
12797
12826
 
12798
12827
  // app/lib/access-email.ts
12799
12828
  import { spawn as spawn2 } from "child_process";
@@ -12856,9 +12885,9 @@ async function sendMagicLinkEmail(payload) {
12856
12885
 
12857
12886
  // server/routes/access/request-magic-link.ts
12858
12887
  var TAG26 = "[access-request-link]";
12859
- var app33 = new Hono();
12888
+ var app34 = new Hono();
12860
12889
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
12861
- app33.post("/", async (c) => {
12890
+ app34.post("/", async (c) => {
12862
12891
  let body;
12863
12892
  try {
12864
12893
  body = await c.req.json();
@@ -12932,16 +12961,16 @@ app33.post("/", async (c) => {
12932
12961
  );
12933
12962
  return c.json({ message: VISITOR_MESSAGE }, 200);
12934
12963
  });
12935
- var request_magic_link_default = app33;
12964
+ var request_magic_link_default = app34;
12936
12965
 
12937
12966
  // server/routes/access/index.ts
12938
- var app34 = new Hono();
12939
- app34.route("/verify-token", verify_token_default);
12940
- app34.route("/request-magic-link", request_magic_link_default);
12941
- var access_default = app34;
12967
+ var app35 = new Hono();
12968
+ app35.route("/verify-token", verify_token_default);
12969
+ app35.route("/request-magic-link", request_magic_link_default);
12970
+ var access_default = app35;
12942
12971
 
12943
12972
  // server/routes/sites.ts
12944
- import { existsSync as existsSync19, readFileSync as readFileSync16, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
12973
+ import { existsSync as existsSync18, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
12945
12974
  import { resolve as resolve20 } from "path";
12946
12975
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12947
12976
  var MIME = {
@@ -12973,8 +13002,8 @@ function getExt(p) {
12973
13002
  if (idx < p.lastIndexOf("/")) return "";
12974
13003
  return p.slice(idx).toLowerCase();
12975
13004
  }
12976
- var app35 = new Hono();
12977
- app35.get("/:rel{.*}", (c) => {
13005
+ var app36 = new Hono();
13006
+ app36.get("/:rel{.*}", (c) => {
12978
13007
  const reqPath = c.req.path;
12979
13008
  const rawRel = c.req.param("rel") ?? "";
12980
13009
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -13007,7 +13036,7 @@ app35.get("/:rel{.*}", (c) => {
13007
13036
  }
13008
13037
  let stat8;
13009
13038
  try {
13010
- stat8 = existsSync19(filePath) ? statSync7(filePath) : null;
13039
+ stat8 = existsSync18(filePath) ? statSync8(filePath) : null;
13011
13040
  } catch {
13012
13041
  stat8 = null;
13013
13042
  }
@@ -13026,7 +13055,7 @@ app35.get("/:rel{.*}", (c) => {
13026
13055
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
13027
13056
  return c.text("Forbidden", 403);
13028
13057
  }
13029
- if (!existsSync19(filePath)) {
13058
+ if (!existsSync18(filePath)) {
13030
13059
  console.error(`[sites] not-found path=${reqPath} status=404`);
13031
13060
  return c.text("Not found", 404);
13032
13061
  }
@@ -13045,7 +13074,7 @@ app35.get("/:rel{.*}", (c) => {
13045
13074
  }
13046
13075
  let body;
13047
13076
  try {
13048
- body = readFileSync16(realPath);
13077
+ body = readFileSync17(realPath);
13049
13078
  } catch (err) {
13050
13079
  const code = err?.code;
13051
13080
  if (code === "EISDIR") {
@@ -13077,11 +13106,11 @@ app35.get("/:rel{.*}", (c) => {
13077
13106
  "X-Content-Type-Options": "nosniff"
13078
13107
  });
13079
13108
  });
13080
- var sites_default = app35;
13109
+ var sites_default = app36;
13081
13110
 
13082
13111
  // app/lib/visitor-token.ts
13083
13112
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
13084
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync17, writeFileSync as writeFileSync6 } from "fs";
13113
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "fs";
13085
13114
  import { dirname as dirname4 } from "path";
13086
13115
  var TOKEN_PREFIX = "v1.";
13087
13116
  var SECRET_BYTES = 32;
@@ -13090,7 +13119,7 @@ var cachedSecret = null;
13090
13119
  function getSecret() {
13091
13120
  if (cachedSecret) return cachedSecret;
13092
13121
  try {
13093
- const hex2 = readFileSync17(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13122
+ const hex2 = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13094
13123
  if (hex2.length === SECRET_BYTES * 2) {
13095
13124
  cachedSecret = Buffer.from(hex2, "hex");
13096
13125
  return cachedSecret;
@@ -13104,7 +13133,7 @@ function getSecret() {
13104
13133
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
13105
13134
  } catch {
13106
13135
  }
13107
- const hex = readFileSync17(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13136
+ const hex = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
13108
13137
  cachedSecret = Buffer.from(hex, "hex");
13109
13138
  return cachedSecret;
13110
13139
  }
@@ -13157,8 +13186,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
13157
13186
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
13158
13187
 
13159
13188
  // app/lib/brand-config.ts
13160
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
13161
- import { join as join14 } from "path";
13189
+ import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
13190
+ import { join as join15 } from "path";
13162
13191
  var cached2 = null;
13163
13192
  var cachedAttempted = false;
13164
13193
  function readBrandConfig() {
@@ -13166,10 +13195,10 @@ function readBrandConfig() {
13166
13195
  cachedAttempted = true;
13167
13196
  const platformRoot = process.env.MAXY_PLATFORM_ROOT;
13168
13197
  if (!platformRoot) return null;
13169
- const brandPath = join14(platformRoot, "config", "brand.json");
13170
- if (!existsSync20(brandPath)) return null;
13198
+ const brandPath = join15(platformRoot, "config", "brand.json");
13199
+ if (!existsSync19(brandPath)) return null;
13171
13200
  try {
13172
- cached2 = JSON.parse(readFileSync18(brandPath, "utf-8"));
13201
+ cached2 = JSON.parse(readFileSync19(brandPath, "utf-8"));
13173
13202
  return cached2;
13174
13203
  } catch {
13175
13204
  return null;
@@ -13177,7 +13206,7 @@ function readBrandConfig() {
13177
13206
  }
13178
13207
 
13179
13208
  // server/routes/visitor-consent.ts
13180
- var app36 = new Hono();
13209
+ var app37 = new Hono();
13181
13210
  var CONSENT_COOKIE_NAME = "mxy_consent";
13182
13211
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
13183
13212
  var DEFAULT_CONSENT_COPY = {
@@ -13222,17 +13251,17 @@ function siteSlugFromReferer(referer) {
13222
13251
  return "";
13223
13252
  }
13224
13253
  }
13225
- app36.options("/consent", (c) => {
13254
+ app37.options("/consent", (c) => {
13226
13255
  const origin = getOrigin(c);
13227
13256
  setCorsHeaders(c, origin);
13228
13257
  return c.body(null, 204);
13229
13258
  });
13230
- app36.options("/brand-config", (c) => {
13259
+ app37.options("/brand-config", (c) => {
13231
13260
  const origin = getOrigin(c);
13232
13261
  setCorsHeaders(c, origin);
13233
13262
  return c.body(null, 204);
13234
13263
  });
13235
- app36.post("/consent", async (c) => {
13264
+ app37.post("/consent", async (c) => {
13236
13265
  const origin = getOrigin(c);
13237
13266
  setCorsHeaders(c, origin);
13238
13267
  let raw;
@@ -13272,7 +13301,7 @@ app36.post("/consent", async (c) => {
13272
13301
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
13273
13302
  return c.body(null, 204);
13274
13303
  });
13275
- app36.get("/brand-config", (c) => {
13304
+ app37.get("/brand-config", (c) => {
13276
13305
  const origin = getOrigin(c);
13277
13306
  setCorsHeaders(c, origin);
13278
13307
  const brand = readBrandConfig();
@@ -13282,7 +13311,7 @@ app36.get("/brand-config", (c) => {
13282
13311
  c.header("Cache-Control", "public, max-age=300");
13283
13312
  return c.json({ consent: { copy, palette } });
13284
13313
  });
13285
- var visitor_consent_default = app36;
13314
+ var visitor_consent_default = app37;
13286
13315
 
13287
13316
  // server/routes/listings.ts
13288
13317
  function getCookie(headerValue, name) {
@@ -13309,8 +13338,8 @@ function appendConsentParams(pageUrl, token) {
13309
13338
  }
13310
13339
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
13311
13340
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
13312
- var app37 = new Hono();
13313
- app37.get("/:slug/click", async (c) => {
13341
+ var app38 = new Hono();
13342
+ app38.get("/:slug/click", async (c) => {
13314
13343
  const slug = c.req.param("slug") ?? "";
13315
13344
  const rawSession = c.req.query("session") ?? "";
13316
13345
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -13374,10 +13403,10 @@ app37.get("/:slug/click", async (c) => {
13374
13403
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
13375
13404
  return c.redirect(redirectUrl, 302);
13376
13405
  });
13377
- var listings_default = app37;
13406
+ var listings_default = app38;
13378
13407
 
13379
13408
  // server/routes/visitor-event.ts
13380
- var app38 = new Hono();
13409
+ var app39 = new Hono();
13381
13410
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
13382
13411
  var buckets = /* @__PURE__ */ new Map();
13383
13412
  var RATE_LIMIT = 60;
@@ -13444,12 +13473,12 @@ function originAllowed(origin, allowlist) {
13444
13473
  return false;
13445
13474
  }
13446
13475
  }
13447
- app38.options("/event", (c) => {
13476
+ app39.options("/event", (c) => {
13448
13477
  const origin = getOrigin2(c);
13449
13478
  setCorsHeaders2(c, origin);
13450
13479
  return c.body(null, 204);
13451
13480
  });
13452
- app38.post("/event", async (c) => {
13481
+ app39.post("/event", async (c) => {
13453
13482
  const origin = getOrigin2(c);
13454
13483
  setCorsHeaders2(c, origin);
13455
13484
  const ua = c.req.header("user-agent") ?? "";
@@ -13654,7 +13683,7 @@ async function writeEvent(opts) {
13654
13683
  );
13655
13684
  }
13656
13685
  }
13657
- var visitor_event_default = app38;
13686
+ var visitor_event_default = app39;
13658
13687
 
13659
13688
  // app/lib/graph-health.ts
13660
13689
  var HOUR_MS = 60 * 60 * 1e3;
@@ -13901,7 +13930,7 @@ function broadcastAdminShutdown(reason) {
13901
13930
 
13902
13931
  // ../lib/entitlement/src/index.ts
13903
13932
  import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
13904
- import { existsSync as existsSync21, readFileSync as readFileSync19, statSync as statSync8 } from "fs";
13933
+ import { existsSync as existsSync20, readFileSync as readFileSync20, statSync as statSync9 } from "fs";
13905
13934
  import { resolve as resolve22 } from "path";
13906
13935
 
13907
13936
  // ../lib/entitlement/src/canonicalize.ts
@@ -13950,10 +13979,10 @@ function resolveEntitlement(brand, account) {
13950
13979
  return logResolved(implicitTrust(account), null);
13951
13980
  }
13952
13981
  const entitlementPath = resolve22(brand.configDir, "entitlement.json");
13953
- if (!existsSync21(entitlementPath)) {
13982
+ if (!existsSync20(entitlementPath)) {
13954
13983
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
13955
13984
  }
13956
- const stat8 = statSync8(entitlementPath);
13985
+ const stat8 = statSync9(entitlementPath);
13957
13986
  const key = memoKey(stat8.mtimeMs, account);
13958
13987
  if (memo && memo.key === key) {
13959
13988
  return memo.result;
@@ -13965,7 +13994,7 @@ function resolveEntitlement(brand, account) {
13965
13994
  function verifyAndResolve(brand, entitlementPath, account) {
13966
13995
  let pubkeyPem;
13967
13996
  try {
13968
- pubkeyPem = readFileSync19(pubkeyPath(brand), "utf-8");
13997
+ pubkeyPem = readFileSync20(pubkeyPath(brand), "utf-8");
13969
13998
  } catch (err) {
13970
13999
  return logResolved(anonymousFallback("pubkey-missing"), {
13971
14000
  reason: "pubkey-missing"
@@ -13979,7 +14008,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
13979
14008
  }
13980
14009
  let envelope;
13981
14010
  try {
13982
- envelope = JSON.parse(readFileSync19(entitlementPath, "utf-8"));
14011
+ envelope = JSON.parse(readFileSync20(entitlementPath, "utf-8"));
13983
14012
  } catch {
13984
14013
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
13985
14014
  }
@@ -14140,14 +14169,14 @@ function clientFrom(c) {
14140
14169
  );
14141
14170
  }
14142
14171
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
14143
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join15(PLATFORM_ROOT9, "config", "brand.json") : "";
14172
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join16(PLATFORM_ROOT9, "config", "brand.json") : "";
14144
14173
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
14145
- if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
14174
+ if (BRAND_JSON_PATH && !existsSync21(BRAND_JSON_PATH)) {
14146
14175
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
14147
14176
  }
14148
- if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
14177
+ if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
14149
14178
  try {
14150
- const parsed = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
14179
+ const parsed = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
14151
14180
  BRAND = { ...BRAND, ...parsed };
14152
14181
  } catch (err) {
14153
14182
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -14166,11 +14195,11 @@ var brandLoginOpts = {
14166
14195
  bodyFont: BRAND.defaultFonts?.body,
14167
14196
  logoContainsName: !!BRAND.logoContainsName
14168
14197
  };
14169
- var ALIAS_DOMAINS_PATH = join15(homedir2(), BRAND.configDir, "alias-domains.json");
14198
+ var ALIAS_DOMAINS_PATH = join16(homedir2(), BRAND.configDir, "alias-domains.json");
14170
14199
  function loadAliasDomains() {
14171
14200
  try {
14172
- if (!existsSync22(ALIAS_DOMAINS_PATH)) return null;
14173
- const parsed = JSON.parse(readFileSync20(ALIAS_DOMAINS_PATH, "utf-8"));
14201
+ if (!existsSync21(ALIAS_DOMAINS_PATH)) return null;
14202
+ const parsed = JSON.parse(readFileSync21(ALIAS_DOMAINS_PATH, "utf-8"));
14174
14203
  if (!Array.isArray(parsed)) {
14175
14204
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
14176
14205
  return null;
@@ -14194,9 +14223,9 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
14194
14223
  function isPublicHost(host) {
14195
14224
  return host.startsWith("public.") || aliasDomains.has(host);
14196
14225
  }
14197
- var app39 = new Hono();
14198
- app39.use("*", clientIpMiddleware);
14199
- app39.use("*", async (c, next) => {
14226
+ var app40 = new Hono();
14227
+ app40.use("*", clientIpMiddleware);
14228
+ app40.use("*", async (c, next) => {
14200
14229
  await next();
14201
14230
  c.header("X-Content-Type-Options", "nosniff");
14202
14231
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -14206,7 +14235,7 @@ app39.use("*", async (c, next) => {
14206
14235
  );
14207
14236
  });
14208
14237
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
14209
- app39.use("*", async (c, next) => {
14238
+ app40.use("*", async (c, next) => {
14210
14239
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
14211
14240
  await next();
14212
14241
  return;
@@ -14239,7 +14268,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
14239
14268
  "/sites/"
14240
14269
  ];
14241
14270
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
14242
- app39.use("*", async (c, next) => {
14271
+ app40.use("*", async (c, next) => {
14243
14272
  const host = (c.req.header("host") ?? "").split(":")[0];
14244
14273
  if (!isPublicHost(host)) {
14245
14274
  await next();
@@ -14279,7 +14308,7 @@ function resolveRemoteAuthOpts() {
14279
14308
  return brandLoginOpts;
14280
14309
  }
14281
14310
  var MAX_LOGIN_BODY = 8 * 1024;
14282
- app39.post("/__remote-auth/login", async (c) => {
14311
+ app40.post("/__remote-auth/login", async (c) => {
14283
14312
  const client = clientFrom(c);
14284
14313
  const clientIp = client.ip || "unknown";
14285
14314
  if (!requestIsTlsTerminated(c)) {
@@ -14324,7 +14353,7 @@ app39.post("/__remote-auth/login", async (c) => {
14324
14353
  }
14325
14354
  });
14326
14355
  });
14327
- app39.get("/__remote-auth/logout", (c) => {
14356
+ app40.get("/__remote-auth/logout", (c) => {
14328
14357
  const client = clientFrom(c);
14329
14358
  const clientIp = client.ip || "unknown";
14330
14359
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -14337,7 +14366,7 @@ app39.get("/__remote-auth/logout", (c) => {
14337
14366
  }
14338
14367
  });
14339
14368
  });
14340
- app39.post("/__remote-auth/change-password", async (c) => {
14369
+ app40.post("/__remote-auth/change-password", async (c) => {
14341
14370
  const client = clientFrom(c);
14342
14371
  const clientIp = client.ip || "unknown";
14343
14372
  const rateLimited = checkRateLimit(client);
@@ -14388,13 +14417,13 @@ app39.post("/__remote-auth/change-password", async (c) => {
14388
14417
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
14389
14418
  }
14390
14419
  });
14391
- app39.get("/__remote-auth/setup", (c) => {
14420
+ app40.get("/__remote-auth/setup", (c) => {
14392
14421
  if (isRemoteAuthConfigured()) {
14393
14422
  return c.redirect("/");
14394
14423
  }
14395
14424
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
14396
14425
  });
14397
- app39.post("/__remote-auth/set-initial-password", async (c) => {
14426
+ app40.post("/__remote-auth/set-initial-password", async (c) => {
14398
14427
  if (isRemoteAuthConfigured()) {
14399
14428
  return c.redirect("/");
14400
14429
  }
@@ -14432,10 +14461,10 @@ app39.post("/__remote-auth/set-initial-password", async (c) => {
14432
14461
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
14433
14462
  }
14434
14463
  });
14435
- app39.get("/api/remote-auth/status", (c) => {
14464
+ app40.get("/api/remote-auth/status", (c) => {
14436
14465
  return c.json({ configured: isRemoteAuthConfigured() });
14437
14466
  });
14438
- app39.post("/api/remote-auth/set-password", async (c) => {
14467
+ app40.post("/api/remote-auth/set-password", async (c) => {
14439
14468
  let body;
14440
14469
  try {
14441
14470
  body = await c.req.json();
@@ -14466,9 +14495,9 @@ app39.post("/api/remote-auth/set-password", async (c) => {
14466
14495
  return c.json({ error: "Failed to save password" }, 500);
14467
14496
  }
14468
14497
  });
14469
- app39.route("/api/_client-error", client_error_default);
14498
+ app40.route("/api/_client-error", client_error_default);
14470
14499
  console.log("[client-error-route] mounted");
14471
- app39.use("*", async (c, next) => {
14500
+ app40.use("*", async (c, next) => {
14472
14501
  const host = (c.req.header("host") ?? "").split(":")[0];
14473
14502
  const path2 = c.req.path;
14474
14503
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -14501,12 +14530,12 @@ app39.use("*", async (c, next) => {
14501
14530
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
14502
14531
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
14503
14532
  });
14504
- app39.route("/api/health", health_default);
14505
- app39.route("/api/chat", chat_default);
14506
- app39.route("/api/whatsapp", whatsapp_default);
14507
- app39.route("/api/onboarding", onboarding_default);
14508
- app39.route("/api/admin", admin_default);
14509
- app39.route("/api/access", access_default);
14533
+ app40.route("/api/health", health_default);
14534
+ app40.route("/api/chat", chat_default);
14535
+ app40.route("/api/whatsapp", whatsapp_default);
14536
+ app40.route("/api/onboarding", onboarding_default);
14537
+ app40.route("/api/admin", admin_default);
14538
+ app40.route("/api/access", access_default);
14510
14539
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
14511
14540
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
14512
14541
  var IMAGE_MIME = {
@@ -14518,7 +14547,7 @@ var IMAGE_MIME = {
14518
14547
  ".svg": "image/svg+xml",
14519
14548
  ".ico": "image/x-icon"
14520
14549
  };
14521
- app39.get("/agent-assets/:slug/:filename", (c) => {
14550
+ app40.get("/agent-assets/:slug/:filename", (c) => {
14522
14551
  const slug = c.req.param("slug");
14523
14552
  const filename = c.req.param("filename");
14524
14553
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -14540,20 +14569,20 @@ app39.get("/agent-assets/:slug/:filename", (c) => {
14540
14569
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
14541
14570
  return c.text("Forbidden", 403);
14542
14571
  }
14543
- if (!existsSync22(filePath)) {
14572
+ if (!existsSync21(filePath)) {
14544
14573
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
14545
14574
  return c.text("Not found", 404);
14546
14575
  }
14547
14576
  const ext = "." + filename.split(".").pop()?.toLowerCase();
14548
14577
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
14549
14578
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
14550
- const body = readFileSync20(filePath);
14579
+ const body = readFileSync21(filePath);
14551
14580
  return c.body(body, 200, {
14552
14581
  "Content-Type": contentType,
14553
14582
  "Cache-Control": "public, max-age=3600"
14554
14583
  });
14555
14584
  });
14556
- app39.get("/generated/:filename", (c) => {
14585
+ app40.get("/generated/:filename", (c) => {
14557
14586
  const filename = c.req.param("filename");
14558
14587
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
14559
14588
  console.error(`[generated] serve file=${filename} status=403`);
@@ -14570,29 +14599,29 @@ app39.get("/generated/:filename", (c) => {
14570
14599
  console.error(`[generated] serve file=${filename} status=403`);
14571
14600
  return c.text("Forbidden", 403);
14572
14601
  }
14573
- if (!existsSync22(filePath)) {
14602
+ if (!existsSync21(filePath)) {
14574
14603
  console.error(`[generated] serve file=${filename} status=404`);
14575
14604
  return c.text("Not found", 404);
14576
14605
  }
14577
14606
  const ext = "." + filename.split(".").pop()?.toLowerCase();
14578
14607
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
14579
14608
  console.log(`[generated] serve file=${filename} status=200`);
14580
- const body = readFileSync20(filePath);
14609
+ const body = readFileSync21(filePath);
14581
14610
  return c.body(body, 200, {
14582
14611
  "Content-Type": contentType,
14583
14612
  "Cache-Control": "public, max-age=86400"
14584
14613
  });
14585
14614
  });
14586
- app39.route("/sites", sites_default);
14587
- app39.route("/listings", listings_default);
14588
- app39.route("/v", visitor_event_default);
14589
- app39.route("/v", visitor_consent_default);
14615
+ app40.route("/sites", sites_default);
14616
+ app40.route("/listings", listings_default);
14617
+ app40.route("/v", visitor_event_default);
14618
+ app40.route("/v", visitor_consent_default);
14590
14619
  var htmlCache = /* @__PURE__ */ new Map();
14591
14620
  var brandLogoPath = "/brand/maxy-monochrome.png";
14592
14621
  var brandIconPath = "/brand/maxy-monochrome.png";
14593
- if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
14622
+ if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
14594
14623
  try {
14595
- const fullBrand = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
14624
+ const fullBrand = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
14596
14625
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
14597
14626
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
14598
14627
  } catch {
@@ -14609,9 +14638,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
14609
14638
  function readInstalledVersion() {
14610
14639
  try {
14611
14640
  if (!PLATFORM_ROOT9) return "unknown";
14612
- const versionFile = join15(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
14613
- if (!existsSync22(versionFile)) return "unknown";
14614
- const content = readFileSync20(versionFile, "utf-8").trim();
14641
+ const versionFile = join16(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
14642
+ if (!existsSync21(versionFile)) return "unknown";
14643
+ const content = readFileSync21(versionFile, "utf-8").trim();
14615
14644
  return content || "unknown";
14616
14645
  } catch {
14617
14646
  return "unknown";
@@ -14652,7 +14681,7 @@ var clientErrorReporterScript = `<script>
14652
14681
  function cachedHtml(file) {
14653
14682
  let html = htmlCache.get(file);
14654
14683
  if (!html) {
14655
- html = readFileSync20(resolve23(process.cwd(), "public", file), "utf-8");
14684
+ html = readFileSync21(resolve23(process.cwd(), "public", file), "utf-8");
14656
14685
  const productNameEsc = escapeHtml(BRAND.productName);
14657
14686
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
14658
14687
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -14668,26 +14697,26 @@ ${clientErrorReporterScript}
14668
14697
  }
14669
14698
  var brandedHtmlCache = /* @__PURE__ */ new Map();
14670
14699
  function loadBrandingCache(agentSlug) {
14671
- const configDir2 = join15(homedir2(), BRAND.configDir);
14700
+ const configDir2 = join16(homedir2(), BRAND.configDir);
14672
14701
  try {
14673
- const accountJsonPath = join15(configDir2, "account.json");
14674
- if (!existsSync22(accountJsonPath)) return null;
14675
- const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
14702
+ const accountJsonPath = join16(configDir2, "account.json");
14703
+ if (!existsSync21(accountJsonPath)) return null;
14704
+ const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
14676
14705
  const accountId = account.accountId;
14677
14706
  if (!accountId) return null;
14678
- const cachePath = join15(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
14679
- if (!existsSync22(cachePath)) return null;
14680
- return JSON.parse(readFileSync20(cachePath, "utf-8"));
14707
+ const cachePath = join16(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
14708
+ if (!existsSync21(cachePath)) return null;
14709
+ return JSON.parse(readFileSync21(cachePath, "utf-8"));
14681
14710
  } catch {
14682
14711
  return null;
14683
14712
  }
14684
14713
  }
14685
14714
  function resolveDefaultSlug() {
14686
14715
  try {
14687
- const configDir2 = join15(homedir2(), BRAND.configDir);
14688
- const accountJsonPath = join15(configDir2, "account.json");
14689
- if (!existsSync22(accountJsonPath)) return null;
14690
- const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
14716
+ const configDir2 = join16(homedir2(), BRAND.configDir);
14717
+ const accountJsonPath = join16(configDir2, "account.json");
14718
+ if (!existsSync21(accountJsonPath)) return null;
14719
+ const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
14691
14720
  return account.defaultAgent || null;
14692
14721
  } catch {
14693
14722
  return null;
@@ -14723,7 +14752,7 @@ function brandedPublicHtml(agentSlug) {
14723
14752
  function escapeHtml(s) {
14724
14753
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
14725
14754
  }
14726
- app39.get("/", (c) => {
14755
+ app40.get("/", (c) => {
14727
14756
  const host = (c.req.header("host") ?? "").split(":")[0];
14728
14757
  if (isPublicHost(host)) {
14729
14758
  const defaultSlug = resolveDefaultSlug();
@@ -14731,12 +14760,12 @@ app39.get("/", (c) => {
14731
14760
  }
14732
14761
  return c.html(cachedHtml("index.html"));
14733
14762
  });
14734
- app39.get("/public", (c) => {
14763
+ app40.get("/public", (c) => {
14735
14764
  const host = (c.req.header("host") ?? "").split(":")[0];
14736
14765
  if (isPublicHost(host)) return c.text("Not found", 404);
14737
14766
  return c.html(cachedHtml("public.html"));
14738
14767
  });
14739
- app39.get("/chat", (c) => {
14768
+ app40.get("/chat", (c) => {
14740
14769
  const host = (c.req.header("host") ?? "").split(":")[0];
14741
14770
  if (isPublicHost(host)) return c.text("Not found", 404);
14742
14771
  return c.html(cachedHtml("public.html"));
@@ -14755,12 +14784,12 @@ async function logViewerFetch(c, next) {
14755
14784
  duration_ms: Date.now() - start
14756
14785
  });
14757
14786
  }
14758
- app39.use("/vnc-viewer.html", logViewerFetch);
14759
- app39.use("/vnc-popout.html", logViewerFetch);
14760
- app39.get("/vnc-popout.html", (c) => {
14787
+ app40.use("/vnc-viewer.html", logViewerFetch);
14788
+ app40.use("/vnc-popout.html", logViewerFetch);
14789
+ app40.get("/vnc-popout.html", (c) => {
14761
14790
  let html = htmlCache.get("vnc-popout.html");
14762
14791
  if (!html) {
14763
- html = readFileSync20(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14792
+ html = readFileSync21(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14764
14793
  const name = escapeHtml(BRAND.productName);
14765
14794
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
14766
14795
  html = html.replace("</head>", ` ${brandScript}
@@ -14770,7 +14799,7 @@ app39.get("/vnc-popout.html", (c) => {
14770
14799
  }
14771
14800
  return c.html(html);
14772
14801
  });
14773
- app39.post("/api/vnc/client-event", async (c) => {
14802
+ app40.post("/api/vnc/client-event", async (c) => {
14774
14803
  let body;
14775
14804
  try {
14776
14805
  body = await c.req.json();
@@ -14791,25 +14820,25 @@ app39.post("/api/vnc/client-event", async (c) => {
14791
14820
  });
14792
14821
  return c.json({ ok: true });
14793
14822
  });
14794
- app39.get("/g/:slug", (c) => {
14823
+ app40.get("/g/:slug", (c) => {
14795
14824
  return c.html(brandedPublicHtml());
14796
14825
  });
14797
- app39.get("/graph", (c) => {
14826
+ app40.get("/graph", (c) => {
14798
14827
  const host = (c.req.header("host") ?? "").split(":")[0];
14799
14828
  if (isPublicHost(host)) return c.text("Not found", 404);
14800
14829
  return c.html(cachedHtml("graph.html"));
14801
14830
  });
14802
- app39.get("/sessions", (c) => {
14831
+ app40.get("/sessions", (c) => {
14803
14832
  const host = (c.req.header("host") ?? "").split(":")[0];
14804
14833
  if (isPublicHost(host)) return c.text("Not found", 404);
14805
14834
  return c.html(cachedHtml("sessions.html"));
14806
14835
  });
14807
- app39.get("/data", (c) => {
14836
+ app40.get("/data", (c) => {
14808
14837
  const host = (c.req.header("host") ?? "").split(":")[0];
14809
14838
  if (isPublicHost(host)) return c.text("Not found", 404);
14810
14839
  return c.html(cachedHtml("data.html"));
14811
14840
  });
14812
- app39.get("/:slug", async (c, next) => {
14841
+ app40.get("/:slug", async (c, next) => {
14813
14842
  const slug = c.req.param("slug");
14814
14843
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
14815
14844
  const branding = loadBrandingCache(slug);
@@ -14819,15 +14848,15 @@ app39.get("/:slug", async (c, next) => {
14819
14848
  await next();
14820
14849
  });
14821
14850
  if (brandFaviconPath !== "/favicon.ico") {
14822
- app39.get("/favicon.ico", (c) => {
14851
+ app40.get("/favicon.ico", (c) => {
14823
14852
  c.header("Cache-Control", "public, max-age=300");
14824
14853
  return c.redirect(brandFaviconPath, 302);
14825
14854
  });
14826
14855
  }
14827
- app39.use("/*", serveStatic({ root: "./public" }));
14856
+ app40.use("/*", serveStatic({ root: "./public" }));
14828
14857
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
14829
14858
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
14830
- var httpServer = serve({ fetch: app39.fetch, port, hostname });
14859
+ var httpServer = serve({ fetch: app40.fetch, port, hostname });
14831
14860
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
14832
14861
  {
14833
14862
  const loopHist = monitorEventLoopDelay({ resolution: 50 });
@@ -14863,7 +14892,7 @@ for (const m of SUBAPP_MANIFEST) {
14863
14892
  }
14864
14893
  try {
14865
14894
  const registered = [];
14866
- for (const r of app39.routes ?? []) {
14895
+ for (const r of app40.routes ?? []) {
14867
14896
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
14868
14897
  if (AGENT_SLUG_PATTERN.test(r.path)) {
14869
14898
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -14885,8 +14914,8 @@ try {
14885
14914
  }
14886
14915
  (async () => {
14887
14916
  try {
14888
- if (!existsSync22(USERS_FILE)) return;
14889
- const usersRaw = readFileSync20(USERS_FILE, "utf-8").trim();
14917
+ if (!existsSync21(USERS_FILE)) return;
14918
+ const usersRaw = readFileSync21(USERS_FILE, "utf-8").trim();
14890
14919
  if (!usersRaw) return;
14891
14920
  const users = JSON.parse(usersRaw);
14892
14921
  const userId = users[0]?.userId;
@@ -14981,7 +15010,7 @@ if (bootAccountConfig?.whatsapp) {
14981
15010
  }
14982
15011
  init({
14983
15012
  configDir: configDirForWhatsApp,
14984
- platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join15(__dirname, "..")),
15013
+ platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join16(__dirname, "..")),
14985
15014
  accountConfig: bootAccountConfig,
14986
15015
  onMessage: async (msg) => {
14987
15016
  if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {