@rubytech/create-maxy 1.0.760 → 1.0.761

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.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-DHg5a2u2.js"></script>
8
+ <script type="module" crossorigin src="/assets/admin-GIIfvDj1.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CFleUYzT.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-BEFjQwLd.js">
@@ -47,7 +47,7 @@ import {
47
47
  vncLog,
48
48
  waitForExit,
49
49
  writeChromiumWrapper
50
- } from "./chunk-WW464F23.js";
50
+ } from "./chunk-QXAUMZXQ.js";
51
51
  import {
52
52
  ACCOUNTS_DIR,
53
53
  GREETING_DIRECTIVE,
@@ -77,6 +77,7 @@ import {
77
77
  getGroupSlugForSession,
78
78
  getMessagesSince,
79
79
  getRecentMessages,
80
+ getRoleForSession,
80
81
  getSession,
81
82
  getSessionMessages,
82
83
  getUserIdForSession,
@@ -106,7 +107,7 @@ import {
106
107
  validateSession,
107
108
  verifyAndGetConversationUpdatedAt,
108
109
  verifyConversationOwnership
109
- } from "./chunk-2W7O63CK.js";
110
+ } from "./chunk-43JK6WNK.js";
110
111
 
111
112
  // ../lib/graph-trash/dist/index.js
112
113
  var require_dist = __commonJS({
@@ -606,7 +607,7 @@ var serveStatic = (options = { root: "" }) => {
606
607
 
607
608
  // server/index.ts
608
609
  import { readFileSync as readFileSync16, existsSync as existsSync19, watchFile } from "fs";
609
- import { resolve as resolve20, join as join10, basename as basename7 } from "path";
610
+ import { resolve as resolve21, join as join10, basename as basename7 } from "path";
610
611
  import { homedir as homedir2 } from "os";
611
612
 
612
613
  // app/lib/agent-slug-pattern.ts
@@ -2691,7 +2692,7 @@ var credsSaveQueue = Promise.resolve();
2691
2692
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
2692
2693
  console.error(`${TAG3} draining credential save queue\u2026`);
2693
2694
  const timer2 = new Promise(
2694
- (resolve21) => setTimeout(() => resolve21("timeout"), timeoutMs)
2695
+ (resolve22) => setTimeout(() => resolve22("timeout"), timeoutMs)
2695
2696
  );
2696
2697
  const result = await Promise.race([
2697
2698
  credsSaveQueue.then(() => "drained"),
@@ -2819,11 +2820,11 @@ async function createWaSocket(opts) {
2819
2820
  return sock;
2820
2821
  }
2821
2822
  async function waitForConnection(sock) {
2822
- return new Promise((resolve21, reject) => {
2823
+ return new Promise((resolve22, reject) => {
2823
2824
  const handler = (update) => {
2824
2825
  if (update.connection === "open") {
2825
2826
  sock.ev.off("connection.update", handler);
2826
- resolve21();
2827
+ resolve22();
2827
2828
  }
2828
2829
  if (update.connection === "close") {
2829
2830
  sock.ev.off("connection.update", handler);
@@ -2937,14 +2938,14 @@ ${inspected}`;
2937
2938
  return inspect2(err, INSPECT_OPTS2);
2938
2939
  }
2939
2940
  function withTimeout(label, promise, timeoutMs) {
2940
- return new Promise((resolve21, reject) => {
2941
+ return new Promise((resolve22, reject) => {
2941
2942
  const timer2 = setTimeout(() => {
2942
2943
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2943
2944
  }, timeoutMs);
2944
2945
  promise.then(
2945
2946
  (value) => {
2946
2947
  clearTimeout(timer2);
2947
- resolve21(value);
2948
+ resolve22(value);
2948
2949
  },
2949
2950
  (err) => {
2950
2951
  clearTimeout(timer2);
@@ -4158,11 +4159,11 @@ async function connectWithReconnect(conn) {
4158
4159
  console.error(
4159
4160
  `${TAG11} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
4160
4161
  );
4161
- await new Promise((resolve21) => {
4162
- const timer2 = setTimeout(resolve21, delay);
4162
+ await new Promise((resolve22) => {
4163
+ const timer2 = setTimeout(resolve22, delay);
4163
4164
  conn.abortController.signal.addEventListener("abort", () => {
4164
4165
  clearTimeout(timer2);
4165
- resolve21();
4166
+ resolve22();
4166
4167
  }, { once: true });
4167
4168
  });
4168
4169
  }
@@ -4170,16 +4171,16 @@ async function connectWithReconnect(conn) {
4170
4171
  }
4171
4172
  }
4172
4173
  function waitForDisconnectEvent(conn) {
4173
- return new Promise((resolve21) => {
4174
+ return new Promise((resolve22) => {
4174
4175
  if (!conn.sock) {
4175
- resolve21();
4176
+ resolve22();
4176
4177
  return;
4177
4178
  }
4178
4179
  const sock = conn.sock;
4179
4180
  const handler = (update) => {
4180
4181
  if (update.connection === "close") {
4181
4182
  sock.ev.off("connection.update", handler);
4182
- resolve21();
4183
+ resolve22();
4183
4184
  }
4184
4185
  };
4185
4186
  sock.ev.on("connection.update", handler);
@@ -4396,8 +4397,8 @@ async function handleInboundMessage(conn, msg) {
4396
4397
  const conversationKey = isGroup ? remoteJid : senderPhone;
4397
4398
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
4398
4399
  let resolvePending;
4399
- const sttPending = new Promise((resolve21) => {
4400
- resolvePending = resolve21;
4400
+ const sttPending = new Promise((resolve22) => {
4401
+ resolvePending = resolve22;
4401
4402
  });
4402
4403
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
4403
4404
  try {
@@ -4510,20 +4511,20 @@ async function probeApiKey() {
4510
4511
  return result.status;
4511
4512
  }
4512
4513
  function checkPort(port2, timeoutMs = 500) {
4513
- return new Promise((resolve21) => {
4514
+ return new Promise((resolve22) => {
4514
4515
  const socket = createConnection(port2, "127.0.0.1");
4515
4516
  socket.setTimeout(timeoutMs);
4516
4517
  socket.once("connect", () => {
4517
4518
  socket.destroy();
4518
- resolve21(true);
4519
+ resolve22(true);
4519
4520
  });
4520
4521
  socket.once("error", () => {
4521
4522
  socket.destroy();
4522
- resolve21(false);
4523
+ resolve22(false);
4523
4524
  });
4524
4525
  socket.once("timeout", () => {
4525
4526
  socket.destroy();
4526
- resolve21(false);
4527
+ resolve22(false);
4527
4528
  });
4528
4529
  });
4529
4530
  }
@@ -5042,6 +5043,14 @@ function detectMimeType(filePath) {
5042
5043
  const ext = extname(filePath).toLowerCase();
5043
5044
  return MIME_BY_EXT[ext] ?? "application/octet-stream";
5044
5045
  }
5046
+ function validateFilePathInAccount(filePath, accountDir) {
5047
+ const resolved = realpathSync(filePath);
5048
+ const accountResolved = realpathSync(accountDir);
5049
+ if (!resolved.startsWith(accountResolved + "/")) {
5050
+ throw new Error(`File path is outside the account directory`);
5051
+ }
5052
+ return resolved;
5053
+ }
5045
5054
  async function storeGeneratedFile(accountId, filePath) {
5046
5055
  const fileStat = await stat2(filePath);
5047
5056
  if (fileStat.size > MAX_FILE_SIZE_BYTES) {
@@ -6725,8 +6734,8 @@ async function startLogin(opts) {
6725
6734
  resetActiveLogin(accountId);
6726
6735
  let resolveQr = null;
6727
6736
  let rejectQr = null;
6728
- const qrPromise = new Promise((resolve21, reject) => {
6729
- resolveQr = resolve21;
6737
+ const qrPromise = new Promise((resolve22, reject) => {
6738
+ resolveQr = resolve22;
6730
6739
  rejectQr = reject;
6731
6740
  });
6732
6741
  const qrTimer = setTimeout(
@@ -7705,11 +7714,11 @@ function readUsersFile2() {
7705
7714
  if (!raw) return [];
7706
7715
  return JSON.parse(raw);
7707
7716
  }
7708
- async function createAdminSession(accountId, thinkingView, userId, userName) {
7717
+ async function createAdminSession(accountId, thinkingView, userId, userName, role) {
7709
7718
  const account = resolveAccount();
7710
7719
  const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
7711
7720
  const sessionKey = crypto.randomUUID();
7712
- registerSession(sessionKey, "admin", accountId, void 0, userId, userName);
7721
+ registerSession(sessionKey, "admin", accountId, void 0, userId, userName, role);
7713
7722
  let onboardingComplete = true;
7714
7723
  try {
7715
7724
  const step = await loadOnboardingStep(accountId);
@@ -7724,11 +7733,13 @@ async function createAdminSession(accountId, thinkingView, userId, userName) {
7724
7733
  } catch {
7725
7734
  }
7726
7735
  console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} admin session created: userId=${userId ?? "\u2013"} userName=${userName ?? "\u2013"} accountId=${accountId} conversationId=deferred sessionKey=${sessionKey.slice(0, 8)}`);
7736
+ console.log(`[admin-session] role=${role ?? "null"} sessionKey=${sessionKey.slice(0, 8)} phase=create`);
7727
7737
  return {
7728
7738
  session_key: sessionKey,
7729
7739
  agent_id: "admin",
7730
7740
  userId,
7731
7741
  userName,
7742
+ role: role ?? null,
7732
7743
  thinkingView: effectiveThinkingView,
7733
7744
  onboardingComplete,
7734
7745
  businessName,
@@ -7760,11 +7771,14 @@ app10.get("/", async (c) => {
7760
7771
  businessName = branding?.name || void 0;
7761
7772
  } catch {
7762
7773
  }
7774
+ const role = getRoleForSession(sessionKey);
7775
+ console.log(`[admin-session] role=${role ?? "null"} sessionKey=${sessionKey.slice(0, 8)} phase=restore`);
7763
7776
  return c.json({
7764
7777
  session_key: sessionKey,
7765
7778
  agent_id: "admin",
7766
7779
  userId: getUserIdForSession(sessionKey),
7767
7780
  userName: getUserNameForSession(sessionKey),
7781
+ role: role ?? null,
7768
7782
  thinkingView,
7769
7783
  onboardingComplete,
7770
7784
  businessName,
@@ -7821,7 +7835,7 @@ app10.post("/", async (c) => {
7821
7835
  console.log(`[session] account selection invalid: userId=${userId} requested=${body.accountId}`);
7822
7836
  return c.json({ error: "Invalid account selection." }, 403);
7823
7837
  }
7824
- const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName);
7838
+ const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName, selected.role);
7825
7839
  return c.json(payload);
7826
7840
  });
7827
7841
  var session_default2 = app10;
@@ -8118,7 +8132,7 @@ var app11 = new Hono();
8118
8132
  app11.post("/cancel", requireAdminSession, async (c) => {
8119
8133
  const session_key = c.var.sessionKey;
8120
8134
  try {
8121
- const { interruptClient: interruptClient2 } = await import("./client-pool-TULUIO6M.js");
8135
+ const { interruptClient: interruptClient2 } = await import("./client-pool-SGPHSYLK.js");
8122
8136
  await interruptClient2(session_key);
8123
8137
  return c.json({ ok: true });
8124
8138
  } catch (err) {
@@ -11563,30 +11577,144 @@ app30.get("/", requireAdminSession, async (c) => {
11563
11577
  });
11564
11578
  var adherence_default = app30;
11565
11579
 
11566
- // server/routes/admin/index.ts
11580
+ // server/routes/admin/sidebar-projects.ts
11581
+ var LIMIT = 50;
11567
11582
  var app31 = new Hono();
11568
- app31.route("/session", session_default2);
11569
- app31.route("/chat", chat_default2);
11570
- app31.route("/compact", compact_default);
11571
- app31.route("/logs", logs_default);
11572
- app31.route("/claude-info", claude_info_default);
11573
- app31.route("/attachment", attachment_default);
11574
- app31.route("/agents", agents_default);
11575
- app31.route("/sessions", sessions_default);
11576
- app31.route("/browser", browser_default);
11577
- app31.route("/device-browser", device_browser_default);
11578
- app31.route("/events", events_default);
11579
- app31.route("/cloudflare", cloudflare_default);
11580
- app31.route("/files", files_default);
11581
- app31.route("/graph-search", graph_search_default);
11582
- app31.route("/graph-subgraph", graph_subgraph_default);
11583
- app31.route("/graph-delete", graph_delete_default);
11584
- app31.route("/graph-restore", graph_restore_default);
11585
- app31.route("/graph-labels-in-graph", graph_labels_in_graph_default);
11586
- app31.route("/graph-default-view", graph_default_view_default);
11587
- app31.route("/file-attach", file_attach_default);
11588
- app31.route("/adherence", adherence_default);
11589
- var admin_default = app31;
11583
+ app31.get("/", requireAdminSession, async (c) => {
11584
+ const sessionKey = c.var.sessionKey;
11585
+ const accountId = getAccountIdForSession(sessionKey);
11586
+ if (!accountId) {
11587
+ return c.json({ error: "Account not found for session" }, 401);
11588
+ }
11589
+ const start = Date.now();
11590
+ const session = getSession();
11591
+ try {
11592
+ const result = await session.run(
11593
+ `MATCH (p:Project { accountId: $accountId })
11594
+ WHERE NOT p:Trashed
11595
+ RETURN p.taskId AS id, p.name AS name, p.updatedAt AS updatedAt
11596
+ ORDER BY p.updatedAt DESC
11597
+ LIMIT $limit`,
11598
+ { accountId, limit: LIMIT }
11599
+ );
11600
+ const projects = result.records.map((r) => ({
11601
+ id: r.get("id"),
11602
+ name: r.get("name") ?? "",
11603
+ updatedAt: r.get("updatedAt") ?? ""
11604
+ }));
11605
+ const ms = Date.now() - start;
11606
+ console.log(`[admin/sidebar-projects] account=${accountId} count=${projects.length} ms=${ms}`);
11607
+ return c.json({ projects });
11608
+ } catch (err) {
11609
+ const ms = Date.now() - start;
11610
+ const message = err instanceof Error ? err.message : String(err);
11611
+ console.error(`[admin/sidebar-projects] account=${accountId} error="${message}" ms=${ms}`);
11612
+ return c.json({ error: "Failed to load projects" }, 500);
11613
+ } finally {
11614
+ await session.close();
11615
+ }
11616
+ });
11617
+ var sidebar_projects_default = app31;
11618
+
11619
+ // server/routes/admin/sidebar-artefacts.ts
11620
+ import { readFile as readFile5, readdir as readdir3 } from "fs/promises";
11621
+ import { resolve as resolve20 } from "path";
11622
+ var LIMIT2 = 50;
11623
+ var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
11624
+ var app32 = new Hono();
11625
+ app32.get("/", requireAdminSession, async (c) => {
11626
+ const sessionKey = c.var.sessionKey;
11627
+ const accountId = getAccountIdForSession(sessionKey);
11628
+ if (!accountId) {
11629
+ return c.json({ error: "Account not found for session" }, 401);
11630
+ }
11631
+ const start = Date.now();
11632
+ const session = getSession();
11633
+ let metas = [];
11634
+ try {
11635
+ const result = await session.run(
11636
+ `MATCH (d:KnowledgeDocument { accountId: $accountId })
11637
+ WHERE d.deletedAt IS NULL AND NOT d:Trashed
11638
+ RETURN d.attachmentId AS id, d.name AS name, d.updatedAt AS updatedAt,
11639
+ d.attachmentId AS attachmentId, d.encodingFormat AS mimeType
11640
+ ORDER BY d.updatedAt DESC
11641
+ LIMIT $limit`,
11642
+ { accountId, limit: LIMIT2 }
11643
+ );
11644
+ metas = result.records.map((r) => ({
11645
+ id: r.get("id"),
11646
+ name: r.get("name") ?? "",
11647
+ updatedAt: r.get("updatedAt") ?? "",
11648
+ attachmentId: r.get("attachmentId"),
11649
+ mimeType: r.get("mimeType") ?? ""
11650
+ }));
11651
+ } catch (err) {
11652
+ const ms2 = Date.now() - start;
11653
+ const message = err instanceof Error ? err.message : String(err);
11654
+ console.error(`[admin/sidebar-artefacts] account=${accountId} error="${message}" ms=${ms2}`);
11655
+ await session.close();
11656
+ return c.json({ error: "Failed to load artefacts" }, 500);
11657
+ } finally {
11658
+ await session.close();
11659
+ }
11660
+ const artefacts = await Promise.all(metas.map(async (m) => {
11661
+ const content = await readArtefactContent(accountId, m.attachmentId, m.mimeType);
11662
+ return { id: m.id, name: m.name, updatedAt: m.updatedAt, content };
11663
+ }));
11664
+ const ms = Date.now() - start;
11665
+ console.log(`[admin/sidebar-artefacts] account=${accountId} count=${artefacts.length} ms=${ms}`);
11666
+ return c.json({ artefacts });
11667
+ });
11668
+ async function readArtefactContent(accountId, attachmentId, mimeType) {
11669
+ if (!attachmentId) return "";
11670
+ const isText = TEXT_MIME_PREFIXES.some((p) => mimeType.startsWith(p));
11671
+ if (!isText) return "";
11672
+ const accountDir = resolve20(ATTACHMENTS_ROOT, accountId);
11673
+ const dir = resolve20(accountDir, attachmentId);
11674
+ try {
11675
+ validateFilePathInAccount(dir, accountDir);
11676
+ } catch {
11677
+ return "";
11678
+ }
11679
+ try {
11680
+ const entries = await readdir3(dir);
11681
+ const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
11682
+ if (!dataFile) return "";
11683
+ return await readFile5(resolve20(dir, dataFile), "utf-8");
11684
+ } catch (err) {
11685
+ const message = err instanceof Error ? err.message : String(err);
11686
+ console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
11687
+ return "";
11688
+ }
11689
+ }
11690
+ var sidebar_artefacts_default = app32;
11691
+
11692
+ // server/routes/admin/index.ts
11693
+ var app33 = new Hono();
11694
+ app33.route("/session", session_default2);
11695
+ app33.route("/chat", chat_default2);
11696
+ app33.route("/compact", compact_default);
11697
+ app33.route("/logs", logs_default);
11698
+ app33.route("/claude-info", claude_info_default);
11699
+ app33.route("/attachment", attachment_default);
11700
+ app33.route("/agents", agents_default);
11701
+ app33.route("/sessions", sessions_default);
11702
+ app33.route("/browser", browser_default);
11703
+ app33.route("/device-browser", device_browser_default);
11704
+ app33.route("/events", events_default);
11705
+ app33.route("/cloudflare", cloudflare_default);
11706
+ app33.route("/files", files_default);
11707
+ app33.route("/graph-search", graph_search_default);
11708
+ app33.route("/graph-subgraph", graph_subgraph_default);
11709
+ app33.route("/graph-delete", graph_delete_default);
11710
+ app33.route("/graph-restore", graph_restore_default);
11711
+ app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
11712
+ app33.route("/graph-default-view", graph_default_view_default);
11713
+ app33.route("/file-attach", file_attach_default);
11714
+ app33.route("/adherence", adherence_default);
11715
+ app33.route("/sidebar-projects", sidebar_projects_default);
11716
+ app33.route("/sidebar-artefacts", sidebar_artefacts_default);
11717
+ var admin_default = app33;
11590
11718
 
11591
11719
  // app/lib/graph-health.ts
11592
11720
  var HOUR_MS = 60 * 60 * 1e3;
@@ -11740,9 +11868,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
11740
11868
  function isPublicHost(host) {
11741
11869
  return host.startsWith("public.") || aliasDomains.has(host);
11742
11870
  }
11743
- var app32 = new Hono();
11744
- app32.use("*", clientIpMiddleware);
11745
- app32.use("*", async (c, next) => {
11871
+ var app34 = new Hono();
11872
+ app34.use("*", clientIpMiddleware);
11873
+ app34.use("*", async (c, next) => {
11746
11874
  await next();
11747
11875
  c.header("X-Content-Type-Options", "nosniff");
11748
11876
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -11765,7 +11893,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
11765
11893
  "/g/"
11766
11894
  ];
11767
11895
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
11768
- app32.use("*", async (c, next) => {
11896
+ app34.use("*", async (c, next) => {
11769
11897
  const host = (c.req.header("host") ?? "").split(":")[0];
11770
11898
  if (!isPublicHost(host)) {
11771
11899
  await next();
@@ -11805,7 +11933,7 @@ function resolveRemoteAuthOpts() {
11805
11933
  return brandLoginOpts;
11806
11934
  }
11807
11935
  var MAX_LOGIN_BODY = 8 * 1024;
11808
- app32.post("/__remote-auth/login", async (c) => {
11936
+ app34.post("/__remote-auth/login", async (c) => {
11809
11937
  const client = clientFrom(c);
11810
11938
  const clientIp = client.ip || "unknown";
11811
11939
  if (!requestIsTlsTerminated(c)) {
@@ -11849,7 +11977,7 @@ app32.post("/__remote-auth/login", async (c) => {
11849
11977
  }
11850
11978
  });
11851
11979
  });
11852
- app32.get("/__remote-auth/logout", (c) => {
11980
+ app34.get("/__remote-auth/logout", (c) => {
11853
11981
  return new Response(null, {
11854
11982
  status: 302,
11855
11983
  headers: {
@@ -11859,7 +11987,7 @@ app32.get("/__remote-auth/logout", (c) => {
11859
11987
  }
11860
11988
  });
11861
11989
  });
11862
- app32.post("/__remote-auth/change-password", async (c) => {
11990
+ app34.post("/__remote-auth/change-password", async (c) => {
11863
11991
  const client = clientFrom(c);
11864
11992
  const clientIp = client.ip || "unknown";
11865
11993
  const rateLimited = checkRateLimit(client);
@@ -11909,13 +12037,13 @@ app32.post("/__remote-auth/change-password", async (c) => {
11909
12037
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
11910
12038
  }
11911
12039
  });
11912
- app32.get("/__remote-auth/setup", (c) => {
12040
+ app34.get("/__remote-auth/setup", (c) => {
11913
12041
  if (isRemoteAuthConfigured()) {
11914
12042
  return c.redirect("/");
11915
12043
  }
11916
12044
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
11917
12045
  });
11918
- app32.post("/__remote-auth/set-initial-password", async (c) => {
12046
+ app34.post("/__remote-auth/set-initial-password", async (c) => {
11919
12047
  if (isRemoteAuthConfigured()) {
11920
12048
  return c.redirect("/");
11921
12049
  }
@@ -11951,10 +12079,10 @@ app32.post("/__remote-auth/set-initial-password", async (c) => {
11951
12079
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
11952
12080
  }
11953
12081
  });
11954
- app32.get("/api/remote-auth/status", (c) => {
12082
+ app34.get("/api/remote-auth/status", (c) => {
11955
12083
  return c.json({ configured: isRemoteAuthConfigured() });
11956
12084
  });
11957
- app32.post("/api/remote-auth/set-password", async (c) => {
12085
+ app34.post("/api/remote-auth/set-password", async (c) => {
11958
12086
  let body;
11959
12087
  try {
11960
12088
  body = await c.req.json();
@@ -11984,9 +12112,9 @@ app32.post("/api/remote-auth/set-password", async (c) => {
11984
12112
  return c.json({ error: "Failed to save password" }, 500);
11985
12113
  }
11986
12114
  });
11987
- app32.route("/api/_client-error", client_error_default);
12115
+ app34.route("/api/_client-error", client_error_default);
11988
12116
  console.log("[client-error-route] mounted");
11989
- app32.use("*", async (c, next) => {
12117
+ app34.use("*", async (c, next) => {
11990
12118
  const host = (c.req.header("host") ?? "").split(":")[0];
11991
12119
  const path2 = c.req.path;
11992
12120
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -12019,15 +12147,15 @@ app32.use("*", async (c, next) => {
12019
12147
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
12020
12148
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
12021
12149
  });
12022
- app32.route("/api/health", health_default);
12023
- app32.route("/api/session", session_default);
12024
- app32.route("/api/chat", chat_default);
12025
- app32.route("/api/group", group_default);
12026
- app32.route("/api/access", access_default);
12027
- app32.route("/api/telegram", telegram_default);
12028
- app32.route("/api/whatsapp", whatsapp_default);
12029
- app32.route("/api/onboarding", onboarding_default);
12030
- app32.route("/api/admin", admin_default);
12150
+ app34.route("/api/health", health_default);
12151
+ app34.route("/api/session", session_default);
12152
+ app34.route("/api/chat", chat_default);
12153
+ app34.route("/api/group", group_default);
12154
+ app34.route("/api/access", access_default);
12155
+ app34.route("/api/telegram", telegram_default);
12156
+ app34.route("/api/whatsapp", whatsapp_default);
12157
+ app34.route("/api/onboarding", onboarding_default);
12158
+ app34.route("/api/admin", admin_default);
12031
12159
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
12032
12160
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12033
12161
  var IMAGE_MIME = {
@@ -12039,7 +12167,7 @@ var IMAGE_MIME = {
12039
12167
  ".svg": "image/svg+xml",
12040
12168
  ".ico": "image/x-icon"
12041
12169
  };
12042
- app32.get("/agent-assets/:slug/:filename", (c) => {
12170
+ app34.get("/agent-assets/:slug/:filename", (c) => {
12043
12171
  const slug = c.req.param("slug");
12044
12172
  const filename = c.req.param("filename");
12045
12173
  if (!SAFE_SLUG_RE.test(slug)) {
@@ -12055,8 +12183,8 @@ app32.get("/agent-assets/:slug/:filename", (c) => {
12055
12183
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
12056
12184
  return c.text("Not found", 404);
12057
12185
  }
12058
- const filePath = resolve20(account.accountDir, "agents", slug, "assets", filename);
12059
- const expectedDir = resolve20(account.accountDir, "agents", slug, "assets");
12186
+ const filePath = resolve21(account.accountDir, "agents", slug, "assets", filename);
12187
+ const expectedDir = resolve21(account.accountDir, "agents", slug, "assets");
12060
12188
  if (!filePath.startsWith(expectedDir + "/")) {
12061
12189
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
12062
12190
  return c.text("Forbidden", 403);
@@ -12074,7 +12202,7 @@ app32.get("/agent-assets/:slug/:filename", (c) => {
12074
12202
  "Cache-Control": "public, max-age=3600"
12075
12203
  });
12076
12204
  });
12077
- app32.get("/generated/:filename", (c) => {
12205
+ app34.get("/generated/:filename", (c) => {
12078
12206
  const filename = c.req.param("filename");
12079
12207
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
12080
12208
  console.error(`[generated] serve file=${filename} status=403`);
@@ -12085,8 +12213,8 @@ app32.get("/generated/:filename", (c) => {
12085
12213
  console.error(`[generated] serve file=${filename} status=404`);
12086
12214
  return c.text("Not found", 404);
12087
12215
  }
12088
- const filePath = resolve20(account.accountDir, "generated", filename);
12089
- const expectedDir = resolve20(account.accountDir, "generated");
12216
+ const filePath = resolve21(account.accountDir, "generated", filename);
12217
+ const expectedDir = resolve21(account.accountDir, "generated");
12090
12218
  if (!filePath.startsWith(expectedDir + "/")) {
12091
12219
  console.error(`[generated] serve file=${filename} status=403`);
12092
12220
  return c.text("Forbidden", 403);
@@ -12169,7 +12297,7 @@ var clientErrorReporterScript = `<script>
12169
12297
  function cachedHtml(file) {
12170
12298
  let html = htmlCache.get(file);
12171
12299
  if (!html) {
12172
- html = readFileSync16(resolve20(process.cwd(), "public", file), "utf-8");
12300
+ html = readFileSync16(resolve21(process.cwd(), "public", file), "utf-8");
12173
12301
  const productNameEsc = escapeHtml(BRAND.productName);
12174
12302
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
12175
12303
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -12240,7 +12368,7 @@ function brandedPublicHtml(agentSlug) {
12240
12368
  function escapeHtml(s) {
12241
12369
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
12242
12370
  }
12243
- app32.get("/", (c) => {
12371
+ app34.get("/", (c) => {
12244
12372
  const host = (c.req.header("host") ?? "").split(":")[0];
12245
12373
  if (isPublicHost(host)) {
12246
12374
  const defaultSlug = resolveDefaultSlug();
@@ -12248,12 +12376,12 @@ app32.get("/", (c) => {
12248
12376
  }
12249
12377
  return c.html(cachedHtml("index.html"));
12250
12378
  });
12251
- app32.get("/public", (c) => {
12379
+ app34.get("/public", (c) => {
12252
12380
  const host = (c.req.header("host") ?? "").split(":")[0];
12253
12381
  if (isPublicHost(host)) return c.text("Not found", 404);
12254
12382
  return c.html(cachedHtml("public.html"));
12255
12383
  });
12256
- app32.get("/chat", (c) => {
12384
+ app34.get("/chat", (c) => {
12257
12385
  const host = (c.req.header("host") ?? "").split(":")[0];
12258
12386
  if (isPublicHost(host)) return c.text("Not found", 404);
12259
12387
  return c.html(cachedHtml("public.html"));
@@ -12272,12 +12400,12 @@ async function logViewerFetch(c, next) {
12272
12400
  duration_ms: Date.now() - start
12273
12401
  });
12274
12402
  }
12275
- app32.use("/vnc-viewer.html", logViewerFetch);
12276
- app32.use("/vnc-popout.html", logViewerFetch);
12277
- app32.get("/vnc-popout.html", (c) => {
12403
+ app34.use("/vnc-viewer.html", logViewerFetch);
12404
+ app34.use("/vnc-popout.html", logViewerFetch);
12405
+ app34.get("/vnc-popout.html", (c) => {
12278
12406
  let html = htmlCache.get("vnc-popout.html");
12279
12407
  if (!html) {
12280
- html = readFileSync16(resolve20(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12408
+ html = readFileSync16(resolve21(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12281
12409
  const name = escapeHtml(BRAND.productName);
12282
12410
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
12283
12411
  html = html.replace("</head>", ` ${brandScript}
@@ -12287,7 +12415,7 @@ app32.get("/vnc-popout.html", (c) => {
12287
12415
  }
12288
12416
  return c.html(html);
12289
12417
  });
12290
- app32.post("/api/vnc/client-event", async (c) => {
12418
+ app34.post("/api/vnc/client-event", async (c) => {
12291
12419
  let body;
12292
12420
  try {
12293
12421
  body = await c.req.json();
@@ -12308,20 +12436,20 @@ app32.post("/api/vnc/client-event", async (c) => {
12308
12436
  });
12309
12437
  return c.json({ ok: true });
12310
12438
  });
12311
- app32.get("/g/:slug", (c) => {
12439
+ app34.get("/g/:slug", (c) => {
12312
12440
  return c.html(brandedPublicHtml());
12313
12441
  });
12314
- app32.get("/graph", (c) => {
12442
+ app34.get("/graph", (c) => {
12315
12443
  const host = (c.req.header("host") ?? "").split(":")[0];
12316
12444
  if (isPublicHost(host)) return c.text("Not found", 404);
12317
12445
  return c.html(cachedHtml("graph.html"));
12318
12446
  });
12319
- app32.get("/data", (c) => {
12447
+ app34.get("/data", (c) => {
12320
12448
  const host = (c.req.header("host") ?? "").split(":")[0];
12321
12449
  if (isPublicHost(host)) return c.text("Not found", 404);
12322
12450
  return c.html(cachedHtml("data.html"));
12323
12451
  });
12324
- app32.get("/:slug", async (c, next) => {
12452
+ app34.get("/:slug", async (c, next) => {
12325
12453
  const slug = c.req.param("slug");
12326
12454
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
12327
12455
  const branding = loadBrandingCache(slug);
@@ -12330,10 +12458,10 @@ app32.get("/:slug", async (c, next) => {
12330
12458
  }
12331
12459
  await next();
12332
12460
  });
12333
- app32.use("/*", serveStatic({ root: "./public" }));
12461
+ app34.use("/*", serveStatic({ root: "./public" }));
12334
12462
  var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
12335
12463
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
12336
- var httpServer = serve({ fetch: app32.fetch, port, hostname });
12464
+ var httpServer = serve({ fetch: app34.fetch, port, hostname });
12337
12465
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
12338
12466
  var SUBAPP_MANIFEST = [
12339
12467
  { prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
@@ -12353,7 +12481,7 @@ for (const m of SUBAPP_MANIFEST) {
12353
12481
  }
12354
12482
  try {
12355
12483
  const registered = [];
12356
- for (const r of app32.routes ?? []) {
12484
+ for (const r of app34.routes ?? []) {
12357
12485
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
12358
12486
  if (AGENT_SLUG_PATTERN.test(r.path)) {
12359
12487
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -12420,7 +12548,7 @@ if (bootAccountConfig?.whatsapp) {
12420
12548
  }
12421
12549
  init({
12422
12550
  configDir: configDirForWhatsApp,
12423
- platformRoot: resolve20(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
12551
+ platformRoot: resolve21(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
12424
12552
  accountConfig: bootAccountConfig,
12425
12553
  onMessage: async (msg) => {
12426
12554
  try {