@rubytech/create-maxy-code 0.1.35 → 0.1.37

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 (125) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/PLUGIN.md +12 -0
  3. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +109 -0
  4. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +114 -0
  5. package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +1 -1
  6. package/payload/platform/plugins/contacts/PLUGIN.md +11 -0
  7. package/payload/platform/plugins/docs/references/internals.md +10 -0
  8. package/payload/platform/plugins/docs/references/platform.md +11 -4
  9. package/payload/platform/plugins/email/PLUGIN.md +11 -0
  10. package/payload/platform/plugins/linkedin-import/.claude-plugin/plugin.json +1 -1
  11. package/payload/platform/plugins/linkedin-import/PLUGIN.md +5 -5
  12. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +3 -1
  13. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +2 -2
  14. package/payload/platform/plugins/memory/PLUGIN.md +11 -0
  15. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -0
  16. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -0
  17. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +6 -4
  18. package/payload/platform/plugins/outlook/PLUGIN.md +11 -0
  19. package/payload/platform/plugins/replicate/PLUGIN.md +11 -0
  20. package/payload/platform/plugins/scheduling/PLUGIN.md +11 -0
  21. package/payload/platform/plugins/tasks/PLUGIN.md +11 -0
  22. package/payload/platform/plugins/telegram/PLUGIN.md +11 -0
  23. package/payload/platform/plugins/waitlist/PLUGIN.md +11 -0
  24. package/payload/platform/plugins/whatsapp/PLUGIN.md +11 -0
  25. package/payload/platform/plugins/workflows/PLUGIN.md +11 -0
  26. package/payload/platform/scripts/seed-neo4j.sh +14 -0
  27. package/payload/platform/scripts/verify-skill-tool-surface.sh +5 -3
  28. package/payload/platform/services/claude-session-manager/dist/config.d.ts +0 -5
  29. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/config.js +16 -6
  31. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  32. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -5
  33. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/http-server.js +109 -139
  35. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/index.js +63 -4
  37. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  38. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +47 -61
  39. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  40. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +191 -131
  41. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  42. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +43 -37
  43. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
  44. package/payload/platform/services/claude-session-manager/dist/session-store.js +72 -61
  45. package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
  46. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +34 -4
  47. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/tool-surface.js +125 -27
  49. package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -1
  50. package/payload/platform/templates/agents/admin/IDENTITY.md +9 -18
  51. package/payload/platform/templates/specialists/agents/database-operator.md +27 -70
  52. package/payload/platform/templates/specialists/agents/librarian.md +55 -0
  53. package/payload/server/public/assets/{Checkbox-8mOR8-gV.js → Checkbox-DAki3vDW.js} +1 -1
  54. package/payload/server/public/assets/{admin-CK4V-B9A.js → admin-CyAZtsYZ.js} +1 -1
  55. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-2DgPtOot.js → architectureDiagram-Q4EWVU46-C-hla3Ip.js} +1 -1
  56. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BilycXVZ.js → blockDiagram-DXYQGD6D-CbzjtNs3.js} +1 -1
  57. package/payload/server/public/assets/{brand-1_DraUIv.css → brand-Cun0PBrA.css} +1 -1
  58. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CGiIFO5U.js → c4Diagram-AHTNJAMY-B87UblA0.js} +1 -1
  59. package/payload/server/public/assets/channel-CTNo72W7.js +1 -0
  60. package/payload/server/public/assets/{chunk-336JU56O-DxTg1h50.js → chunk-336JU56O-2a2pVlSg.js} +2 -2
  61. package/payload/server/public/assets/{chunk-426QAEUC-DkGPjs0P.js → chunk-426QAEUC-j9NOD8_a.js} +1 -1
  62. package/payload/server/public/assets/{chunk-4TB4RGXK-D2JaxD6r.js → chunk-4TB4RGXK-Cs872xAq.js} +1 -1
  63. package/payload/server/public/assets/{chunk-5FUZZQ4R-Do3pbAGo.js → chunk-5FUZZQ4R-BnDFbZ_I.js} +1 -1
  64. package/payload/server/public/assets/{chunk-5PVQY5BW-np5moZSl.js → chunk-5PVQY5BW-Bu5B3Hyf.js} +1 -1
  65. package/payload/server/public/assets/{chunk-EDXVE4YY-BUFLWwRP.js → chunk-EDXVE4YY-B96Fw4FF.js} +1 -1
  66. package/payload/server/public/assets/{chunk-ENJZ2VHE-BE7Gt41s.js → chunk-ENJZ2VHE-CcGrGQim.js} +1 -1
  67. package/payload/server/public/assets/{chunk-ICPOFSXX-gOBkROMP.js → chunk-ICPOFSXX-ZRvcI4Ai.js} +1 -1
  68. package/payload/server/public/assets/{chunk-OYMX7WX6-DR-BkNZa.js → chunk-OYMX7WX6-B6RI9Fbf.js} +1 -1
  69. package/payload/server/public/assets/{chunk-U2HBQHQK-qLp-uSVE.js → chunk-U2HBQHQK-BYGHVYyo.js} +1 -1
  70. package/payload/server/public/assets/{chunk-X2U36JSP-DQiKti0J.js → chunk-X2U36JSP-rwNs-gTO.js} +1 -1
  71. package/payload/server/public/assets/{chunk-YZCP3GAM-Cd0JhpTo.js → chunk-YZCP3GAM-jPttJRap.js} +1 -1
  72. package/payload/server/public/assets/{chunk-ZZ45TVLE-8u01H3Hy.js → chunk-ZZ45TVLE-DLykWOT5.js} +1 -1
  73. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BaV5nDmT.js +1 -0
  74. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DOKlCKjY.js +1 -0
  75. package/payload/server/public/assets/clone-sQSwlSln.js +1 -0
  76. package/payload/server/public/assets/{dagre-KV5264BT-BBF_zxbi.js → dagre-KV5264BT-C6wSzHX2.js} +1 -1
  77. package/payload/server/public/assets/{dagre-BfVsOYOv.js → dagre-jnQDnF-5.js} +1 -1
  78. package/payload/server/public/assets/data-DbkuXcPb.js +1 -0
  79. package/payload/server/public/assets/{device-url-actions-CJBD3ecO.js → device-url-actions-y1tXNDZx.js} +1 -1
  80. package/payload/server/public/assets/{diagram-5BDNPKRD-BFHk2a7t.js → diagram-5BDNPKRD-N3X-n90h.js} +1 -1
  81. package/payload/server/public/assets/{diagram-G4DWMVQ6-Be3_qYl2.js → diagram-G4DWMVQ6-vfmbzdPd.js} +1 -1
  82. package/payload/server/public/assets/{diagram-MMDJMWI5-B3r4XVcu.js → diagram-MMDJMWI5-BETmPx_w.js} +1 -1
  83. package/payload/server/public/assets/{diagram-TYMM5635-BW5EIT4D.js → diagram-TYMM5635-BSUGM4wG.js} +1 -1
  84. package/payload/server/public/assets/{erDiagram-SMLLAGMA-DTu4_1Kb.js → erDiagram-SMLLAGMA-CWZ9OwMb.js} +1 -1
  85. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CadrjLcA.js → flowDiagram-DWJPFMVM-BpQOQS1a.js} +1 -1
  86. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-Cn0npD0L.js → ganttDiagram-T4ZO3ILL-Dc59igCS.js} +1 -1
  87. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CK3gG5Qm.js → gitGraphDiagram-UUTBAWPF-D6lXg3zl.js} +1 -1
  88. package/payload/server/public/assets/graph-CC5_6-dg.js +1 -0
  89. package/payload/server/public/assets/{graph-labels-CPzF6Gbk.js → graph-labels-DFyNH0jb.js} +1 -1
  90. package/payload/server/public/assets/{graphlib-DFIOO59N.js → graphlib-yG7kH8Fr.js} +1 -1
  91. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BohUsXnN.js → infoDiagram-42DDH7IO-TS9Pv8Os.js} +1 -1
  92. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-tjmA4BU8.js → ishikawaDiagram-UXIWVN3A-BJiJJTq6.js} +1 -1
  93. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DzBlFESM.js → journeyDiagram-VCZTEJTY-C7PW4fmw.js} +1 -1
  94. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BTw9BxK8.js → kanban-definition-6JOO6SKY-BEk21ciD.js} +1 -1
  95. package/payload/server/public/assets/{line-BYPL6wAj.js → line-DusyVWDE.js} +1 -1
  96. package/payload/server/public/assets/{mermaid-parser.core-Dmu4fWCS.js → mermaid-parser.core-DeeojQSb.js} +1 -1
  97. package/payload/server/public/assets/{mermaid.core-Z9vvieC2.js → mermaid.core-p65Lo7Sj.js} +3 -3
  98. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BccAnfJ4.js → mindmap-definition-QFDTVHPH-B0jxFxdS.js} +1 -1
  99. package/payload/server/public/assets/{page-CBTlFm3b.js → page-BeYGnDzI.js} +1 -1
  100. package/payload/server/public/assets/{page-CDrsNrDO.js → page-x5khmfRx.js} +1 -1
  101. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CZwxH1nJ.js → pieDiagram-DEJITSTG-DJ5GKYt6.js} +1 -1
  102. package/payload/server/public/assets/{public-MKWxjwiF.js → public-cnoUs7vq.js} +3 -3
  103. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BWT4DItX.js → quadrantDiagram-34T5L4WZ-BV7R-kwV.js} +1 -1
  104. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CHYkWUEy.js → requirementDiagram-MS252O5E-DRiLzlGN.js} +1 -1
  105. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-km7p45Ng.js → sankeyDiagram-XADWPNL6-C5-6_cCI.js} +1 -1
  106. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BT1C0Dw-.js → sequenceDiagram-FGHM5R23-5FXm_VYM.js} +1 -1
  107. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-hibC19DY.js → stateDiagram-FHFEXIEX-FCQTaGqV.js} +1 -1
  108. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdpPhdqg.js +1 -0
  109. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Cnm86NfE.js → timeline-definition-GMOUNBTQ-tvtq62ef.js} +1 -1
  110. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-ByjQPLzS.js → vennDiagram-DHZGUBPP-Dk-k7CE4.js} +1 -1
  111. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CMVrWw7l.js → wardleyDiagram-NUSXRM2D-CZSrqniY.js} +1 -1
  112. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-Mpc1u3FV.js → xychartDiagram-5P7HB3ND-CpGLpk7Q.js} +1 -1
  113. package/payload/server/public/data.html +5 -5
  114. package/payload/server/public/graph.html +6 -6
  115. package/payload/server/public/index.html +8 -8
  116. package/payload/server/public/public.html +5 -5
  117. package/payload/server/server.js +128 -106
  118. package/payload/server/public/assets/channel-DYpIZW3Q.js +0 -1
  119. package/payload/server/public/assets/classDiagram-6PBFFD2Q-nkfy9gg7.js +0 -1
  120. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B-pMmeCC.js +0 -1
  121. package/payload/server/public/assets/clone-jiTzIER6.js +0 -1
  122. package/payload/server/public/assets/data-BIOaDoqe.js +0 -1
  123. package/payload/server/public/assets/graph-ClfU7t1k.js +0 -1
  124. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-MuJZxjmU.js +0 -1
  125. /package/payload/server/public/assets/{brand-CENN2zdq.js → brand-lj7EhWRg.js} +0 -0
@@ -595,8 +595,8 @@ var serveStatic = (options = { root: "" }) => {
595
595
  };
596
596
 
597
597
  // server/index.ts
598
- import { readFileSync as readFileSync19, existsSync as existsSync22, watchFile } from "fs";
599
- import { resolve as resolve22, join as join12, basename as basename5 } from "path";
598
+ import { readFileSync as readFileSync20, existsSync as existsSync22, watchFile } from "fs";
599
+ import { resolve as resolve23, join as join12, basename as basename5 } from "path";
600
600
  import { homedir as homedir4 } from "os";
601
601
 
602
602
  // app/lib/agent-slug-pattern.ts
@@ -1416,7 +1416,7 @@ var credsSaveQueue = Promise.resolve();
1416
1416
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1417
1417
  console.error(`${TAG3} draining credential save queue\u2026`);
1418
1418
  const timer2 = new Promise(
1419
- (resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
1419
+ (resolve24) => setTimeout(() => resolve24("timeout"), timeoutMs)
1420
1420
  );
1421
1421
  const result = await Promise.race([
1422
1422
  credsSaveQueue.then(() => "drained"),
@@ -1544,11 +1544,11 @@ async function createWaSocket(opts) {
1544
1544
  return sock;
1545
1545
  }
1546
1546
  async function waitForConnection(sock) {
1547
- return new Promise((resolve23, reject) => {
1547
+ return new Promise((resolve24, reject) => {
1548
1548
  const handler = (update) => {
1549
1549
  if (update.connection === "open") {
1550
1550
  sock.ev.off("connection.update", handler);
1551
- resolve23();
1551
+ resolve24();
1552
1552
  }
1553
1553
  if (update.connection === "close") {
1554
1554
  sock.ev.off("connection.update", handler);
@@ -1662,14 +1662,14 @@ ${inspected}`;
1662
1662
  return inspect2(err, INSPECT_OPTS2);
1663
1663
  }
1664
1664
  function withTimeout(label, promise, timeoutMs) {
1665
- return new Promise((resolve23, reject) => {
1665
+ return new Promise((resolve24, reject) => {
1666
1666
  const timer2 = setTimeout(() => {
1667
1667
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1668
1668
  }, timeoutMs);
1669
1669
  promise.then(
1670
1670
  (value) => {
1671
1671
  clearTimeout(timer2);
1672
- resolve23(value);
1672
+ resolve24(value);
1673
1673
  },
1674
1674
  (err) => {
1675
1675
  clearTimeout(timer2);
@@ -2204,8 +2204,8 @@ async function persistWhatsAppMessage(input) {
2204
2204
  const { givenName, familyName } = splitName(input.pushName);
2205
2205
  const prev = sessionWriteLocks.get(input.cacheKey);
2206
2206
  let release;
2207
- const mine = new Promise((resolve23) => {
2208
- release = resolve23;
2207
+ const mine = new Promise((resolve24) => {
2208
+ release = resolve24;
2209
2209
  });
2210
2210
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2211
2211
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3242,11 +3242,11 @@ async function connectWithReconnect(conn) {
3242
3242
  console.error(
3243
3243
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3244
3244
  );
3245
- await new Promise((resolve23) => {
3246
- const timer2 = setTimeout(resolve23, delay);
3245
+ await new Promise((resolve24) => {
3246
+ const timer2 = setTimeout(resolve24, delay);
3247
3247
  conn.abortController.signal.addEventListener("abort", () => {
3248
3248
  clearTimeout(timer2);
3249
- resolve23();
3249
+ resolve24();
3250
3250
  }, { once: true });
3251
3251
  });
3252
3252
  }
@@ -3254,16 +3254,16 @@ async function connectWithReconnect(conn) {
3254
3254
  }
3255
3255
  }
3256
3256
  function waitForDisconnectEvent(conn) {
3257
- return new Promise((resolve23) => {
3257
+ return new Promise((resolve24) => {
3258
3258
  if (!conn.sock) {
3259
- resolve23();
3259
+ resolve24();
3260
3260
  return;
3261
3261
  }
3262
3262
  const sock = conn.sock;
3263
3263
  const handler = (update) => {
3264
3264
  if (update.connection === "close") {
3265
3265
  sock.ev.off("connection.update", handler);
3266
- resolve23();
3266
+ resolve24();
3267
3267
  }
3268
3268
  };
3269
3269
  sock.ev.on("connection.update", handler);
@@ -3525,8 +3525,8 @@ async function handleInboundMessage(conn, msg) {
3525
3525
  const conversationKey = isGroup ? remoteJid : senderPhone;
3526
3526
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
3527
3527
  let resolvePending;
3528
- const sttPending = new Promise((resolve23) => {
3529
- resolvePending = resolve23;
3528
+ const sttPending = new Promise((resolve24) => {
3529
+ resolvePending = resolve24;
3530
3530
  });
3531
3531
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
3532
3532
  try {
@@ -3930,20 +3930,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
3930
3930
 
3931
3931
  // server/routes/health.ts
3932
3932
  function checkPort(port2, timeoutMs = 500) {
3933
- return new Promise((resolve23) => {
3933
+ return new Promise((resolve24) => {
3934
3934
  const socket = createConnection2(port2, "127.0.0.1");
3935
3935
  socket.setTimeout(timeoutMs);
3936
3936
  socket.once("connect", () => {
3937
3937
  socket.destroy();
3938
- resolve23(true);
3938
+ resolve24(true);
3939
3939
  });
3940
3940
  socket.once("error", () => {
3941
3941
  socket.destroy();
3942
- resolve23(false);
3942
+ resolve24(false);
3943
3943
  });
3944
3944
  socket.once("timeout", () => {
3945
3945
  socket.destroy();
3946
- resolve23(false);
3946
+ resolve24(false);
3947
3947
  });
3948
3948
  });
3949
3949
  }
@@ -5019,12 +5019,12 @@ async function dispatchOnce(input) {
5019
5019
  });
5020
5020
  if (!entry) return { error: "spawn-failed" };
5021
5021
  entry.lastInboundAt = Date.now();
5022
- let resolve23;
5022
+ let resolve24;
5023
5023
  const turnPromise = new Promise((r) => {
5024
- resolve23 = r;
5024
+ resolve24 = r;
5025
5025
  });
5026
5026
  const listener = (text) => {
5027
- resolve23(text);
5027
+ resolve24(text);
5028
5028
  };
5029
5029
  entry.subscribers.add(listener);
5030
5030
  const writeOk = await writeInput(entry, input.text);
@@ -5387,8 +5387,8 @@ async function startLogin(opts) {
5387
5387
  resetActiveLogin(accountId);
5388
5388
  let resolveQr = null;
5389
5389
  let rejectQr = null;
5390
- const qrPromise = new Promise((resolve23, reject) => {
5391
- resolveQr = resolve23;
5390
+ const qrPromise = new Promise((resolve24, reject) => {
5391
+ resolveQr = resolve24;
5392
5392
  rejectQr = reject;
5393
5393
  });
5394
5394
  const qrTimer = setTimeout(
@@ -7957,6 +7957,23 @@ function computeDormantPlugins(accountId) {
7957
7957
  }
7958
7958
 
7959
7959
  // server/routes/admin/claude-sessions.ts
7960
+ import { readFileSync as readFileSync14 } from "fs";
7961
+ import { resolve as resolve12 } from "path";
7962
+ function resolveTunnelUrl() {
7963
+ const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
7964
+ let brand;
7965
+ try {
7966
+ brand = JSON.parse(readFileSync14(resolve12(platformRoot, "config", "brand.json"), "utf-8"));
7967
+ } catch {
7968
+ return null;
7969
+ }
7970
+ const hostname2 = typeof brand.hostname === "string" && brand.hostname ? brand.hostname : null;
7971
+ const configDir2 = typeof brand.configDir === "string" && brand.configDir ? brand.configDir : null;
7972
+ if (!hostname2 || !configDir2) return null;
7973
+ const state = readTunnelState(configDir2);
7974
+ if (!state) return null;
7975
+ return `https://${hostname2}.${state.domain}`;
7976
+ }
7960
7977
  var TAG18 = "[claude-session-manager:wrapper]";
7961
7978
  function managerBase2() {
7962
7979
  const port2 = Number(process.env.CLAUDE_SESSION_MANAGER_PORT ?? "19400");
@@ -7990,6 +8007,8 @@ app15.post("/", async (c) => {
7990
8007
  const dormantStart = Date.now();
7991
8008
  const dormantPlugins = computeDormantPlugins(senderId);
7992
8009
  console.log(`${TAG18} dormant-plugins-computed count=${Array.isArray(dormantPlugins) ? dormantPlugins.length : 0} ms=${Date.now() - dormantStart}`);
8010
+ const tunnelUrl = resolveTunnelUrl();
8011
+ console.log(`${TAG18} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
7993
8012
  const forwardStart = Date.now();
7994
8013
  const upstreamPayload = JSON.stringify({
7995
8014
  senderId,
@@ -7997,7 +8016,8 @@ app15.post("/", async (c) => {
7997
8016
  channel,
7998
8017
  permissionMode,
7999
8018
  aboutOwner,
8000
- dormantPlugins
8019
+ dormantPlugins,
8020
+ tunnelUrl
8001
8021
  });
8002
8022
  console.log(`${TAG18} forward-spawn-start managerBase=${managerBase2()} bytes=${upstreamPayload.length}`);
8003
8023
  const upstream = await fetch(`${managerBase2()}/spawn`, {
@@ -8058,6 +8078,7 @@ app15.post("/resume", async (c) => {
8058
8078
  const channel = typeof body.channel === "string" ? body.channel : "browser";
8059
8079
  const aboutOwner = await resolveOwnerProfileBlock(senderId, userId);
8060
8080
  const dormantPlugins = computeDormantPlugins(senderId);
8081
+ const tunnelUrl = resolveTunnelUrl();
8061
8082
  const upstream = await fetch(`${managerBase2()}/resume`, {
8062
8083
  method: "POST",
8063
8084
  headers: { "content-type": "application/json" },
@@ -8067,7 +8088,8 @@ app15.post("/resume", async (c) => {
8067
8088
  channel,
8068
8089
  claudeSessionId: body.claudeSessionId,
8069
8090
  aboutOwner,
8070
- dormantPlugins
8091
+ dormantPlugins,
8092
+ tunnelUrl
8071
8093
  })
8072
8094
  }).catch((err) => {
8073
8095
  console.error(`${TAG18} fetch-failed op=resume message=${err instanceof Error ? err.message : String(err)}`);
@@ -8404,8 +8426,8 @@ var events_default = app19;
8404
8426
 
8405
8427
  // server/routes/admin/cloudflare.ts
8406
8428
  import { homedir as homedir3 } from "os";
8407
- import { resolve as resolve13 } from "path";
8408
- import { readFileSync as readFileSync15 } from "fs";
8429
+ import { resolve as resolve14 } from "path";
8430
+ import { readFileSync as readFileSync16 } from "fs";
8409
8431
 
8410
8432
  // app/lib/dns-label.ts
8411
8433
  var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
@@ -8421,14 +8443,14 @@ function isValidDomain(value) {
8421
8443
  }
8422
8444
 
8423
8445
  // app/lib/alias-domains.ts
8424
- import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
8446
+ import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
8425
8447
  import { dirname as dirname2 } from "path";
8426
- import { resolve as resolve12 } from "path";
8427
- var ALIAS_DOMAINS_PATH = resolve12(MAXY_DIR, "alias-domains.json");
8448
+ import { resolve as resolve13 } from "path";
8449
+ var ALIAS_DOMAINS_PATH = resolve13(MAXY_DIR, "alias-domains.json");
8428
8450
  function readExisting() {
8429
8451
  if (!existsSync15(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
8430
8452
  try {
8431
- const parsed = JSON.parse(readFileSync14(ALIAS_DOMAINS_PATH, "utf-8"));
8453
+ const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH, "utf-8"));
8432
8454
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
8433
8455
  return new Set(parsed.filter((h) => typeof h === "string"));
8434
8456
  } catch {
@@ -8695,7 +8717,7 @@ var CLOUDFLARE_SETUP_FORM_SCHEMA = {
8695
8717
 
8696
8718
  // server/routes/admin/cloudflare.ts
8697
8719
  function cloudflareStreamLogPath(accountId, correlationId) {
8698
- return resolve13(ACCOUNTS_DIR, accountId, "cloudflare-stream-logs", `${correlationId}.log`);
8720
+ return resolve14(ACCOUNTS_DIR, accountId, "cloudflare-stream-logs", `${correlationId}.log`);
8699
8721
  }
8700
8722
  var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
8701
8723
  var DOMAINS_TIMEOUT_MS = 40 * 1e3;
@@ -8725,10 +8747,10 @@ function readDiscoveryResults(accountId) {
8725
8747
  return { tunnels: entry.tunnels, domains: entry.domains };
8726
8748
  }
8727
8749
  function loadBrandInfo() {
8728
- const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "..");
8729
- const brandPath = resolve13(platformRoot, "config", "brand.json");
8750
+ const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
8751
+ const brandPath = resolve14(platformRoot, "config", "brand.json");
8730
8752
  try {
8731
- const parsed = JSON.parse(readFileSync15(brandPath, "utf-8"));
8753
+ const parsed = JSON.parse(readFileSync16(brandPath, "utf-8"));
8732
8754
  const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
8733
8755
  const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
8734
8756
  return { hostname: hostname2, configDir: configDir2 };
@@ -8856,7 +8878,7 @@ app20.get("/domains", requireAdminSession, async (c) => {
8856
8878
  streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
8857
8879
  log(`phase=stream-log-resolved path=${streamLogPath}`);
8858
8880
  const brand = loadBrandInfo();
8859
- const scriptPath = resolve13(homedir3(), "list-cf-domains.sh");
8881
+ const scriptPath = resolve14(homedir3(), "list-cf-domains.sh");
8860
8882
  const result = await runFormSpawn({
8861
8883
  scriptPath,
8862
8884
  args: [brand.hostname],
@@ -8947,7 +8969,7 @@ app20.get("/tunnels", requireAdminSession, async (c) => {
8947
8969
  if (!accountId) return err("session", "No account bound to session \u2014 refresh chat.");
8948
8970
  if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
8949
8971
  streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
8950
- const certPath = resolve13(homedir3(), brand.configDir, "cloudflared", "cert.pem");
8972
+ const certPath = resolve14(homedir3(), brand.configDir, "cloudflared", "cert.pem");
8951
8973
  const { existsSync: existsSync23 } = await import("fs");
8952
8974
  if (!existsSync23(certPath)) {
8953
8975
  return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
@@ -9273,17 +9295,17 @@ var cloudflare_default = app20;
9273
9295
  import { createReadStream as createReadStream3 } from "fs";
9274
9296
  import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
9275
9297
  import { realpathSync as realpathSync4 } from "fs";
9276
- import { basename as basename4, dirname as dirname4, join as join10, resolve as resolve15, sep as sep3 } from "path";
9298
+ import { basename as basename4, dirname as dirname4, join as join10, resolve as resolve16, sep as sep3 } from "path";
9277
9299
  import { Readable as Readable2 } from "stream";
9278
9300
 
9279
9301
  // app/lib/data-path.ts
9280
9302
  import { realpathSync as realpathSync3 } from "fs";
9281
- import { resolve as resolve14, normalize, sep as sep2, relative } from "path";
9282
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "../platform");
9283
- var DATA_ROOT = resolve14(PLATFORM_ROOT5, "..", "data");
9303
+ import { resolve as resolve15, normalize, sep as sep2, relative } from "path";
9304
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve15(process.cwd(), "../platform");
9305
+ var DATA_ROOT = resolve15(PLATFORM_ROOT5, "..", "data");
9284
9306
  function resolveDataPath(raw) {
9285
9307
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
9286
- const absolute = resolve14(DATA_ROOT, cleaned);
9308
+ const absolute = resolve15(DATA_ROOT, cleaned);
9287
9309
  let dataRootReal;
9288
9310
  try {
9289
9311
  dataRootReal = realpathSync3(DATA_ROOT);
@@ -9641,7 +9663,7 @@ async function readMeta(absDir, baseName) {
9641
9663
  }
9642
9664
  async function readAccountNames() {
9643
9665
  const map = /* @__PURE__ */ new Map();
9644
- const accountsDir = resolve15(DATA_ROOT, "accounts");
9666
+ const accountsDir = resolve16(DATA_ROOT, "accounts");
9645
9667
  let names;
9646
9668
  try {
9647
9669
  names = await readdir2(accountsDir);
@@ -9650,7 +9672,7 @@ async function readAccountNames() {
9650
9672
  }
9651
9673
  for (const name of names) {
9652
9674
  if (!UUID_RE4.test(name)) continue;
9653
- const configPath2 = resolve15(accountsDir, name, "account.json");
9675
+ const configPath2 = resolve16(accountsDir, name, "account.json");
9654
9676
  try {
9655
9677
  const raw = await readFile4(configPath2, "utf8");
9656
9678
  const parsed = JSON.parse(raw);
@@ -9841,8 +9863,8 @@ app21.post("/upload", requireAdminSession, async (c) => {
9841
9863
  }
9842
9864
  const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
9843
9865
  const finalName = `${Date.now()}-${safeName}`;
9844
- const destDir = resolve15(DATA_ROOT, "uploads", accountId);
9845
- const destPath = resolve15(destDir, finalName);
9866
+ const destDir = resolve16(DATA_ROOT, "uploads", accountId);
9867
+ const destPath = resolve16(destDir, finalName);
9846
9868
  try {
9847
9869
  await mkdir3(destDir, { recursive: true });
9848
9870
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11561,7 +11583,7 @@ var file_attach_default = app28;
11561
11583
  // server/routes/admin/sidebar-artefacts.ts
11562
11584
  import neo4j2 from "neo4j-driver";
11563
11585
  import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
11564
- import { resolve as resolve16, relative as relative2, isAbsolute } from "path";
11586
+ import { resolve as resolve17, relative as relative2, isAbsolute } from "path";
11565
11587
  import { existsSync as existsSync16 } from "fs";
11566
11588
  var LIMIT = 50;
11567
11589
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
@@ -11578,7 +11600,7 @@ app29.get("/", requireAdminSession, async (c) => {
11578
11600
  if (docs === null) {
11579
11601
  return c.json({ error: "Failed to load artefacts" }, 500);
11580
11602
  }
11581
- const accountDir = resolve16(ACCOUNTS_DIR, accountId);
11603
+ const accountDir = resolve17(ACCOUNTS_DIR, accountId);
11582
11604
  const agents = await fetchAgentTemplateRows(accountDir);
11583
11605
  const artefacts = [...docs, ...agents].sort(
11584
11606
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -11641,8 +11663,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11641
11663
  logSkip(displayName, "non-text-mime", mimeType);
11642
11664
  return { content: "", skipReason: "non-text-mime" };
11643
11665
  }
11644
- const accountDir = resolve16(ATTACHMENTS_ROOT, accountId);
11645
- const dir = resolve16(accountDir, attachmentId);
11666
+ const accountDir = resolve17(ATTACHMENTS_ROOT, accountId);
11667
+ const dir = resolve17(accountDir, attachmentId);
11646
11668
  try {
11647
11669
  validateFilePathInAccount(dir, accountDir);
11648
11670
  } catch {
@@ -11656,7 +11678,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11656
11678
  logSkip(displayName, "missing-on-disk", mimeType);
11657
11679
  return { content: "", skipReason: "missing-on-disk" };
11658
11680
  }
11659
- return { content: await readFile5(resolve16(dir, dataFile), "utf-8"), skipReason: null };
11681
+ return { content: await readFile5(resolve17(dir, dataFile), "utf-8"), skipReason: null };
11660
11682
  } catch (err) {
11661
11683
  const message = err instanceof Error ? err.message : String(err);
11662
11684
  console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
@@ -11672,8 +11694,8 @@ function logSkip(name, reason, mimeType) {
11672
11694
  async function fetchAgentTemplateRows(accountDir) {
11673
11695
  const rows = [];
11674
11696
  for (const filename of ADMIN_AGENT_FILES) {
11675
- const overridePath = resolve16(accountDir, "agents", "admin", filename);
11676
- const bundledPath = resolve16(PLATFORM_ROOT, "templates", "agents", "admin", filename);
11697
+ const overridePath = resolve17(accountDir, "agents", "admin", filename);
11698
+ const bundledPath = resolve17(PLATFORM_ROOT, "templates", "agents", "admin", filename);
11677
11699
  const labelStem = filename.replace(/\.md$/, "");
11678
11700
  const row = await readAgentTemplateRow({
11679
11701
  id: `agent-template:admin:${filename}`,
@@ -11687,12 +11709,12 @@ async function fetchAgentTemplateRows(accountDir) {
11687
11709
  });
11688
11710
  if (row) rows.push(row);
11689
11711
  }
11690
- const overrideDir = resolve16(accountDir, "specialists", "agents");
11691
- const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
11712
+ const overrideDir = resolve17(accountDir, "specialists", "agents");
11713
+ const bundledDir = resolve17(PLATFORM_ROOT, "templates", "specialists", "agents");
11692
11714
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
11693
11715
  for (const filename of specialistNames) {
11694
- const overridePath = resolve16(overrideDir, filename);
11695
- const bundledPath = resolve16(bundledDir, filename);
11716
+ const overridePath = resolve17(overrideDir, filename);
11717
+ const bundledPath = resolve17(bundledDir, filename);
11696
11718
  const row = await readAgentTemplateRow({
11697
11719
  id: `agent-template:specialist:${filename}`,
11698
11720
  displayName: filename.replace(/\.md$/, ""),
@@ -11777,7 +11799,7 @@ var sidebar_artefacts_default = app29;
11777
11799
 
11778
11800
  // server/routes/admin/sidebar-artefact-save.ts
11779
11801
  import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11780
- import { resolve as resolve17 } from "path";
11802
+ import { resolve as resolve18 } from "path";
11781
11803
  import { existsSync as existsSync17 } from "fs";
11782
11804
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
11783
11805
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
@@ -11790,7 +11812,7 @@ app30.post("/", requireAdminSession, async (c) => {
11790
11812
  if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
11791
11813
  return c.json({ error: "id and content required" }, 400);
11792
11814
  }
11793
- const accountDir = resolve17(ACCOUNTS_DIR, accountId);
11815
+ const accountDir = resolve18(ACCOUNTS_DIR, accountId);
11794
11816
  const resolved = await resolveSavePath(body.id, accountId, accountDir);
11795
11817
  if (resolved.kind === "heal-race") {
11796
11818
  c.header("Retry-After", "2");
@@ -11835,17 +11857,17 @@ async function resolveSavePath(id, accountId, accountDir) {
11835
11857
  if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
11836
11858
  return { kind: "reject", status: 400, reason: "invalid-id" };
11837
11859
  }
11838
- const parent = resolve17(accountDir, "agents", "admin");
11860
+ const parent = resolve18(accountDir, "agents", "admin");
11839
11861
  await mkdir4(parent, { recursive: true });
11840
11862
  try {
11841
11863
  validateFilePathInAccount(parent, accountDir);
11842
11864
  } catch {
11843
11865
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11844
11866
  }
11845
- return { kind: "admin-template", path: resolve17(parent, filename) };
11867
+ return { kind: "admin-template", path: resolve18(parent, filename) };
11846
11868
  }
11847
11869
  if (UUID_RE5.test(id)) {
11848
- const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
11870
+ const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11849
11871
  if (!existsSync17(dir)) {
11850
11872
  const attShort = id.slice(0, 8);
11851
11873
  if (isHealPending(accountId, id)) {
@@ -11878,7 +11900,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11878
11900
  }
11879
11901
  }
11880
11902
  try {
11881
- validateFilePathInAccount(dir, resolve17(ATTACHMENTS_ROOT, accountId));
11903
+ validateFilePathInAccount(dir, resolve18(ATTACHMENTS_ROOT, accountId));
11882
11904
  } catch {
11883
11905
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11884
11906
  }
@@ -11887,7 +11909,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11887
11909
  if (!dataFile) {
11888
11910
  return { kind: "reject", status: 400, reason: "not-found" };
11889
11911
  }
11890
- return { kind: "knowledge-doc", path: resolve17(dir, dataFile) };
11912
+ return { kind: "knowledge-doc", path: resolve18(dir, dataFile) };
11891
11913
  }
11892
11914
  return { kind: "reject", status: 400, reason: "invalid-id" };
11893
11915
  }
@@ -11899,7 +11921,7 @@ var sidebar_artefact_save_default = app30;
11899
11921
  // server/routes/admin/sidebar-artefact-content.ts
11900
11922
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
11901
11923
  import { existsSync as existsSync18 } from "fs";
11902
- import { resolve as resolve18 } from "path";
11924
+ import { resolve as resolve19 } from "path";
11903
11925
  var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11904
11926
  var app31 = new Hono();
11905
11927
  app31.get("/", requireAdminSession, async (c) => {
@@ -11911,14 +11933,14 @@ app31.get("/", requireAdminSession, async (c) => {
11911
11933
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11912
11934
  return new Response("Not found", { status: 404 });
11913
11935
  }
11914
- const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11936
+ const dir = resolve19(ATTACHMENTS_ROOT, accountId, id);
11915
11937
  if (!existsSync18(dir)) {
11916
11938
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11917
11939
  return new Response("Not found", { status: 404 });
11918
11940
  }
11919
11941
  let meta;
11920
11942
  try {
11921
- meta = JSON.parse(await readFile6(resolve18(dir, `${id}.meta.json`), "utf-8"));
11943
+ meta = JSON.parse(await readFile6(resolve19(dir, `${id}.meta.json`), "utf-8"));
11922
11944
  } catch {
11923
11945
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11924
11946
  return new Response("Not found", { status: 404 });
@@ -11930,7 +11952,7 @@ app31.get("/", requireAdminSession, async (c) => {
11930
11952
  return new Response("Not found", { status: 404 });
11931
11953
  }
11932
11954
  const start = Date.now();
11933
- const buffer = await readFile6(resolve18(dir, dataFile));
11955
+ const buffer = await readFile6(resolve19(dir, dataFile));
11934
11956
  const ms = Date.now() - start;
11935
11957
  console.log(
11936
11958
  `[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
@@ -11946,24 +11968,24 @@ app31.get("/", requireAdminSession, async (c) => {
11946
11968
  var sidebar_artefact_content_default = app31;
11947
11969
 
11948
11970
  // server/routes/admin/health.ts
11949
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
11950
- import { resolve as resolve19, join as join11 } from "path";
11951
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
11971
+ import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
11972
+ import { resolve as resolve20, join as join11 } from "path";
11973
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
11952
11974
  var brandHostname = "maxy";
11953
11975
  var brandJsonPath = join11(PLATFORM_ROOT6, "config", "brand.json");
11954
11976
  if (existsSync19(brandJsonPath)) {
11955
11977
  try {
11956
- const brand = JSON.parse(readFileSync16(brandJsonPath, "utf-8"));
11978
+ const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
11957
11979
  if (brand.hostname) brandHostname = brand.hostname;
11958
11980
  } catch {
11959
11981
  }
11960
11982
  }
11961
- var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
11983
+ var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
11962
11984
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11963
11985
  var PROBE_TIMEOUT_MS = 1e3;
11964
11986
  function readVersion() {
11965
11987
  if (!existsSync19(VERSION_FILE)) return "unknown";
11966
- return readFileSync16(VERSION_FILE, "utf-8").trim() || "unknown";
11988
+ return readFileSync17(VERSION_FILE, "utf-8").trim() || "unknown";
11967
11989
  }
11968
11990
  async function probeConversationDb() {
11969
11991
  let session;
@@ -12045,8 +12067,8 @@ app33.route("/health-brand", health_default2);
12045
12067
  var admin_default = app33;
12046
12068
 
12047
12069
  // server/routes/sites.ts
12048
- import { existsSync as existsSync20, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
12049
- import { resolve as resolve20 } from "path";
12070
+ import { existsSync as existsSync20, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
12071
+ import { resolve as resolve21 } from "path";
12050
12072
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12051
12073
  var MIME = {
12052
12074
  ".html": "text/html; charset=utf-8",
@@ -12103,8 +12125,8 @@ app34.get("/:rel{.*}", (c) => {
12103
12125
  }
12104
12126
  segments.push(seg);
12105
12127
  }
12106
- const rootDir = resolve20(account.accountDir, "sites");
12107
- let filePath = segments.length === 0 ? rootDir : resolve20(rootDir, ...segments);
12128
+ const rootDir = resolve21(account.accountDir, "sites");
12129
+ let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
12108
12130
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
12109
12131
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
12110
12132
  return c.text("Forbidden", 403);
@@ -12124,7 +12146,7 @@ app34.get("/:rel{.*}", (c) => {
12124
12146
  return c.redirect(target, 301);
12125
12147
  }
12126
12148
  if (stat7?.isDirectory()) {
12127
- filePath = resolve20(filePath, "index.html");
12149
+ filePath = resolve21(filePath, "index.html");
12128
12150
  }
12129
12151
  if (!filePath.startsWith(rootDir + "/")) {
12130
12152
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -12149,7 +12171,7 @@ app34.get("/:rel{.*}", (c) => {
12149
12171
  }
12150
12172
  let body;
12151
12173
  try {
12152
- body = readFileSync17(realPath);
12174
+ body = readFileSync18(realPath);
12153
12175
  } catch (err) {
12154
12176
  const code = err?.code;
12155
12177
  if (code === "EISDIR") {
@@ -12295,8 +12317,8 @@ function startReaper2() {
12295
12317
 
12296
12318
  // ../lib/entitlement/src/index.ts
12297
12319
  import { createPublicKey, createHash as createHash3, verify as cryptoVerify } from "crypto";
12298
- import { existsSync as existsSync21, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
12299
- import { resolve as resolve21 } from "path";
12320
+ import { existsSync as existsSync21, readFileSync as readFileSync19, statSync as statSync8 } from "fs";
12321
+ import { resolve as resolve22 } from "path";
12300
12322
 
12301
12323
  // ../lib/entitlement/src/canonicalize.ts
12302
12324
  function canonicalize(value) {
@@ -12331,7 +12353,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
12331
12353
  var GRACE_DAYS = 7;
12332
12354
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
12333
12355
  function pubkeyPath(brand) {
12334
- return resolve21(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
12356
+ return resolve22(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
12335
12357
  }
12336
12358
  var memo = null;
12337
12359
  function memoKey(mtimeMs, account) {
@@ -12343,7 +12365,7 @@ function resolveEntitlement(brand, account) {
12343
12365
  if (brand.commercialMode !== true) {
12344
12366
  return logResolved(implicitTrust(account), null);
12345
12367
  }
12346
- const entitlementPath = resolve21(brand.configDir, "entitlement.json");
12368
+ const entitlementPath = resolve22(brand.configDir, "entitlement.json");
12347
12369
  if (!existsSync21(entitlementPath)) {
12348
12370
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
12349
12371
  }
@@ -12359,7 +12381,7 @@ function resolveEntitlement(brand, account) {
12359
12381
  function verifyAndResolve(brand, entitlementPath, account) {
12360
12382
  let pubkeyPem;
12361
12383
  try {
12362
- pubkeyPem = readFileSync18(pubkeyPath(brand), "utf-8");
12384
+ pubkeyPem = readFileSync19(pubkeyPath(brand), "utf-8");
12363
12385
  } catch (err) {
12364
12386
  return logResolved(anonymousFallback("pubkey-missing"), {
12365
12387
  reason: "pubkey-missing"
@@ -12373,7 +12395,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
12373
12395
  }
12374
12396
  let envelope;
12375
12397
  try {
12376
- envelope = JSON.parse(readFileSync18(entitlementPath, "utf-8"));
12398
+ envelope = JSON.parse(readFileSync19(entitlementPath, "utf-8"));
12377
12399
  } catch {
12378
12400
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
12379
12401
  }
@@ -12541,7 +12563,7 @@ if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
12541
12563
  }
12542
12564
  if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12543
12565
  try {
12544
- const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
12566
+ const parsed = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
12545
12567
  BRAND = { ...BRAND, ...parsed };
12546
12568
  } catch (err) {
12547
12569
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -12564,7 +12586,7 @@ var ALIAS_DOMAINS_PATH2 = join12(homedir4(), BRAND.configDir, "alias-domains.jso
12564
12586
  function loadAliasDomains() {
12565
12587
  try {
12566
12588
  if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
12567
- const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH2, "utf-8"));
12589
+ const parsed = JSON.parse(readFileSync20(ALIAS_DOMAINS_PATH2, "utf-8"));
12568
12590
  if (!Array.isArray(parsed)) {
12569
12591
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
12570
12592
  return null;
@@ -12934,8 +12956,8 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
12934
12956
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
12935
12957
  return c.text("Not found", 404);
12936
12958
  }
12937
- const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
12938
- const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
12959
+ const filePath = resolve23(account.accountDir, "agents", slug, "assets", filename);
12960
+ const expectedDir = resolve23(account.accountDir, "agents", slug, "assets");
12939
12961
  if (!filePath.startsWith(expectedDir + "/")) {
12940
12962
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
12941
12963
  return c.text("Forbidden", 403);
@@ -12947,7 +12969,7 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
12947
12969
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12948
12970
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12949
12971
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
12950
- const body = readFileSync19(filePath);
12972
+ const body = readFileSync20(filePath);
12951
12973
  return c.body(body, 200, {
12952
12974
  "Content-Type": contentType,
12953
12975
  "Cache-Control": "public, max-age=3600"
@@ -12964,8 +12986,8 @@ app35.get("/generated/:filename", (c) => {
12964
12986
  console.error(`[generated] serve file=${filename} status=404`);
12965
12987
  return c.text("Not found", 404);
12966
12988
  }
12967
- const filePath = resolve22(account.accountDir, "generated", filename);
12968
- const expectedDir = resolve22(account.accountDir, "generated");
12989
+ const filePath = resolve23(account.accountDir, "generated", filename);
12990
+ const expectedDir = resolve23(account.accountDir, "generated");
12969
12991
  if (!filePath.startsWith(expectedDir + "/")) {
12970
12992
  console.error(`[generated] serve file=${filename} status=403`);
12971
12993
  return c.text("Forbidden", 403);
@@ -12977,7 +12999,7 @@ app35.get("/generated/:filename", (c) => {
12977
12999
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12978
13000
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12979
13001
  console.log(`[generated] serve file=${filename} status=200`);
12980
- const body = readFileSync19(filePath);
13002
+ const body = readFileSync20(filePath);
12981
13003
  return c.body(body, 200, {
12982
13004
  "Content-Type": contentType,
12983
13005
  "Cache-Control": "public, max-age=86400"
@@ -12989,7 +13011,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
12989
13011
  var brandIconPath = "/brand/maxy-monochrome.png";
12990
13012
  if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12991
13013
  try {
12992
- const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
13014
+ const fullBrand = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
12993
13015
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
12994
13016
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
12995
13017
  } catch {
@@ -13008,7 +13030,7 @@ function readInstalledVersion() {
13008
13030
  if (!PLATFORM_ROOT7) return "unknown";
13009
13031
  const versionFile = join12(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
13010
13032
  if (!existsSync22(versionFile)) return "unknown";
13011
- const content = readFileSync19(versionFile, "utf-8").trim();
13033
+ const content = readFileSync20(versionFile, "utf-8").trim();
13012
13034
  return content || "unknown";
13013
13035
  } catch {
13014
13036
  return "unknown";
@@ -13049,7 +13071,7 @@ var clientErrorReporterScript = `<script>
13049
13071
  function cachedHtml(file) {
13050
13072
  let html = htmlCache.get(file);
13051
13073
  if (!html) {
13052
- html = readFileSync19(resolve22(process.cwd(), "public", file), "utf-8");
13074
+ html = readFileSync20(resolve23(process.cwd(), "public", file), "utf-8");
13053
13075
  const productNameEsc = escapeHtml(BRAND.productName);
13054
13076
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
13055
13077
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -13069,12 +13091,12 @@ function loadBrandingCache(agentSlug) {
13069
13091
  try {
13070
13092
  const accountJsonPath = join12(configDir2, "account.json");
13071
13093
  if (!existsSync22(accountJsonPath)) return null;
13072
- const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13094
+ const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
13073
13095
  const accountId = account.accountId;
13074
13096
  if (!accountId) return null;
13075
13097
  const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
13076
13098
  if (!existsSync22(cachePath)) return null;
13077
- return JSON.parse(readFileSync19(cachePath, "utf-8"));
13099
+ return JSON.parse(readFileSync20(cachePath, "utf-8"));
13078
13100
  } catch {
13079
13101
  return null;
13080
13102
  }
@@ -13084,7 +13106,7 @@ function resolveDefaultSlug() {
13084
13106
  const configDir2 = join12(homedir4(), BRAND.configDir);
13085
13107
  const accountJsonPath = join12(configDir2, "account.json");
13086
13108
  if (!existsSync22(accountJsonPath)) return null;
13087
- const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13109
+ const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
13088
13110
  return account.defaultAgent || null;
13089
13111
  } catch {
13090
13112
  return null;
@@ -13157,7 +13179,7 @@ app35.use("/vnc-popout.html", logViewerFetch);
13157
13179
  app35.get("/vnc-popout.html", (c) => {
13158
13180
  let html = htmlCache.get("vnc-popout.html");
13159
13181
  if (!html) {
13160
- html = readFileSync19(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13182
+ html = readFileSync20(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13161
13183
  const name = escapeHtml(BRAND.productName);
13162
13184
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
13163
13185
  html = html.replace("</head>", ` ${brandScript}
@@ -13264,7 +13286,7 @@ try {
13264
13286
  (async () => {
13265
13287
  try {
13266
13288
  if (!existsSync22(USERS_FILE)) return;
13267
- const usersRaw = readFileSync19(USERS_FILE, "utf-8").trim();
13289
+ const usersRaw = readFileSync20(USERS_FILE, "utf-8").trim();
13268
13290
  if (!usersRaw) return;
13269
13291
  const users = JSON.parse(usersRaw);
13270
13292
  const userId = users[0]?.userId;
@@ -13390,7 +13412,7 @@ if (bootAccountConfig?.whatsapp) {
13390
13412
  }
13391
13413
  init({
13392
13414
  configDir: configDirForWhatsApp,
13393
- platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
13415
+ platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
13394
13416
  accountConfig: bootAccountConfig,
13395
13417
  onMessage: async (msg) => {
13396
13418
  if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {