@rubytech/create-maxy 1.0.660 → 1.0.662

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 (21) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +18 -0
  3. package/payload/platform/plugins/docs/references/memory-guide.md +4 -2
  4. package/payload/platform/plugins/docs/references/platform.md +4 -0
  5. package/payload/platform/plugins/docs/references/troubleshooting.md +20 -4
  6. package/payload/server/public/assets/{admin-BFIYSS4u.js → admin-C9qoVb2l.js} +63 -63
  7. package/payload/server/public/assets/{data-BmeeI1Ix.js → data-C-WE3FGr.js} +1 -1
  8. package/payload/server/public/assets/{file-D4Qulqz_.js → file-lmzx24EO.js} +1 -1
  9. package/payload/server/public/assets/{graph-MoIys9Ub.js → graph-Bcao42cE.js} +17 -17
  10. package/payload/server/public/assets/{house-B0Hukxjp.js → house-ClhI06TA.js} +1 -1
  11. package/payload/server/public/assets/{jsx-runtime-C6owBiFB.css → jsx-runtime-CLCFnMYD.css} +1 -1
  12. package/payload/server/public/assets/{public-LvjJTLGn.js → public-Dz33-dIE.js} +1 -1
  13. package/payload/server/public/assets/{share-2-BafZBLp9.js → share-2-MZ4MqbjS.js} +1 -1
  14. package/payload/server/public/assets/{useVoiceRecorder-dLOpmcYJ.js → useVoiceRecorder-Cm0G51D_.js} +1 -1
  15. package/payload/server/public/assets/{x-BOZIeV0f.js → x-CLhtM_Mh.js} +1 -1
  16. package/payload/server/public/data.html +6 -6
  17. package/payload/server/public/graph.html +6 -6
  18. package/payload/server/public/index.html +7 -7
  19. package/payload/server/public/public.html +4 -4
  20. package/payload/server/server.js +277 -72
  21. /package/payload/server/public/assets/{jsx-runtime-CmCvZzVE.js → jsx-runtime-ImbU973I.js} +0 -0
@@ -1201,14 +1201,14 @@ var Hono = class _Hono {
1201
1201
  * app.route("/api", app2) // GET /api/user
1202
1202
  * ```
1203
1203
  */
1204
- route(path2, app33) {
1204
+ route(path2, app35) {
1205
1205
  const subApp = this.basePath(path2);
1206
- app33.routes.map((r) => {
1206
+ app35.routes.map((r) => {
1207
1207
  let handler;
1208
- if (app33.errorHandler === errorHandler) {
1208
+ if (app35.errorHandler === errorHandler) {
1209
1209
  handler = r.handler;
1210
1210
  } else {
1211
- handler = async (c, next) => (await compose([], app33.errorHandler)(c, () => r.handler(c, next))).res;
1211
+ handler = async (c, next) => (await compose([], app35.errorHandler)(c, () => r.handler(c, next))).res;
1212
1212
  handler[COMPOSED_HANDLER] = r.handler;
1213
1213
  }
1214
1214
  subApp.#addRoute(r.method, r.path, handler);
@@ -3855,6 +3855,8 @@ function terminalLog(phase, fields = {}) {
3855
3855
  // server/ws-proxy-terminal.ts
3856
3856
  var WS_PATH2 = "/admin/terminal/ws";
3857
3857
  var UPSTREAM_TIMEOUT_MS2 = 5e3;
3858
+ var FLOW_TICK_MS = 5e3;
3859
+ var FLOW_IDLE_EMIT_MS = 3e4;
3858
3860
  var HOP_BY_HOP2 = /* @__PURE__ */ new Set([
3859
3861
  "connection",
3860
3862
  "keep-alive",
@@ -3979,9 +3981,17 @@ function handleUpgrade2(req, clientSocket, head, opts) {
3979
3981
  let bytesUpstreamToClient = 0;
3980
3982
  let closedBy = null;
3981
3983
  let proxyOpened = false;
3984
+ let lastUpstreamByteTs = 0;
3985
+ let flowInterval = null;
3986
+ let lastEmittedAt = 0;
3987
+ let lastEmittedUpstreamBytes = 0;
3982
3988
  const finish = (side, reason) => {
3983
3989
  if (closedBy) return;
3984
3990
  closedBy = side;
3991
+ if (flowInterval) {
3992
+ clearInterval(flowInterval);
3993
+ flowInterval = null;
3994
+ }
3985
3995
  if (proxyOpened) {
3986
3996
  terminalLog("proxy-close", {
3987
3997
  corrId,
@@ -4025,9 +4035,28 @@ function handleUpgrade2(req, clientSocket, head, opts) {
4025
4035
  });
4026
4036
  upstream.on("data", (chunk) => {
4027
4037
  bytesUpstreamToClient += chunk.length;
4038
+ lastUpstreamByteTs = Date.now();
4028
4039
  });
4029
4040
  clientSocket.pipe(upstream);
4030
4041
  upstream.pipe(clientSocket);
4042
+ lastEmittedAt = Date.now();
4043
+ lastEmittedUpstreamBytes = 0;
4044
+ flowInterval = setInterval(() => {
4045
+ const now = Date.now();
4046
+ const idleMs = lastUpstreamByteTs === 0 ? now - lastEmittedAt : now - lastUpstreamByteTs;
4047
+ const upstreamMoved = bytesUpstreamToClient !== lastEmittedUpstreamBytes;
4048
+ const sinceLastEmit = now - lastEmittedAt;
4049
+ if (upstreamMoved || sinceLastEmit >= FLOW_IDLE_EMIT_MS) {
4050
+ terminalLog("proxy-flow", {
4051
+ corrId,
4052
+ clientBytes: bytesClientToUpstream,
4053
+ upstreamBytes: bytesUpstreamToClient,
4054
+ idleMs
4055
+ });
4056
+ lastEmittedAt = now;
4057
+ lastEmittedUpstreamBytes = bytesUpstreamToClient;
4058
+ }
4059
+ }, FLOW_TICK_MS);
4031
4060
  clientSocket.once("close", (hadError) => {
4032
4061
  finish("client", hadError ? "error" : "normal");
4033
4062
  });
@@ -20870,7 +20899,7 @@ var ALL_GRAPH_LABELS = Object.freeze(
20870
20899
  Object.keys(GRAPH_LABEL_COLOURS)
20871
20900
  );
20872
20901
  var HIDDEN_BY_DEFAULT_LABELS = Object.freeze(
20873
- /* @__PURE__ */ new Set(["Chunk"])
20902
+ /* @__PURE__ */ new Set(["Chunk", "GraphPreference"])
20874
20903
  );
20875
20904
  function isKnownLabel(label) {
20876
20905
  return Object.prototype.hasOwnProperty.call(GRAPH_LABEL_COLOURS, label);
@@ -21270,9 +21299,183 @@ app28.post("/", requireAdminSession, async (c) => {
21270
21299
  });
21271
21300
  var graph_restore_default = app28;
21272
21301
 
21273
- // server/routes/admin/file-attach.ts
21302
+ // server/routes/admin/graph-labels-in-graph.ts
21274
21303
  var app29 = new Hono2();
21275
- app29.post("/", async (c) => {
21304
+ app29.get("/", requireAdminSession, async (c) => {
21305
+ const sessionKey = c.var.sessionKey;
21306
+ const accountId = getAccountIdForSession(sessionKey);
21307
+ if (!accountId) {
21308
+ console.error('[graph-page] labels-in-graph-rejected reason="no account for session"');
21309
+ return c.json({ error: "Account not found for session" }, 401);
21310
+ }
21311
+ const started = Date.now();
21312
+ const session = getSession();
21313
+ try {
21314
+ const hidden = [...HIDDEN_BY_DEFAULT_LABELS];
21315
+ const result = await session.executeRead(async (tx) => {
21316
+ return await tx.run(LABELS_IN_GRAPH_CYPHER, { accountId, hidden });
21317
+ });
21318
+ const record = result.records[0];
21319
+ const rawLabels = record?.get("labels") ?? [];
21320
+ const labels = [...new Set(rawLabels)].sort();
21321
+ const elapsed = Date.now() - started;
21322
+ console.error(
21323
+ `[graph-page] labels-in-graph account=${accountId} labels=${labels.join(",")} ms=${elapsed}`
21324
+ );
21325
+ return c.json({ labels });
21326
+ } catch (err) {
21327
+ const elapsed = Date.now() - started;
21328
+ const message = err instanceof Error ? err.message : String(err);
21329
+ console.error(
21330
+ `[graph-page] labels-in-graph-rejected account=${accountId} reason="${message}" ms=${elapsed}`
21331
+ );
21332
+ return c.json({ error: `Graph labels unavailable: ${message}` }, 503);
21333
+ } finally {
21334
+ try {
21335
+ await session.close();
21336
+ } catch {
21337
+ }
21338
+ }
21339
+ });
21340
+ var LABELS_IN_GRAPH_CYPHER = `
21341
+ MATCH (n)
21342
+ WHERE n.accountId = $accountId
21343
+ AND NOT n:Trashed
21344
+ AND n.deletedAt IS NULL
21345
+ UNWIND labels(n) AS lbl
21346
+ WITH DISTINCT lbl
21347
+ WHERE NOT lbl IN $hidden
21348
+ RETURN collect(lbl) AS labels
21349
+ `;
21350
+ var graph_labels_in_graph_default = app29;
21351
+
21352
+ // server/routes/admin/graph-default-view.ts
21353
+ var app30 = new Hono2();
21354
+ app30.get("/", requireAdminSession, async (c) => {
21355
+ const sessionKey = c.var.sessionKey;
21356
+ const accountId = getAccountIdForSession(sessionKey);
21357
+ const userId = getUserIdForSession(sessionKey);
21358
+ if (!accountId || !userId) {
21359
+ console.error('[graph-page] default-view-rejected reason="missing account or user context"');
21360
+ return c.json({ error: "Account and user context required for default view" }, 401);
21361
+ }
21362
+ const started = Date.now();
21363
+ const session = getSession();
21364
+ try {
21365
+ const result = await session.executeRead(async (tx) => {
21366
+ return await tx.run(READ_CYPHER, { accountId, userId });
21367
+ });
21368
+ const record = result.records[0];
21369
+ const rawLabels = record?.get("labels");
21370
+ const rawIncludeTrashed = record?.get("includeTrashed");
21371
+ const labels = Array.isArray(rawLabels) ? rawLabels : [];
21372
+ const includeTrashed = rawIncludeTrashed === true;
21373
+ const elapsed = Date.now() - started;
21374
+ console.error(
21375
+ `[graph-page] default-view-load account=${accountId} labels=${labels.join(",")} includeTrashed=${includeTrashed ? 1 : 0} ms=${elapsed}`
21376
+ );
21377
+ return c.json({ labels, includeTrashed });
21378
+ } catch (err) {
21379
+ const elapsed = Date.now() - started;
21380
+ const message = err instanceof Error ? err.message : String(err);
21381
+ console.error(
21382
+ `[graph-page] default-view-rejected op=load account=${accountId} reason="${message}" ms=${elapsed}`
21383
+ );
21384
+ return c.json({ error: `Graph default view unavailable: ${message}` }, 503);
21385
+ } finally {
21386
+ try {
21387
+ await session.close();
21388
+ } catch {
21389
+ }
21390
+ }
21391
+ });
21392
+ app30.put("/", requireAdminSession, async (c) => {
21393
+ const sessionKey = c.var.sessionKey;
21394
+ const accountId = getAccountIdForSession(sessionKey);
21395
+ const userId = getUserIdForSession(sessionKey);
21396
+ if (!accountId || !userId) {
21397
+ console.error('[graph-page] default-view-rejected reason="missing account or user context"');
21398
+ return c.json({ error: "Account and user context required for default view" }, 401);
21399
+ }
21400
+ const body = await safeJson(c);
21401
+ if (!body) {
21402
+ return c.json({ error: "Request body must be JSON" }, 400);
21403
+ }
21404
+ const validation = validateBody2(body);
21405
+ if (!validation.ok) {
21406
+ console.error(
21407
+ `[graph-page] default-view-rejected op=save account=${accountId} reason="${validation.reason}"`
21408
+ );
21409
+ return c.json({ error: validation.reason }, 400);
21410
+ }
21411
+ const { labels, includeTrashed } = validation;
21412
+ const session = getSession();
21413
+ try {
21414
+ await session.executeWrite(async (tx) => {
21415
+ return await tx.run(WRITE_CYPHER, {
21416
+ accountId,
21417
+ userId,
21418
+ labels,
21419
+ includeTrashed,
21420
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
21421
+ });
21422
+ });
21423
+ console.error(
21424
+ `[graph-page] default-view-save account=${accountId} labels=${labels.join(",")} includeTrashed=${includeTrashed ? 1 : 0}`
21425
+ );
21426
+ return c.json({ labels, includeTrashed });
21427
+ } catch (err) {
21428
+ const message = err instanceof Error ? err.message : String(err);
21429
+ console.error(
21430
+ `[graph-page] default-view-rejected op=save account=${accountId} reason="${message}"`
21431
+ );
21432
+ return c.json({ error: `Failed to save graph default view: ${message}` }, 503);
21433
+ } finally {
21434
+ try {
21435
+ await session.close();
21436
+ } catch {
21437
+ }
21438
+ }
21439
+ });
21440
+ function validateBody2(body) {
21441
+ if (!Array.isArray(body.labels)) {
21442
+ return { ok: false, reason: "labels must be an array of strings" };
21443
+ }
21444
+ if (typeof body.includeTrashed !== "boolean") {
21445
+ return { ok: false, reason: "includeTrashed must be a boolean" };
21446
+ }
21447
+ const seen = /* @__PURE__ */ new Set();
21448
+ for (const lbl of body.labels) {
21449
+ if (typeof lbl !== "string") {
21450
+ return { ok: false, reason: "labels must be an array of strings" };
21451
+ }
21452
+ if (!isKnownLabel(lbl)) {
21453
+ return { ok: false, reason: `unknown label "${lbl}" \u2014 not registered in graph-labels.ts` };
21454
+ }
21455
+ if (isHiddenByDefault(lbl)) {
21456
+ return { ok: false, reason: `label "${lbl}" is hidden by default and cannot be a default view selection` };
21457
+ }
21458
+ seen.add(lbl);
21459
+ }
21460
+ const labels = [...seen].sort();
21461
+ return { ok: true, labels, includeTrashed: body.includeTrashed };
21462
+ }
21463
+ var READ_CYPHER = `
21464
+ OPTIONAL MATCH (p:GraphPreference {accountId: $accountId, userId: $userId})
21465
+ RETURN p.labels AS labels, p.includeTrashed AS includeTrashed
21466
+ `;
21467
+ var WRITE_CYPHER = `
21468
+ MERGE (p:GraphPreference {accountId: $accountId, userId: $userId})
21469
+ SET p.labels = $labels,
21470
+ p.includeTrashed = $includeTrashed,
21471
+ p.updatedAt = $updatedAt
21472
+ RETURN p.labels AS labels
21473
+ `;
21474
+ var graph_default_view_default = app30;
21475
+
21476
+ // server/routes/admin/file-attach.ts
21477
+ var app31 = new Hono2();
21478
+ app31.post("/", async (c) => {
21276
21479
  try {
21277
21480
  const body = await c.req.json();
21278
21481
  const { filePath, accountId } = body;
@@ -21295,11 +21498,11 @@ app29.post("/", async (c) => {
21295
21498
  return c.json({ error: message }, 500);
21296
21499
  }
21297
21500
  });
21298
- var file_attach_default = app29;
21501
+ var file_attach_default = app31;
21299
21502
 
21300
21503
  // server/routes/admin/adherence.ts
21301
- var app30 = new Hono2();
21302
- app30.get("/", requireAdminSession, async (c) => {
21504
+ var app32 = new Hono2();
21505
+ app32.get("/", requireAdminSession, async (c) => {
21303
21506
  const agent = c.req.query("agent") ?? "admin";
21304
21507
  const includeBlock = c.req.query("block") === "1";
21305
21508
  const account = resolveAccount();
@@ -21320,32 +21523,34 @@ app30.get("/", requireAdminSession, async (c) => {
21320
21523
  return c.json({ error: "Failed to read adherence ledger", agent }, 500);
21321
21524
  }
21322
21525
  });
21323
- var adherence_default = app30;
21526
+ var adherence_default = app32;
21324
21527
 
21325
21528
  // server/routes/admin/index.ts
21326
- var app31 = new Hono2();
21327
- app31.route("/session", session_default2);
21328
- app31.route("/chat", chat_default2);
21329
- app31.route("/compact", compact_default);
21330
- app31.route("/logs", logs_default);
21331
- app31.route("/claude-info", claude_info_default);
21332
- app31.route("/attachment", attachment_default);
21333
- app31.route("/account", account_default);
21334
- app31.route("/agents", agents_default);
21335
- app31.route("/version", version_default);
21336
- app31.route("/sessions", sessions_default);
21337
- app31.route("/browser", browser_default);
21338
- app31.route("/device-browser", device_browser_default);
21339
- app31.route("/events", events_default);
21340
- app31.route("/cloudflare", cloudflare_default);
21341
- app31.route("/files", files_default);
21342
- app31.route("/graph-search", graph_search_default);
21343
- app31.route("/graph-subgraph", graph_subgraph_default);
21344
- app31.route("/graph-delete", graph_delete_default);
21345
- app31.route("/graph-restore", graph_restore_default);
21346
- app31.route("/file-attach", file_attach_default);
21347
- app31.route("/adherence", adherence_default);
21348
- var admin_default = app31;
21529
+ var app33 = new Hono2();
21530
+ app33.route("/session", session_default2);
21531
+ app33.route("/chat", chat_default2);
21532
+ app33.route("/compact", compact_default);
21533
+ app33.route("/logs", logs_default);
21534
+ app33.route("/claude-info", claude_info_default);
21535
+ app33.route("/attachment", attachment_default);
21536
+ app33.route("/account", account_default);
21537
+ app33.route("/agents", agents_default);
21538
+ app33.route("/version", version_default);
21539
+ app33.route("/sessions", sessions_default);
21540
+ app33.route("/browser", browser_default);
21541
+ app33.route("/device-browser", device_browser_default);
21542
+ app33.route("/events", events_default);
21543
+ app33.route("/cloudflare", cloudflare_default);
21544
+ app33.route("/files", files_default);
21545
+ app33.route("/graph-search", graph_search_default);
21546
+ app33.route("/graph-subgraph", graph_subgraph_default);
21547
+ app33.route("/graph-delete", graph_delete_default);
21548
+ app33.route("/graph-restore", graph_restore_default);
21549
+ app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
21550
+ app33.route("/graph-default-view", graph_default_view_default);
21551
+ app33.route("/file-attach", file_attach_default);
21552
+ app33.route("/adherence", adherence_default);
21553
+ var admin_default = app33;
21349
21554
 
21350
21555
  // server/index.ts
21351
21556
  var PLATFORM_ROOT11 = process.env.MAXY_PLATFORM_ROOT || "";
@@ -21403,9 +21608,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
21403
21608
  function isPublicHost(host) {
21404
21609
  return host.startsWith("public.") || aliasDomains.has(host);
21405
21610
  }
21406
- var app32 = new Hono2();
21407
- app32.use("*", clientIpMiddleware);
21408
- app32.use("*", async (c, next) => {
21611
+ var app34 = new Hono2();
21612
+ app34.use("*", clientIpMiddleware);
21613
+ app34.use("*", async (c, next) => {
21409
21614
  await next();
21410
21615
  c.header("X-Content-Type-Options", "nosniff");
21411
21616
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -21428,7 +21633,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
21428
21633
  "/g/"
21429
21634
  ];
21430
21635
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
21431
- app32.use("*", async (c, next) => {
21636
+ app34.use("*", async (c, next) => {
21432
21637
  const host = (c.req.header("host") ?? "").split(":")[0];
21433
21638
  if (!isPublicHost(host)) {
21434
21639
  await next();
@@ -21468,7 +21673,7 @@ function resolveRemoteAuthOpts() {
21468
21673
  return brandLoginOpts;
21469
21674
  }
21470
21675
  var MAX_LOGIN_BODY = 8 * 1024;
21471
- app32.post("/__remote-auth/login", async (c) => {
21676
+ app34.post("/__remote-auth/login", async (c) => {
21472
21677
  const clientIp = c.var.clientIp || "unknown";
21473
21678
  const rateLimited = checkRateLimit(clientIp);
21474
21679
  if (rateLimited) {
@@ -21504,7 +21709,7 @@ app32.post("/__remote-auth/login", async (c) => {
21504
21709
  }
21505
21710
  });
21506
21711
  });
21507
- app32.get("/__remote-auth/logout", (c) => {
21712
+ app34.get("/__remote-auth/logout", (c) => {
21508
21713
  const cookieHeader = c.req.header("cookie");
21509
21714
  const token = parseCookie(cookieHeader, "__remote_session");
21510
21715
  if (token) invalidateRemoteSession(token);
@@ -21517,7 +21722,7 @@ app32.get("/__remote-auth/logout", (c) => {
21517
21722
  }
21518
21723
  });
21519
21724
  });
21520
- app32.post("/__remote-auth/change-password", async (c) => {
21725
+ app34.post("/__remote-auth/change-password", async (c) => {
21521
21726
  const clientIp = c.var.clientIp || "unknown";
21522
21727
  const rateLimited = checkRateLimit(clientIp);
21523
21728
  if (rateLimited) {
@@ -21566,13 +21771,13 @@ app32.post("/__remote-auth/change-password", async (c) => {
21566
21771
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
21567
21772
  }
21568
21773
  });
21569
- app32.get("/__remote-auth/setup", (c) => {
21774
+ app34.get("/__remote-auth/setup", (c) => {
21570
21775
  if (isRemoteAuthConfigured()) {
21571
21776
  return c.redirect("/");
21572
21777
  }
21573
21778
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
21574
21779
  });
21575
- app32.post("/__remote-auth/set-initial-password", async (c) => {
21780
+ app34.post("/__remote-auth/set-initial-password", async (c) => {
21576
21781
  if (isRemoteAuthConfigured()) {
21577
21782
  return c.redirect("/");
21578
21783
  }
@@ -21608,10 +21813,10 @@ app32.post("/__remote-auth/set-initial-password", async (c) => {
21608
21813
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
21609
21814
  }
21610
21815
  });
21611
- app32.get("/api/remote-auth/status", (c) => {
21816
+ app34.get("/api/remote-auth/status", (c) => {
21612
21817
  return c.json({ configured: isRemoteAuthConfigured() });
21613
21818
  });
21614
- app32.post("/api/remote-auth/set-password", async (c) => {
21819
+ app34.post("/api/remote-auth/set-password", async (c) => {
21615
21820
  let body;
21616
21821
  try {
21617
21822
  body = await c.req.json();
@@ -21641,9 +21846,9 @@ app32.post("/api/remote-auth/set-password", async (c) => {
21641
21846
  return c.json({ error: "Failed to save password" }, 500);
21642
21847
  }
21643
21848
  });
21644
- app32.route("/api/_client-error", client_error_default);
21849
+ app34.route("/api/_client-error", client_error_default);
21645
21850
  console.log("[client-error-route] mounted");
21646
- app32.use("*", async (c, next) => {
21851
+ app34.use("*", async (c, next) => {
21647
21852
  const host = (c.req.header("host") ?? "").split(":")[0];
21648
21853
  const path2 = c.req.path;
21649
21854
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -21683,15 +21888,15 @@ function parseCookie(cookieHeader, name) {
21683
21888
  return null;
21684
21889
  }
21685
21890
  }
21686
- app32.route("/api/health", health_default);
21687
- app32.route("/api/session", session_default);
21688
- app32.route("/api/chat", chat_default);
21689
- app32.route("/api/group", group_default);
21690
- app32.route("/api/access", access_default);
21691
- app32.route("/api/telegram", telegram_default);
21692
- app32.route("/api/whatsapp", whatsapp_default);
21693
- app32.route("/api/onboarding", onboarding_default);
21694
- app32.route("/api/admin", admin_default);
21891
+ app34.route("/api/health", health_default);
21892
+ app34.route("/api/session", session_default);
21893
+ app34.route("/api/chat", chat_default);
21894
+ app34.route("/api/group", group_default);
21895
+ app34.route("/api/access", access_default);
21896
+ app34.route("/api/telegram", telegram_default);
21897
+ app34.route("/api/whatsapp", whatsapp_default);
21898
+ app34.route("/api/onboarding", onboarding_default);
21899
+ app34.route("/api/admin", admin_default);
21695
21900
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
21696
21901
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
21697
21902
  var IMAGE_MIME = {
@@ -21703,7 +21908,7 @@ var IMAGE_MIME = {
21703
21908
  ".svg": "image/svg+xml",
21704
21909
  ".ico": "image/x-icon"
21705
21910
  };
21706
- app32.get("/agent-assets/:slug/:filename", (c) => {
21911
+ app34.get("/agent-assets/:slug/:filename", (c) => {
21707
21912
  const slug = c.req.param("slug");
21708
21913
  const filename = c.req.param("filename");
21709
21914
  if (!SAFE_SLUG_RE.test(slug)) {
@@ -21738,7 +21943,7 @@ app32.get("/agent-assets/:slug/:filename", (c) => {
21738
21943
  "Cache-Control": "public, max-age=3600"
21739
21944
  });
21740
21945
  });
21741
- app32.get("/generated/:filename", (c) => {
21946
+ app34.get("/generated/:filename", (c) => {
21742
21947
  const filename = c.req.param("filename");
21743
21948
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
21744
21949
  console.error(`[generated] serve file=${filename} status=403`);
@@ -21903,7 +22108,7 @@ function brandedPublicHtml(agentSlug) {
21903
22108
  function escapeHtml2(s) {
21904
22109
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
21905
22110
  }
21906
- app32.get("/", (c) => {
22111
+ app34.get("/", (c) => {
21907
22112
  const host = (c.req.header("host") ?? "").split(":")[0];
21908
22113
  if (isPublicHost(host)) {
21909
22114
  const defaultSlug = resolveDefaultSlug();
@@ -21911,12 +22116,12 @@ app32.get("/", (c) => {
21911
22116
  }
21912
22117
  return c.html(cachedHtml("index.html"));
21913
22118
  });
21914
- app32.get("/public", (c) => {
22119
+ app34.get("/public", (c) => {
21915
22120
  const host = (c.req.header("host") ?? "").split(":")[0];
21916
22121
  if (isPublicHost(host)) return c.text("Not found", 404);
21917
22122
  return c.html(cachedHtml("public.html"));
21918
22123
  });
21919
- app32.get("/chat", (c) => {
22124
+ app34.get("/chat", (c) => {
21920
22125
  const host = (c.req.header("host") ?? "").split(":")[0];
21921
22126
  if (isPublicHost(host)) return c.text("Not found", 404);
21922
22127
  return c.html(cachedHtml("public.html"));
@@ -21935,9 +22140,9 @@ async function logViewerFetch(c, next) {
21935
22140
  duration_ms: Date.now() - start
21936
22141
  });
21937
22142
  }
21938
- app32.use("/vnc-viewer.html", logViewerFetch);
21939
- app32.use("/vnc-popout.html", logViewerFetch);
21940
- app32.get("/vnc-popout.html", (c) => {
22143
+ app34.use("/vnc-viewer.html", logViewerFetch);
22144
+ app34.use("/vnc-popout.html", logViewerFetch);
22145
+ app34.get("/vnc-popout.html", (c) => {
21941
22146
  let html = htmlCache.get("vnc-popout.html");
21942
22147
  if (!html) {
21943
22148
  html = readFileSync26(resolve30(process.cwd(), "public", "vnc-popout.html"), "utf-8");
@@ -21950,7 +22155,7 @@ app32.get("/vnc-popout.html", (c) => {
21950
22155
  }
21951
22156
  return c.html(html);
21952
22157
  });
21953
- app32.post("/api/vnc/client-event", async (c) => {
22158
+ app34.post("/api/vnc/client-event", async (c) => {
21954
22159
  let body;
21955
22160
  try {
21956
22161
  body = await c.req.json();
@@ -21971,20 +22176,20 @@ app32.post("/api/vnc/client-event", async (c) => {
21971
22176
  });
21972
22177
  return c.json({ ok: true });
21973
22178
  });
21974
- app32.get("/g/:slug", (c) => {
22179
+ app34.get("/g/:slug", (c) => {
21975
22180
  return c.html(brandedPublicHtml());
21976
22181
  });
21977
- app32.get("/graph", (c) => {
22182
+ app34.get("/graph", (c) => {
21978
22183
  const host = (c.req.header("host") ?? "").split(":")[0];
21979
22184
  if (isPublicHost(host)) return c.text("Not found", 404);
21980
22185
  return c.html(cachedHtml("graph.html"));
21981
22186
  });
21982
- app32.get("/data", (c) => {
22187
+ app34.get("/data", (c) => {
21983
22188
  const host = (c.req.header("host") ?? "").split(":")[0];
21984
22189
  if (isPublicHost(host)) return c.text("Not found", 404);
21985
22190
  return c.html(cachedHtml("data.html"));
21986
22191
  });
21987
- app32.get("/:slug", async (c, next) => {
22192
+ app34.get("/:slug", async (c, next) => {
21988
22193
  const slug = c.req.param("slug");
21989
22194
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
21990
22195
  const branding = loadBrandingCache(slug);
@@ -21993,10 +22198,10 @@ app32.get("/:slug", async (c, next) => {
21993
22198
  }
21994
22199
  await next();
21995
22200
  });
21996
- app32.use("/*", serveStatic({ root: "./public" }));
22201
+ app34.use("/*", serveStatic({ root: "./public" }));
21997
22202
  var port = parseInt(process.env.PORT ?? "19200", 10);
21998
22203
  var hostname = process.env.HOSTNAME ?? "0.0.0.0";
21999
- var httpServer = serve({ fetch: app32.fetch, port, hostname });
22204
+ var httpServer = serve({ fetch: app34.fetch, port, hostname });
22000
22205
  attachVncWsProxy(httpServer, {
22001
22206
  isPublicHost,
22002
22207
  upstreamHost: "127.0.0.1",
@@ -22042,7 +22247,7 @@ for (const m of SUBAPP_MANIFEST) {
22042
22247
  }
22043
22248
  try {
22044
22249
  const registered = [];
22045
- for (const r of app32.routes ?? []) {
22250
+ for (const r of app34.routes ?? []) {
22046
22251
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
22047
22252
  if (AGENT_SLUG_PATTERN.test(r.path)) {
22048
22253
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });