@rubytech/create-maxy-code 0.1.34 → 0.1.36

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 (100) hide show
  1. package/package.json +4 -1
  2. package/payload/platform/plugins/docs/references/platform.md +3 -1
  3. package/payload/platform/services/claude-session-manager/dist/config.d.ts +0 -5
  4. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  5. package/payload/platform/services/claude-session-manager/dist/config.js +16 -6
  6. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  7. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -5
  8. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  9. package/payload/platform/services/claude-session-manager/dist/http-server.js +98 -131
  10. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  11. package/payload/platform/services/claude-session-manager/dist/index.js +0 -1
  12. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  13. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +1 -1
  14. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +38 -9
  15. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -1
  16. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +14 -61
  17. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  18. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +109 -104
  19. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  20. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +30 -36
  21. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
  22. package/payload/platform/services/claude-session-manager/dist/session-store.js +65 -58
  23. package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
  24. package/payload/platform/templates/agents/admin/IDENTITY.md +5 -5
  25. package/payload/server/public/assets/{Checkbox-C6zXApx_.js → Checkbox-C_5g1tvd.js} +1 -1
  26. package/payload/server/public/assets/{admin-CF2ZQvXu.js → admin-CMhAQf3x.js} +24 -24
  27. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BYXgFii5.js → architectureDiagram-Q4EWVU46-PATAR9cB.js} +1 -1
  28. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-GIQ0eO13.js → blockDiagram-DXYQGD6D-BTtUDSn8.js} +1 -1
  29. package/payload/server/public/assets/{brand-DdhkC994.css → brand--hRSJcTa.css} +1 -1
  30. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BmyWfG-l.js → c4Diagram-AHTNJAMY-DagJLqud.js} +1 -1
  31. package/payload/server/public/assets/channel-ad6bhEyF.js +1 -0
  32. package/payload/server/public/assets/{chunk-336JU56O-DcWl0MQo.js → chunk-336JU56O-r_17ZSte.js} +2 -2
  33. package/payload/server/public/assets/{chunk-426QAEUC-BIW6kq6y.js → chunk-426QAEUC-BeZHE5Od.js} +1 -1
  34. package/payload/server/public/assets/{chunk-4TB4RGXK-CdoHpV4X.js → chunk-4TB4RGXK-BOKuzFDs.js} +1 -1
  35. package/payload/server/public/assets/{chunk-5FUZZQ4R-bn_a4sfU.js → chunk-5FUZZQ4R-CFPql_Mb.js} +1 -1
  36. package/payload/server/public/assets/{chunk-5PVQY5BW-C_Rq8j_M.js → chunk-5PVQY5BW-B-ooj0Oj.js} +1 -1
  37. package/payload/server/public/assets/{chunk-EDXVE4YY-CWQvoVKV.js → chunk-EDXVE4YY-pfgSmAaU.js} +1 -1
  38. package/payload/server/public/assets/{chunk-ENJZ2VHE-DBHn1kSk.js → chunk-ENJZ2VHE-Czo3wSBG.js} +1 -1
  39. package/payload/server/public/assets/{chunk-ICPOFSXX-SW2Qx11O.js → chunk-ICPOFSXX-B0Kq8LNp.js} +1 -1
  40. package/payload/server/public/assets/{chunk-OYMX7WX6-BvIG7tVW.js → chunk-OYMX7WX6-BM97IkL3.js} +1 -1
  41. package/payload/server/public/assets/{chunk-U2HBQHQK-BiBUb0cF.js → chunk-U2HBQHQK-Qu1CuohC.js} +1 -1
  42. package/payload/server/public/assets/{chunk-X2U36JSP-Y0MKZCCh.js → chunk-X2U36JSP-uDlh8MVE.js} +1 -1
  43. package/payload/server/public/assets/{chunk-YZCP3GAM-DKPh06GH.js → chunk-YZCP3GAM-DUlG-OZ5.js} +1 -1
  44. package/payload/server/public/assets/{chunk-ZZ45TVLE-C2WNo-fK.js → chunk-ZZ45TVLE-BABivBFM.js} +1 -1
  45. package/payload/server/public/assets/classDiagram-6PBFFD2Q-D9Gycby2.js +1 -0
  46. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sUgm3wmz.js +1 -0
  47. package/payload/server/public/assets/clone-CZxh5VW0.js +1 -0
  48. package/payload/server/public/assets/{dagre-CrK8E9ee.js → dagre-BLaP4HDY.js} +1 -1
  49. package/payload/server/public/assets/{dagre-KV5264BT-_o6uXcH8.js → dagre-KV5264BT-CVL1mRVD.js} +1 -1
  50. package/payload/server/public/assets/data-DarDs6k1.js +1 -0
  51. package/payload/server/public/assets/{device-url-actions-BcHerWqJ.js → device-url-actions-Dmhh-Azv.js} +1 -1
  52. package/payload/server/public/assets/{diagram-5BDNPKRD-FFP9DKhc.js → diagram-5BDNPKRD-Db75sppc.js} +1 -1
  53. package/payload/server/public/assets/{diagram-G4DWMVQ6-DpwD1jBP.js → diagram-G4DWMVQ6-Cj8Nvgev.js} +1 -1
  54. package/payload/server/public/assets/{diagram-MMDJMWI5-C3K5agdK.js → diagram-MMDJMWI5-BGXJmtU0.js} +1 -1
  55. package/payload/server/public/assets/{diagram-TYMM5635-CbeDipbC.js → diagram-TYMM5635-FALU804i.js} +1 -1
  56. package/payload/server/public/assets/{erDiagram-SMLLAGMA-XBIFndNy.js → erDiagram-SMLLAGMA-Dny5IMgt.js} +1 -1
  57. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BvEgySyn.js → flowDiagram-DWJPFMVM-CvKuRNSd.js} +1 -1
  58. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-D7gIRKJf.js → ganttDiagram-T4ZO3ILL-CMMNRVGJ.js} +1 -1
  59. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-vJu_hcri.js → gitGraphDiagram-UUTBAWPF-GNp7o9CH.js} +1 -1
  60. package/payload/server/public/assets/graph-CG9KcTMy.js +1 -0
  61. package/payload/server/public/assets/graph-labels-DnFPoPy9.js +1 -0
  62. package/payload/server/public/assets/{graphlib-Dp0mN6JW.js → graphlib-Bbf4iSQ9.js} +1 -1
  63. package/payload/server/public/assets/{infoDiagram-42DDH7IO-g4Dlc5Cr.js → infoDiagram-42DDH7IO-CKnsQ4zf.js} +1 -1
  64. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-D_45LXOe.js → ishikawaDiagram-UXIWVN3A-7iiLy5h7.js} +1 -1
  65. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CggbHl6N.js → journeyDiagram-VCZTEJTY-BqbrYu64.js} +1 -1
  66. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CysAe-Ab.js → kanban-definition-6JOO6SKY-B4xrW1HU.js} +1 -1
  67. package/payload/server/public/assets/{line-BAxq_DSY.js → line-VuY4jgLe.js} +1 -1
  68. package/payload/server/public/assets/{mermaid-parser.core-DbFuvkjL.js → mermaid-parser.core-BaqOkGpC.js} +1 -1
  69. package/payload/server/public/assets/{mermaid.core-CehvJn5b.js → mermaid.core-CCQHCJiH.js} +3 -3
  70. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DbPbBJ9h.js → mindmap-definition-QFDTVHPH-CD7_gX12.js} +1 -1
  71. package/payload/server/public/assets/page-BbunxlG3.js +1 -0
  72. package/payload/server/public/assets/{page-Co7KCRV8.js → page-CDFsJW62.js} +1 -1
  73. package/payload/server/public/assets/{pieDiagram-DEJITSTG-cagLL9ng.js → pieDiagram-DEJITSTG-DYv6IDvS.js} +1 -1
  74. package/payload/server/public/assets/{public-B6TEcDLx.js → public-vZ5OE_BJ.js} +3 -3
  75. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Keaa1jDh.js → quadrantDiagram-34T5L4WZ-Djjgb1kX.js} +1 -1
  76. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BcYRyn5z.js → requirementDiagram-MS252O5E-D1jpw_fu.js} +1 -1
  77. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6--fKoG9NR.js → sankeyDiagram-XADWPNL6-CiWmspyf.js} +1 -1
  78. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-lKG36-Di.js → sequenceDiagram-FGHM5R23-B1GXIeQe.js} +1 -1
  79. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BuVsrlig.js → stateDiagram-FHFEXIEX-DX7QZrhc.js} +1 -1
  80. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CekuC-ks.js +1 -0
  81. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-D6X6uq17.js → timeline-definition-GMOUNBTQ-BxiwnKFu.js} +1 -1
  82. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BgvcfRVf.js → vennDiagram-DHZGUBPP-RxZA_K0W.js} +1 -1
  83. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Cpd1xsrt.js → wardleyDiagram-NUSXRM2D-b2tVWjtB.js} +1 -1
  84. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CDF5ZVFv.js → xychartDiagram-5P7HB3ND-D55tkJH1.js} +1 -1
  85. package/payload/server/public/data.html +5 -5
  86. package/payload/server/public/graph.html +6 -6
  87. package/payload/server/public/index.html +8 -8
  88. package/payload/server/public/public.html +5 -5
  89. package/payload/server/server.js +149 -129
  90. package/payload/docs/desktop-code-controls.md +0 -63
  91. package/payload/server/public/assets/channel-C76knBRO.js +0 -1
  92. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bohexn7P.js +0 -1
  93. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DVsmsAu7.js +0 -1
  94. package/payload/server/public/assets/clone-DUrXF4sO.js +0 -1
  95. package/payload/server/public/assets/data-j1WNhF8t.js +0 -1
  96. package/payload/server/public/assets/graph-C_f_9L_7.js +0 -1
  97. package/payload/server/public/assets/graph-labels-BSQJHlgf.js +0 -1
  98. package/payload/server/public/assets/page-B0BPrSE3.js +0 -1
  99. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSt88_xL.js +0 -1
  100. /package/payload/server/public/assets/{brand-B-bNrpwc.js → brand-B62OQoRC.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");
@@ -7965,10 +7982,11 @@ function managerBase2() {
7965
7982
  var app15 = new Hono();
7966
7983
  app15.use("*", requireAdminSession);
7967
7984
  app15.post("/", async (c) => {
7985
+ const routeStart = Date.now();
7968
7986
  const cacheKey = c.get("cacheKey") ?? "";
7969
7987
  const senderId = getAccountIdForSession(cacheKey) ?? "";
7970
7988
  if (!senderId) {
7971
- console.error(`${TAG18} reject reason=no-account-id`);
7989
+ console.error(`${TAG18} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
7972
7990
  return c.json({ error: "admin-account-not-resolved" }, 500);
7973
7991
  }
7974
7992
  const userId = getUserIdForSession(cacheKey);
@@ -7980,24 +7998,38 @@ app15.post("/", async (c) => {
7980
7998
  const channel = typeof body.channel === "string" ? body.channel : "browser";
7981
7999
  const initialMessage = typeof body.initialMessage === "string" && body.initialMessage.trim() ? body.initialMessage : null;
7982
8000
  const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
8001
+ console.log(`${TAG18} spawn-request-in cacheKey-prefix=${cacheKey.slice(0, 8)} senderId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
8002
+ const ownerStart = Date.now();
7983
8003
  const aboutOwner = await resolveOwnerProfileBlock(senderId, userId);
8004
+ const ownerMs = Date.now() - ownerStart;
8005
+ const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
8006
+ console.log(`${TAG18} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
8007
+ const dormantStart = Date.now();
7984
8008
  const dormantPlugins = computeDormantPlugins(senderId);
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"}`);
8012
+ const forwardStart = Date.now();
8013
+ const upstreamPayload = JSON.stringify({
8014
+ senderId,
8015
+ role: "admin",
8016
+ channel,
8017
+ permissionMode,
8018
+ aboutOwner,
8019
+ dormantPlugins,
8020
+ tunnelUrl
8021
+ });
8022
+ console.log(`${TAG18} forward-spawn-start managerBase=${managerBase2()} bytes=${upstreamPayload.length}`);
7985
8023
  const upstream = await fetch(`${managerBase2()}/spawn`, {
7986
8024
  method: "POST",
7987
8025
  headers: { "content-type": "application/json" },
7988
- body: JSON.stringify({
7989
- senderId,
7990
- role: "admin",
7991
- channel,
7992
- permissionMode,
7993
- aboutOwner,
7994
- dormantPlugins
7995
- })
8026
+ body: upstreamPayload
7996
8027
  }).catch((err) => {
7997
- console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)}`);
8028
+ console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
7998
8029
  return null;
7999
8030
  });
8000
8031
  if (!upstream) return c.json({ error: "manager-unreachable" }, 503);
8032
+ console.log(`${TAG18} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart} route-ms=${Date.now() - routeStart}`);
8001
8033
  let spawnedSessionId = null;
8002
8034
  if (upstream.ok && initialMessage) {
8003
8035
  const buffered = await upstream.clone().json().catch(() => null);
@@ -8046,6 +8078,7 @@ app15.post("/resume", async (c) => {
8046
8078
  const channel = typeof body.channel === "string" ? body.channel : "browser";
8047
8079
  const aboutOwner = await resolveOwnerProfileBlock(senderId, userId);
8048
8080
  const dormantPlugins = computeDormantPlugins(senderId);
8081
+ const tunnelUrl = resolveTunnelUrl();
8049
8082
  const upstream = await fetch(`${managerBase2()}/resume`, {
8050
8083
  method: "POST",
8051
8084
  headers: { "content-type": "application/json" },
@@ -8055,7 +8088,8 @@ app15.post("/resume", async (c) => {
8055
8088
  channel,
8056
8089
  claudeSessionId: body.claudeSessionId,
8057
8090
  aboutOwner,
8058
- dormantPlugins
8091
+ dormantPlugins,
8092
+ tunnelUrl
8059
8093
  })
8060
8094
  }).catch((err) => {
8061
8095
  console.error(`${TAG18} fetch-failed op=resume message=${err instanceof Error ? err.message : String(err)}`);
@@ -8392,8 +8426,8 @@ var events_default = app19;
8392
8426
 
8393
8427
  // server/routes/admin/cloudflare.ts
8394
8428
  import { homedir as homedir3 } from "os";
8395
- import { resolve as resolve13 } from "path";
8396
- import { readFileSync as readFileSync15 } from "fs";
8429
+ import { resolve as resolve14 } from "path";
8430
+ import { readFileSync as readFileSync16 } from "fs";
8397
8431
 
8398
8432
  // app/lib/dns-label.ts
8399
8433
  var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
@@ -8409,14 +8443,14 @@ function isValidDomain(value) {
8409
8443
  }
8410
8444
 
8411
8445
  // app/lib/alias-domains.ts
8412
- 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";
8413
8447
  import { dirname as dirname2 } from "path";
8414
- import { resolve as resolve12 } from "path";
8415
- 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");
8416
8450
  function readExisting() {
8417
8451
  if (!existsSync15(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
8418
8452
  try {
8419
- const parsed = JSON.parse(readFileSync14(ALIAS_DOMAINS_PATH, "utf-8"));
8453
+ const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH, "utf-8"));
8420
8454
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
8421
8455
  return new Set(parsed.filter((h) => typeof h === "string"));
8422
8456
  } catch {
@@ -8683,7 +8717,7 @@ var CLOUDFLARE_SETUP_FORM_SCHEMA = {
8683
8717
 
8684
8718
  // server/routes/admin/cloudflare.ts
8685
8719
  function cloudflareStreamLogPath(accountId, correlationId) {
8686
- return resolve13(ACCOUNTS_DIR, accountId, "cloudflare-stream-logs", `${correlationId}.log`);
8720
+ return resolve14(ACCOUNTS_DIR, accountId, "cloudflare-stream-logs", `${correlationId}.log`);
8687
8721
  }
8688
8722
  var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
8689
8723
  var DOMAINS_TIMEOUT_MS = 40 * 1e3;
@@ -8713,10 +8747,10 @@ function readDiscoveryResults(accountId) {
8713
8747
  return { tunnels: entry.tunnels, domains: entry.domains };
8714
8748
  }
8715
8749
  function loadBrandInfo() {
8716
- const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "..");
8717
- 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");
8718
8752
  try {
8719
- const parsed = JSON.parse(readFileSync15(brandPath, "utf-8"));
8753
+ const parsed = JSON.parse(readFileSync16(brandPath, "utf-8"));
8720
8754
  const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
8721
8755
  const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
8722
8756
  return { hostname: hostname2, configDir: configDir2 };
@@ -8844,7 +8878,7 @@ app20.get("/domains", requireAdminSession, async (c) => {
8844
8878
  streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
8845
8879
  log(`phase=stream-log-resolved path=${streamLogPath}`);
8846
8880
  const brand = loadBrandInfo();
8847
- const scriptPath = resolve13(homedir3(), "list-cf-domains.sh");
8881
+ const scriptPath = resolve14(homedir3(), "list-cf-domains.sh");
8848
8882
  const result = await runFormSpawn({
8849
8883
  scriptPath,
8850
8884
  args: [brand.hostname],
@@ -8935,7 +8969,7 @@ app20.get("/tunnels", requireAdminSession, async (c) => {
8935
8969
  if (!accountId) return err("session", "No account bound to session \u2014 refresh chat.");
8936
8970
  if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
8937
8971
  streamLogPath = cloudflareStreamLogPath(accountId, correlationId);
8938
- const certPath = resolve13(homedir3(), brand.configDir, "cloudflared", "cert.pem");
8972
+ const certPath = resolve14(homedir3(), brand.configDir, "cloudflared", "cert.pem");
8939
8973
  const { existsSync: existsSync23 } = await import("fs");
8940
8974
  if (!existsSync23(certPath)) {
8941
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.`);
@@ -9261,17 +9295,17 @@ var cloudflare_default = app20;
9261
9295
  import { createReadStream as createReadStream3 } from "fs";
9262
9296
  import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
9263
9297
  import { realpathSync as realpathSync4 } from "fs";
9264
- 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";
9265
9299
  import { Readable as Readable2 } from "stream";
9266
9300
 
9267
9301
  // app/lib/data-path.ts
9268
9302
  import { realpathSync as realpathSync3 } from "fs";
9269
- import { resolve as resolve14, normalize, sep as sep2, relative } from "path";
9270
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "../platform");
9271
- 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");
9272
9306
  function resolveDataPath(raw) {
9273
9307
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
9274
- const absolute = resolve14(DATA_ROOT, cleaned);
9308
+ const absolute = resolve15(DATA_ROOT, cleaned);
9275
9309
  let dataRootReal;
9276
9310
  try {
9277
9311
  dataRootReal = realpathSync3(DATA_ROOT);
@@ -9629,7 +9663,7 @@ async function readMeta(absDir, baseName) {
9629
9663
  }
9630
9664
  async function readAccountNames() {
9631
9665
  const map = /* @__PURE__ */ new Map();
9632
- const accountsDir = resolve15(DATA_ROOT, "accounts");
9666
+ const accountsDir = resolve16(DATA_ROOT, "accounts");
9633
9667
  let names;
9634
9668
  try {
9635
9669
  names = await readdir2(accountsDir);
@@ -9638,7 +9672,7 @@ async function readAccountNames() {
9638
9672
  }
9639
9673
  for (const name of names) {
9640
9674
  if (!UUID_RE4.test(name)) continue;
9641
- const configPath2 = resolve15(accountsDir, name, "account.json");
9675
+ const configPath2 = resolve16(accountsDir, name, "account.json");
9642
9676
  try {
9643
9677
  const raw = await readFile4(configPath2, "utf8");
9644
9678
  const parsed = JSON.parse(raw);
@@ -9829,8 +9863,8 @@ app21.post("/upload", requireAdminSession, async (c) => {
9829
9863
  }
9830
9864
  const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
9831
9865
  const finalName = `${Date.now()}-${safeName}`;
9832
- const destDir = resolve15(DATA_ROOT, "uploads", accountId);
9833
- const destPath = resolve15(destDir, finalName);
9866
+ const destDir = resolve16(DATA_ROOT, "uploads", accountId);
9867
+ const destPath = resolve16(destDir, finalName);
9834
9868
  try {
9835
9869
  await mkdir3(destDir, { recursive: true });
9836
9870
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11549,7 +11583,7 @@ var file_attach_default = app28;
11549
11583
  // server/routes/admin/sidebar-artefacts.ts
11550
11584
  import neo4j2 from "neo4j-driver";
11551
11585
  import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
11552
- import { resolve as resolve16, relative as relative2, isAbsolute } from "path";
11586
+ import { resolve as resolve17, relative as relative2, isAbsolute } from "path";
11553
11587
  import { existsSync as existsSync16 } from "fs";
11554
11588
  var LIMIT = 50;
11555
11589
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
@@ -11566,7 +11600,7 @@ app29.get("/", requireAdminSession, async (c) => {
11566
11600
  if (docs === null) {
11567
11601
  return c.json({ error: "Failed to load artefacts" }, 500);
11568
11602
  }
11569
- const accountDir = resolve16(ACCOUNTS_DIR, accountId);
11603
+ const accountDir = resolve17(ACCOUNTS_DIR, accountId);
11570
11604
  const agents = await fetchAgentTemplateRows(accountDir);
11571
11605
  const artefacts = [...docs, ...agents].sort(
11572
11606
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -11629,8 +11663,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11629
11663
  logSkip(displayName, "non-text-mime", mimeType);
11630
11664
  return { content: "", skipReason: "non-text-mime" };
11631
11665
  }
11632
- const accountDir = resolve16(ATTACHMENTS_ROOT, accountId);
11633
- const dir = resolve16(accountDir, attachmentId);
11666
+ const accountDir = resolve17(ATTACHMENTS_ROOT, accountId);
11667
+ const dir = resolve17(accountDir, attachmentId);
11634
11668
  try {
11635
11669
  validateFilePathInAccount(dir, accountDir);
11636
11670
  } catch {
@@ -11644,7 +11678,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11644
11678
  logSkip(displayName, "missing-on-disk", mimeType);
11645
11679
  return { content: "", skipReason: "missing-on-disk" };
11646
11680
  }
11647
- return { content: await readFile5(resolve16(dir, dataFile), "utf-8"), skipReason: null };
11681
+ return { content: await readFile5(resolve17(dir, dataFile), "utf-8"), skipReason: null };
11648
11682
  } catch (err) {
11649
11683
  const message = err instanceof Error ? err.message : String(err);
11650
11684
  console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
@@ -11660,8 +11694,8 @@ function logSkip(name, reason, mimeType) {
11660
11694
  async function fetchAgentTemplateRows(accountDir) {
11661
11695
  const rows = [];
11662
11696
  for (const filename of ADMIN_AGENT_FILES) {
11663
- const overridePath = resolve16(accountDir, "agents", "admin", filename);
11664
- 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);
11665
11699
  const labelStem = filename.replace(/\.md$/, "");
11666
11700
  const row = await readAgentTemplateRow({
11667
11701
  id: `agent-template:admin:${filename}`,
@@ -11675,12 +11709,12 @@ async function fetchAgentTemplateRows(accountDir) {
11675
11709
  });
11676
11710
  if (row) rows.push(row);
11677
11711
  }
11678
- const overrideDir = resolve16(accountDir, "specialists", "agents");
11679
- const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
11712
+ const overrideDir = resolve17(accountDir, "specialists", "agents");
11713
+ const bundledDir = resolve17(PLATFORM_ROOT, "templates", "specialists", "agents");
11680
11714
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
11681
11715
  for (const filename of specialistNames) {
11682
- const overridePath = resolve16(overrideDir, filename);
11683
- const bundledPath = resolve16(bundledDir, filename);
11716
+ const overridePath = resolve17(overrideDir, filename);
11717
+ const bundledPath = resolve17(bundledDir, filename);
11684
11718
  const row = await readAgentTemplateRow({
11685
11719
  id: `agent-template:specialist:${filename}`,
11686
11720
  displayName: filename.replace(/\.md$/, ""),
@@ -11765,7 +11799,7 @@ var sidebar_artefacts_default = app29;
11765
11799
 
11766
11800
  // server/routes/admin/sidebar-artefact-save.ts
11767
11801
  import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11768
- import { resolve as resolve17 } from "path";
11802
+ import { resolve as resolve18 } from "path";
11769
11803
  import { existsSync as existsSync17 } from "fs";
11770
11804
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
11771
11805
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
@@ -11778,7 +11812,7 @@ app30.post("/", requireAdminSession, async (c) => {
11778
11812
  if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
11779
11813
  return c.json({ error: "id and content required" }, 400);
11780
11814
  }
11781
- const accountDir = resolve17(ACCOUNTS_DIR, accountId);
11815
+ const accountDir = resolve18(ACCOUNTS_DIR, accountId);
11782
11816
  const resolved = await resolveSavePath(body.id, accountId, accountDir);
11783
11817
  if (resolved.kind === "heal-race") {
11784
11818
  c.header("Retry-After", "2");
@@ -11823,17 +11857,17 @@ async function resolveSavePath(id, accountId, accountDir) {
11823
11857
  if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
11824
11858
  return { kind: "reject", status: 400, reason: "invalid-id" };
11825
11859
  }
11826
- const parent = resolve17(accountDir, "agents", "admin");
11860
+ const parent = resolve18(accountDir, "agents", "admin");
11827
11861
  await mkdir4(parent, { recursive: true });
11828
11862
  try {
11829
11863
  validateFilePathInAccount(parent, accountDir);
11830
11864
  } catch {
11831
11865
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11832
11866
  }
11833
- return { kind: "admin-template", path: resolve17(parent, filename) };
11867
+ return { kind: "admin-template", path: resolve18(parent, filename) };
11834
11868
  }
11835
11869
  if (UUID_RE5.test(id)) {
11836
- const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
11870
+ const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11837
11871
  if (!existsSync17(dir)) {
11838
11872
  const attShort = id.slice(0, 8);
11839
11873
  if (isHealPending(accountId, id)) {
@@ -11866,7 +11900,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11866
11900
  }
11867
11901
  }
11868
11902
  try {
11869
- validateFilePathInAccount(dir, resolve17(ATTACHMENTS_ROOT, accountId));
11903
+ validateFilePathInAccount(dir, resolve18(ATTACHMENTS_ROOT, accountId));
11870
11904
  } catch {
11871
11905
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11872
11906
  }
@@ -11875,7 +11909,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11875
11909
  if (!dataFile) {
11876
11910
  return { kind: "reject", status: 400, reason: "not-found" };
11877
11911
  }
11878
- return { kind: "knowledge-doc", path: resolve17(dir, dataFile) };
11912
+ return { kind: "knowledge-doc", path: resolve18(dir, dataFile) };
11879
11913
  }
11880
11914
  return { kind: "reject", status: 400, reason: "invalid-id" };
11881
11915
  }
@@ -11887,7 +11921,7 @@ var sidebar_artefact_save_default = app30;
11887
11921
  // server/routes/admin/sidebar-artefact-content.ts
11888
11922
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
11889
11923
  import { existsSync as existsSync18 } from "fs";
11890
- import { resolve as resolve18 } from "path";
11924
+ import { resolve as resolve19 } from "path";
11891
11925
  var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11892
11926
  var app31 = new Hono();
11893
11927
  app31.get("/", requireAdminSession, async (c) => {
@@ -11899,14 +11933,14 @@ app31.get("/", requireAdminSession, async (c) => {
11899
11933
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11900
11934
  return new Response("Not found", { status: 404 });
11901
11935
  }
11902
- const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11936
+ const dir = resolve19(ATTACHMENTS_ROOT, accountId, id);
11903
11937
  if (!existsSync18(dir)) {
11904
11938
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11905
11939
  return new Response("Not found", { status: 404 });
11906
11940
  }
11907
11941
  let meta;
11908
11942
  try {
11909
- 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"));
11910
11944
  } catch {
11911
11945
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11912
11946
  return new Response("Not found", { status: 404 });
@@ -11918,7 +11952,7 @@ app31.get("/", requireAdminSession, async (c) => {
11918
11952
  return new Response("Not found", { status: 404 });
11919
11953
  }
11920
11954
  const start = Date.now();
11921
- const buffer = await readFile6(resolve18(dir, dataFile));
11955
+ const buffer = await readFile6(resolve19(dir, dataFile));
11922
11956
  const ms = Date.now() - start;
11923
11957
  console.log(
11924
11958
  `[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
@@ -11934,24 +11968,24 @@ app31.get("/", requireAdminSession, async (c) => {
11934
11968
  var sidebar_artefact_content_default = app31;
11935
11969
 
11936
11970
  // server/routes/admin/health.ts
11937
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
11938
- import { resolve as resolve19, join as join11 } from "path";
11939
- 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(), "..");
11940
11974
  var brandHostname = "maxy";
11941
11975
  var brandJsonPath = join11(PLATFORM_ROOT6, "config", "brand.json");
11942
11976
  if (existsSync19(brandJsonPath)) {
11943
11977
  try {
11944
- const brand = JSON.parse(readFileSync16(brandJsonPath, "utf-8"));
11978
+ const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
11945
11979
  if (brand.hostname) brandHostname = brand.hostname;
11946
11980
  } catch {
11947
11981
  }
11948
11982
  }
11949
- var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
11983
+ var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
11950
11984
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11951
11985
  var PROBE_TIMEOUT_MS = 1e3;
11952
11986
  function readVersion() {
11953
11987
  if (!existsSync19(VERSION_FILE)) return "unknown";
11954
- return readFileSync16(VERSION_FILE, "utf-8").trim() || "unknown";
11988
+ return readFileSync17(VERSION_FILE, "utf-8").trim() || "unknown";
11955
11989
  }
11956
11990
  async function probeConversationDb() {
11957
11991
  let session;
@@ -12033,8 +12067,8 @@ app33.route("/health-brand", health_default2);
12033
12067
  var admin_default = app33;
12034
12068
 
12035
12069
  // server/routes/sites.ts
12036
- import { existsSync as existsSync20, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
12037
- 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";
12038
12072
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12039
12073
  var MIME = {
12040
12074
  ".html": "text/html; charset=utf-8",
@@ -12091,8 +12125,8 @@ app34.get("/:rel{.*}", (c) => {
12091
12125
  }
12092
12126
  segments.push(seg);
12093
12127
  }
12094
- const rootDir = resolve20(account.accountDir, "sites");
12095
- 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);
12096
12130
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
12097
12131
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
12098
12132
  return c.text("Forbidden", 403);
@@ -12112,7 +12146,7 @@ app34.get("/:rel{.*}", (c) => {
12112
12146
  return c.redirect(target, 301);
12113
12147
  }
12114
12148
  if (stat7?.isDirectory()) {
12115
- filePath = resolve20(filePath, "index.html");
12149
+ filePath = resolve21(filePath, "index.html");
12116
12150
  }
12117
12151
  if (!filePath.startsWith(rootDir + "/")) {
12118
12152
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -12137,7 +12171,7 @@ app34.get("/:rel{.*}", (c) => {
12137
12171
  }
12138
12172
  let body;
12139
12173
  try {
12140
- body = readFileSync17(realPath);
12174
+ body = readFileSync18(realPath);
12141
12175
  } catch (err) {
12142
12176
  const code = err?.code;
12143
12177
  if (code === "EISDIR") {
@@ -12283,8 +12317,8 @@ function startReaper2() {
12283
12317
 
12284
12318
  // ../lib/entitlement/src/index.ts
12285
12319
  import { createPublicKey, createHash as createHash3, verify as cryptoVerify } from "crypto";
12286
- import { existsSync as existsSync21, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
12287
- 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";
12288
12322
 
12289
12323
  // ../lib/entitlement/src/canonicalize.ts
12290
12324
  function canonicalize(value) {
@@ -12319,7 +12353,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
12319
12353
  var GRACE_DAYS = 7;
12320
12354
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
12321
12355
  function pubkeyPath(brand) {
12322
- return resolve21(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
12356
+ return resolve22(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
12323
12357
  }
12324
12358
  var memo = null;
12325
12359
  function memoKey(mtimeMs, account) {
@@ -12331,7 +12365,7 @@ function resolveEntitlement(brand, account) {
12331
12365
  if (brand.commercialMode !== true) {
12332
12366
  return logResolved(implicitTrust(account), null);
12333
12367
  }
12334
- const entitlementPath = resolve21(brand.configDir, "entitlement.json");
12368
+ const entitlementPath = resolve22(brand.configDir, "entitlement.json");
12335
12369
  if (!existsSync21(entitlementPath)) {
12336
12370
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
12337
12371
  }
@@ -12347,7 +12381,7 @@ function resolveEntitlement(brand, account) {
12347
12381
  function verifyAndResolve(brand, entitlementPath, account) {
12348
12382
  let pubkeyPem;
12349
12383
  try {
12350
- pubkeyPem = readFileSync18(pubkeyPath(brand), "utf-8");
12384
+ pubkeyPem = readFileSync19(pubkeyPath(brand), "utf-8");
12351
12385
  } catch (err) {
12352
12386
  return logResolved(anonymousFallback("pubkey-missing"), {
12353
12387
  reason: "pubkey-missing"
@@ -12361,7 +12395,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
12361
12395
  }
12362
12396
  let envelope;
12363
12397
  try {
12364
- envelope = JSON.parse(readFileSync18(entitlementPath, "utf-8"));
12398
+ envelope = JSON.parse(readFileSync19(entitlementPath, "utf-8"));
12365
12399
  } catch {
12366
12400
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
12367
12401
  }
@@ -12529,7 +12563,7 @@ if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
12529
12563
  }
12530
12564
  if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12531
12565
  try {
12532
- const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
12566
+ const parsed = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
12533
12567
  BRAND = { ...BRAND, ...parsed };
12534
12568
  } catch (err) {
12535
12569
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -12552,7 +12586,7 @@ var ALIAS_DOMAINS_PATH2 = join12(homedir4(), BRAND.configDir, "alias-domains.jso
12552
12586
  function loadAliasDomains() {
12553
12587
  try {
12554
12588
  if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
12555
- const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH2, "utf-8"));
12589
+ const parsed = JSON.parse(readFileSync20(ALIAS_DOMAINS_PATH2, "utf-8"));
12556
12590
  if (!Array.isArray(parsed)) {
12557
12591
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
12558
12592
  return null;
@@ -12922,8 +12956,8 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
12922
12956
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
12923
12957
  return c.text("Not found", 404);
12924
12958
  }
12925
- const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
12926
- 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");
12927
12961
  if (!filePath.startsWith(expectedDir + "/")) {
12928
12962
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
12929
12963
  return c.text("Forbidden", 403);
@@ -12935,7 +12969,7 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
12935
12969
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12936
12970
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12937
12971
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
12938
- const body = readFileSync19(filePath);
12972
+ const body = readFileSync20(filePath);
12939
12973
  return c.body(body, 200, {
12940
12974
  "Content-Type": contentType,
12941
12975
  "Cache-Control": "public, max-age=3600"
@@ -12952,8 +12986,8 @@ app35.get("/generated/:filename", (c) => {
12952
12986
  console.error(`[generated] serve file=${filename} status=404`);
12953
12987
  return c.text("Not found", 404);
12954
12988
  }
12955
- const filePath = resolve22(account.accountDir, "generated", filename);
12956
- const expectedDir = resolve22(account.accountDir, "generated");
12989
+ const filePath = resolve23(account.accountDir, "generated", filename);
12990
+ const expectedDir = resolve23(account.accountDir, "generated");
12957
12991
  if (!filePath.startsWith(expectedDir + "/")) {
12958
12992
  console.error(`[generated] serve file=${filename} status=403`);
12959
12993
  return c.text("Forbidden", 403);
@@ -12965,7 +12999,7 @@ app35.get("/generated/:filename", (c) => {
12965
12999
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12966
13000
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12967
13001
  console.log(`[generated] serve file=${filename} status=200`);
12968
- const body = readFileSync19(filePath);
13002
+ const body = readFileSync20(filePath);
12969
13003
  return c.body(body, 200, {
12970
13004
  "Content-Type": contentType,
12971
13005
  "Cache-Control": "public, max-age=86400"
@@ -12977,7 +13011,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
12977
13011
  var brandIconPath = "/brand/maxy-monochrome.png";
12978
13012
  if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12979
13013
  try {
12980
- const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
13014
+ const fullBrand = JSON.parse(readFileSync20(BRAND_JSON_PATH, "utf-8"));
12981
13015
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
12982
13016
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
12983
13017
  } catch {
@@ -12996,7 +13030,7 @@ function readInstalledVersion() {
12996
13030
  if (!PLATFORM_ROOT7) return "unknown";
12997
13031
  const versionFile = join12(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
12998
13032
  if (!existsSync22(versionFile)) return "unknown";
12999
- const content = readFileSync19(versionFile, "utf-8").trim();
13033
+ const content = readFileSync20(versionFile, "utf-8").trim();
13000
13034
  return content || "unknown";
13001
13035
  } catch {
13002
13036
  return "unknown";
@@ -13037,7 +13071,7 @@ var clientErrorReporterScript = `<script>
13037
13071
  function cachedHtml(file) {
13038
13072
  let html = htmlCache.get(file);
13039
13073
  if (!html) {
13040
- html = readFileSync19(resolve22(process.cwd(), "public", file), "utf-8");
13074
+ html = readFileSync20(resolve23(process.cwd(), "public", file), "utf-8");
13041
13075
  const productNameEsc = escapeHtml(BRAND.productName);
13042
13076
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
13043
13077
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -13057,12 +13091,12 @@ function loadBrandingCache(agentSlug) {
13057
13091
  try {
13058
13092
  const accountJsonPath = join12(configDir2, "account.json");
13059
13093
  if (!existsSync22(accountJsonPath)) return null;
13060
- const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13094
+ const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
13061
13095
  const accountId = account.accountId;
13062
13096
  if (!accountId) return null;
13063
13097
  const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
13064
13098
  if (!existsSync22(cachePath)) return null;
13065
- return JSON.parse(readFileSync19(cachePath, "utf-8"));
13099
+ return JSON.parse(readFileSync20(cachePath, "utf-8"));
13066
13100
  } catch {
13067
13101
  return null;
13068
13102
  }
@@ -13072,7 +13106,7 @@ function resolveDefaultSlug() {
13072
13106
  const configDir2 = join12(homedir4(), BRAND.configDir);
13073
13107
  const accountJsonPath = join12(configDir2, "account.json");
13074
13108
  if (!existsSync22(accountJsonPath)) return null;
13075
- const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13109
+ const account = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
13076
13110
  return account.defaultAgent || null;
13077
13111
  } catch {
13078
13112
  return null;
@@ -13145,7 +13179,7 @@ app35.use("/vnc-popout.html", logViewerFetch);
13145
13179
  app35.get("/vnc-popout.html", (c) => {
13146
13180
  let html = htmlCache.get("vnc-popout.html");
13147
13181
  if (!html) {
13148
- html = readFileSync19(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13182
+ html = readFileSync20(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13149
13183
  const name = escapeHtml(BRAND.productName);
13150
13184
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
13151
13185
  html = html.replace("</head>", ` ${brandScript}
@@ -13194,20 +13228,6 @@ app35.get("/data", (c) => {
13194
13228
  if (isPublicHost(host)) return c.text("Not found", 404);
13195
13229
  return c.html(cachedHtml("data.html"));
13196
13230
  });
13197
- app35.get("/docs/desktop-code-controls", (c) => {
13198
- const host = (c.req.header("host") ?? "").split(":")[0];
13199
- if (isPublicHost(host)) return c.text("Not found", 404);
13200
- const docsPath = PLATFORM_ROOT7 ? resolve22(PLATFORM_ROOT7, "..", "docs", "desktop-code-controls.md") : resolve22(process.cwd(), "docs", "desktop-code-controls.md");
13201
- if (!existsSync22(docsPath)) {
13202
- console.error(`[docs] desktop-code-controls.md missing at ${docsPath}`);
13203
- return c.text(`docs/desktop-code-controls.md not found at ${docsPath}`, 404);
13204
- }
13205
- const md = readFileSync19(docsPath, "utf-8");
13206
- const escaped = md.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
13207
- return c.html(
13208
- `<!doctype html><meta charset="utf-8"><title>Desktop Code-tab controls</title><style>body{font:14px/1.55 -apple-system,system-ui,sans-serif;max-width:760px;margin:2rem auto;padding:0 1rem;color:#111}pre{white-space:pre-wrap;font:inherit}</style><pre>${escaped}</pre>`
13209
- );
13210
- });
13211
13231
  app35.get("/:slug", async (c, next) => {
13212
13232
  const slug = c.req.param("slug");
13213
13233
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
@@ -13266,7 +13286,7 @@ try {
13266
13286
  (async () => {
13267
13287
  try {
13268
13288
  if (!existsSync22(USERS_FILE)) return;
13269
- const usersRaw = readFileSync19(USERS_FILE, "utf-8").trim();
13289
+ const usersRaw = readFileSync20(USERS_FILE, "utf-8").trim();
13270
13290
  if (!usersRaw) return;
13271
13291
  const users = JSON.parse(usersRaw);
13272
13292
  const userId = users[0]?.userId;
@@ -13392,7 +13412,7 @@ if (bootAccountConfig?.whatsapp) {
13392
13412
  }
13393
13413
  init({
13394
13414
  configDir: configDirForWhatsApp,
13395
- platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
13415
+ platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
13396
13416
  accountConfig: bootAccountConfig,
13397
13417
  onMessage: async (msg) => {
13398
13418
  if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {