@rubytech/create-maxy 1.0.664 → 1.0.666

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 (52) hide show
  1. package/dist/index.js +5 -1
  2. package/package.json +1 -1
  3. package/payload/platform/neo4j/schema.cypher +13 -3
  4. package/payload/platform/plugins/docs/references/memory-guide.md +1 -1
  5. package/payload/platform/plugins/docs/references/platform.md +1 -1
  6. package/payload/platform/plugins/docs/references/troubleshooting.md +24 -6
  7. package/payload/platform/scripts/vnc.sh +174 -2
  8. package/payload/server/public/assets/{admin-Bo3NKS_u.js → admin-Brug36E-.js} +5 -5
  9. package/payload/server/public/assets/{data-DQcIUUZW.js → data-woLf2Tmp.js} +1 -1
  10. package/payload/server/public/assets/{file-BhFSdU7V.js → file-rN5uuyaV.js} +1 -1
  11. package/payload/server/public/assets/{graph-DSUSNmfO.js → graph-BYaOEZUg.js} +17 -17
  12. package/payload/server/public/assets/{house-CA7LcTyb.js → house-DnFgpCt2.js} +1 -1
  13. package/payload/server/public/assets/jsx-runtime-CSCPZpLN.css +1 -0
  14. package/payload/server/public/assets/{public-C7sPrAvE.js → public-BRrqpeVH.js} +1 -1
  15. package/payload/server/public/assets/{share-2-CVCJTVW7.js → share-2-DLjRUEiG.js} +1 -1
  16. package/payload/server/public/assets/{useVoiceRecorder-DwMKR9su.js → useVoiceRecorder-D_efR3Nx.js} +1 -1
  17. package/payload/server/public/assets/{x-Dnw-ie9I.js → x-L6KPMfIN.js} +1 -1
  18. package/payload/server/public/data.html +6 -6
  19. package/payload/server/public/graph.html +6 -6
  20. package/payload/server/public/index.html +7 -7
  21. package/payload/server/public/public.html +4 -4
  22. package/payload/server/server.js +267 -115
  23. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts +0 -2
  24. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts.map +0 -1
  25. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js +0 -224
  26. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js.map +0 -1
  27. package/payload/platform/plugins/documents/mcp/dist/index.d.ts +0 -2
  28. package/payload/platform/plugins/documents/mcp/dist/index.d.ts.map +0 -1
  29. package/payload/platform/plugins/documents/mcp/dist/index.js +0 -98
  30. package/payload/platform/plugins/documents/mcp/dist/index.js.map +0 -1
  31. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts +0 -2
  32. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts.map +0 -1
  33. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js +0 -233
  34. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js.map +0 -1
  35. package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts +0 -18
  36. package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts.map +0 -1
  37. package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js +0 -80
  38. package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js.map +0 -1
  39. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts +0 -7
  40. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts.map +0 -1
  41. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js +0 -10
  42. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js.map +0 -1
  43. package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts +0 -23
  44. package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts.map +0 -1
  45. package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js +0 -115
  46. package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js.map +0 -1
  47. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts +0 -12
  48. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts.map +0 -1
  49. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js +0 -197
  50. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js.map +0 -1
  51. package/payload/server/public/assets/jsx-runtime-CH3XaSdT.css +0 -1
  52. /package/payload/server/public/assets/{jsx-runtime-BZgdWJ0Y.js → jsx-runtime-XWiDQoTG.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, app35) {
1204
+ route(path2, app36) {
1205
1205
  const subApp = this.basePath(path2);
1206
- app35.routes.map((r) => {
1206
+ app36.routes.map((r) => {
1207
1207
  let handler;
1208
- if (app35.errorHandler === errorHandler) {
1208
+ if (app36.errorHandler === errorHandler) {
1209
1209
  handler = r.handler;
1210
1210
  } else {
1211
- handler = async (c, next) => (await compose([], app35.errorHandler)(c, () => r.handler(c, next))).res;
1211
+ handler = async (c, next) => (await compose([], app36.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);
@@ -4501,6 +4501,7 @@ function resolveBrowserTransport(req, remoteAddress) {
4501
4501
  return transport;
4502
4502
  }
4503
4503
  var currentCdpDisplay = null;
4504
+ var currentTerminalDisplay = null;
4504
4505
  function discoverNativeDisplay() {
4505
4506
  const fallback = { sessionType: "x11", display: ":0", waylandDisplay: "" };
4506
4507
  try {
@@ -4671,6 +4672,73 @@ async function ensureCdp(transport = "vnc") {
4671
4672
  function killChromium() {
4672
4673
  spawnSync("pkill", ["-f", "chromium"], { stdio: "pipe" });
4673
4674
  }
4675
+ function terminalAlive() {
4676
+ const result = spawnSync("bash", [VNC_SCRIPT, "status-terminal"], {
4677
+ stdio: "pipe",
4678
+ timeout: 2e3
4679
+ });
4680
+ return result.status === 0;
4681
+ }
4682
+ async function ensureTerminal(transport = "vnc") {
4683
+ const targetSentinel = transport === "native" ? "native" : ":99";
4684
+ if (terminalAlive()) {
4685
+ if (currentTerminalDisplay !== null && currentTerminalDisplay !== targetSentinel) {
4686
+ console.error(`[ensureTerminal] Display switch: ${currentTerminalDisplay} \u2192 ${targetSentinel}`);
4687
+ vncLog("ensure-terminal", {
4688
+ action: "display-switch",
4689
+ transport,
4690
+ from_display: currentTerminalDisplay,
4691
+ to_display: targetSentinel
4692
+ });
4693
+ killTerminal();
4694
+ await sleep(500);
4695
+ } else {
4696
+ if (currentTerminalDisplay === null) {
4697
+ currentTerminalDisplay = targetSentinel;
4698
+ }
4699
+ vncLog("ensure-terminal", { action: "already-running", transport });
4700
+ return true;
4701
+ }
4702
+ }
4703
+ const vncCommand = transport === "native" ? "start-terminal-native" : "start-terminal";
4704
+ if (transport === "vnc") {
4705
+ const xAlive = await waitForPort(5900, 1e3);
4706
+ if (!xAlive) {
4707
+ console.error("[ensureTerminal] X server down on :5900 \u2014 escalating to full VNC restart");
4708
+ vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport });
4709
+ const vncOk = await ensureVnc();
4710
+ if (!vncOk) {
4711
+ console.error("[ensureTerminal] Full VNC restart failed \u2014 terminal degraded");
4712
+ vncLog("ensure-terminal", { action: "degraded", reason: "vnc-restart-failed", transport });
4713
+ return false;
4714
+ }
4715
+ }
4716
+ }
4717
+ if (transport === "native") {
4718
+ const nativeInfo = discoverNativeDisplay();
4719
+ vncLog("ensure-terminal", {
4720
+ action: "native-display-resolved",
4721
+ transport,
4722
+ session_type: nativeInfo.sessionType,
4723
+ display: nativeInfo.display
4724
+ });
4725
+ }
4726
+ console.error(`[ensureTerminal] Launching terminal (${vncCommand}) for transport=${transport}`);
4727
+ vncLog("ensure-terminal", { action: `launch-${vncCommand}`, transport });
4728
+ try {
4729
+ execFileSync("bash", [VNC_SCRIPT, vncCommand], { timeout: 1e4 });
4730
+ } catch (err) {
4731
+ vncLog("ensure-terminal", { action: "launch-failed", transport, err: err.message });
4732
+ return false;
4733
+ }
4734
+ currentTerminalDisplay = targetSentinel;
4735
+ vncLog("ensure-terminal", { action: "launch-complete", transport, sentinel: targetSentinel });
4736
+ return true;
4737
+ }
4738
+ function killTerminal() {
4739
+ spawnSync("bash", [VNC_SCRIPT, "kill-terminal"], { stdio: "pipe", timeout: 5e3 });
4740
+ currentTerminalDisplay = null;
4741
+ }
4674
4742
  function writeChromiumWrapper() {
4675
4743
  mkdirSync4(BIN_DIR, { recursive: true });
4676
4744
  const wrapperPath = resolve5(BIN_DIR, "chromium");
@@ -5213,6 +5281,7 @@ async function persistToolCall(record) {
5213
5281
  }
5214
5282
  }
5215
5283
  var SUMMARY_MAX_LEN = 200;
5284
+ var persistMessageLocks = /* @__PURE__ */ new Map();
5216
5285
  async function persistMessage(conversationId, role, content, accountId, tokens, createdAt, sender) {
5217
5286
  if (!content) return null;
5218
5287
  const messageId = randomUUID();
@@ -5223,6 +5292,15 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
5223
5292
  } catch (err) {
5224
5293
  console.error(`[persist] Embedding failed, storing without: ${err instanceof Error ? err.message : String(err)}`);
5225
5294
  }
5295
+ const prev = persistMessageLocks.get(conversationId);
5296
+ const waited = prev !== void 0;
5297
+ let release;
5298
+ const mine = new Promise((resolve31) => {
5299
+ release = resolve31;
5300
+ });
5301
+ const chained = (prev ?? Promise.resolve()).then(() => mine);
5302
+ persistMessageLocks.set(conversationId, chained);
5303
+ await prev;
5226
5304
  const session = getSession();
5227
5305
  try {
5228
5306
  const result = await session.run(
@@ -5285,7 +5363,7 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
5285
5363
  const summarySetThisWrite = record.get("summarySetThisWrite") === true;
5286
5364
  const chainLenRaw = record.get("chainLen");
5287
5365
  const chainLen = typeof chainLenRaw === "bigint" ? Number(chainLenRaw) : typeof chainLenRaw?.toNumber === "function" ? chainLenRaw.toNumber() : Number(chainLenRaw ?? 0);
5288
- console.error(`[neo4j-store] append-message conversationId=${conversationId.slice(0, 8)}\u2026 messageId=${messageId.slice(0, 8)}\u2026 prev=${prevMessageId ? prevMessageId.slice(0, 8) + "\u2026" : "null"} chainLen=${chainLen}`);
5366
+ console.error(`[neo4j-store] append-message conversationId=${conversationId.slice(0, 8)}\u2026 messageId=${messageId.slice(0, 8)}\u2026 prev=${prevMessageId ? prevMessageId.slice(0, 8) + "\u2026" : "null"} chainLen=${chainLen} waited=${waited}`);
5289
5367
  if (summarySetThisWrite) {
5290
5368
  console.error(`[neo4j-store] conversation-summary-set conversationId=${conversationId.slice(0, 8)}\u2026 len=${summary.length}`);
5291
5369
  }
@@ -5295,6 +5373,10 @@ async function persistMessage(conversationId, role, content, accountId, tokens,
5295
5373
  console.error(`[persist] Neo4j write failed: ${err instanceof Error ? err.message : String(err)}`);
5296
5374
  return null;
5297
5375
  } finally {
5376
+ release();
5377
+ if (persistMessageLocks.get(conversationId) === chained) {
5378
+ persistMessageLocks.delete(conversationId);
5379
+ }
5298
5380
  await session.close();
5299
5381
  }
5300
5382
  }
@@ -19797,6 +19879,44 @@ app20.post("/launch", async (c) => {
19797
19879
  });
19798
19880
  var browser_default = app20;
19799
19881
 
19882
+ // server/routes/admin/terminal.ts
19883
+ var app21 = new Hono2();
19884
+ app21.post("/launch", async (c) => {
19885
+ try {
19886
+ const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
19887
+ if (transport === "vnc") {
19888
+ const vncOk = await ensureVnc();
19889
+ if (!vncOk) {
19890
+ return c.json({ ok: false, error: "VNC failed to start" }, 502);
19891
+ }
19892
+ }
19893
+ const terminalOk = await ensureTerminal(transport);
19894
+ if (!terminalOk) {
19895
+ return c.json({ ok: false, error: "Terminal failed to start" }, 502);
19896
+ }
19897
+ return c.json({ ok: true, transport });
19898
+ } catch (err) {
19899
+ console.error("[admin/terminal/launch] Failed to start terminal:", err);
19900
+ return c.json(
19901
+ { ok: false, error: err instanceof Error ? err.message : "Unknown error" },
19902
+ 500
19903
+ );
19904
+ }
19905
+ });
19906
+ app21.post("/close", (c) => {
19907
+ try {
19908
+ killTerminal();
19909
+ return c.json({ ok: true });
19910
+ } catch (err) {
19911
+ console.error("[admin/terminal/close] kill failed:", err);
19912
+ return c.json(
19913
+ { ok: false, error: err instanceof Error ? err.message : "Unknown error" },
19914
+ 500
19915
+ );
19916
+ }
19917
+ });
19918
+ var terminal_default = app21;
19919
+
19800
19920
  // app/lib/cdp-client.ts
19801
19921
  var CDP_HOST = "127.0.0.1";
19802
19922
  var CDP_PORT = 9222;
@@ -19838,8 +19958,8 @@ async function cdpNavigateNewTab(url, opts = {}) {
19838
19958
  }
19839
19959
 
19840
19960
  // server/routes/admin/device-browser.ts
19841
- var app21 = new Hono2();
19842
- app21.post("/navigate", async (c) => {
19961
+ var app22 = new Hono2();
19962
+ app22.post("/navigate", async (c) => {
19843
19963
  const TAG19 = "[device-url:click]";
19844
19964
  let body;
19845
19965
  try {
@@ -19926,7 +20046,7 @@ app21.post("/navigate", async (c) => {
19926
20046
  targetId: outcome.targetId
19927
20047
  });
19928
20048
  });
19929
- var device_browser_default = app21;
20049
+ var device_browser_default = app22;
19930
20050
 
19931
20051
  // server/routes/admin/events.ts
19932
20052
  var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
@@ -19935,8 +20055,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
19935
20055
  "device-url:vnc-surface-shown",
19936
20056
  "device-url:malformed"
19937
20057
  ]);
19938
- var app22 = new Hono2();
19939
- app22.post("/", async (c) => {
20058
+ var app23 = new Hono2();
20059
+ app23.post("/", async (c) => {
19940
20060
  const TAG19 = "[admin:events]";
19941
20061
  let body;
19942
20062
  try {
@@ -19967,7 +20087,7 @@ app22.post("/", async (c) => {
19967
20087
  console.error(`[${event}] ${formatted}`);
19968
20088
  return c.json({ ok: true });
19969
20089
  });
19970
- var events_default = app22;
20090
+ var events_default = app23;
19971
20091
 
19972
20092
  // server/routes/admin/cloudflare.ts
19973
20093
  import { homedir as homedir4 } from "os";
@@ -20060,7 +20180,7 @@ function validateBody(body) {
20060
20180
  }
20061
20181
  return null;
20062
20182
  }
20063
- var app23 = new Hono2();
20183
+ var app24 = new Hono2();
20064
20184
  function fieldFromReason(reason) {
20065
20185
  switch (reason) {
20066
20186
  case "not-signed-in":
@@ -20077,7 +20197,7 @@ function fieldFromReason(reason) {
20077
20197
  return "script";
20078
20198
  }
20079
20199
  }
20080
- app23.get("/domains", requireAdminSession, async (c) => {
20200
+ app24.get("/domains", requireAdminSession, async (c) => {
20081
20201
  const started = Date.now();
20082
20202
  const sessionKey = c.var.sessionKey;
20083
20203
  let correlationId;
@@ -20170,7 +20290,7 @@ ${result.stderr}` : ""}`;
20170
20290
  );
20171
20291
  return c.json(success, 200);
20172
20292
  });
20173
- app23.post("/setup", requireAdminSession, async (c) => {
20293
+ app24.post("/setup", requireAdminSession, async (c) => {
20174
20294
  const started = Date.now();
20175
20295
  const sessionKey = c.var.sessionKey;
20176
20296
  let correlationId;
@@ -20308,7 +20428,7 @@ ${result.stderr}` : ""}`;
20308
20428
  log2(`phase=response-sent`);
20309
20429
  return resp;
20310
20430
  });
20311
- var cloudflare_default = app23;
20431
+ var cloudflare_default = app24;
20312
20432
 
20313
20433
  // server/routes/admin/files.ts
20314
20434
  import { createReadStream as createReadStream3 } from "fs";
@@ -20660,8 +20780,8 @@ function buildDisplayPath(relPath, accountNames) {
20660
20780
  return dn ? { name: seg, displayName: dn } : { name: seg };
20661
20781
  });
20662
20782
  }
20663
- var app24 = new Hono2();
20664
- app24.get("/", requireAdminSession, async (c) => {
20783
+ var app25 = new Hono2();
20784
+ app25.get("/", requireAdminSession, async (c) => {
20665
20785
  const sessionKey = c.var.sessionKey;
20666
20786
  if (!getAccountIdForSession(sessionKey)) {
20667
20787
  console.error(`[data] auth-rejected endpoint="/api/admin/files" reason="no account for session"`);
@@ -20722,7 +20842,7 @@ app24.get("/", requireAdminSession, async (c) => {
20722
20842
  return c.json({ error: message }, 500);
20723
20843
  }
20724
20844
  });
20725
- app24.get("/download", requireAdminSession, async (c) => {
20845
+ app25.get("/download", requireAdminSession, async (c) => {
20726
20846
  const sessionKey = c.var.sessionKey;
20727
20847
  if (!getAccountIdForSession(sessionKey)) {
20728
20848
  console.error(`[data] auth-rejected endpoint="/api/admin/files/download" reason="no account for session"`);
@@ -20770,7 +20890,7 @@ app24.get("/download", requireAdminSession, async (c) => {
20770
20890
  return c.json({ error: message }, 500);
20771
20891
  }
20772
20892
  });
20773
- app24.post("/upload", requireAdminSession, async (c) => {
20893
+ app25.post("/upload", requireAdminSession, async (c) => {
20774
20894
  const sessionKey = c.var.sessionKey;
20775
20895
  const accountId = getAccountIdForSession(sessionKey);
20776
20896
  if (!accountId) {
@@ -20828,7 +20948,7 @@ app24.post("/upload", requireAdminSession, async (c) => {
20828
20948
  mimeType: file.type
20829
20949
  });
20830
20950
  });
20831
- app24.delete("/", requireAdminSession, async (c) => {
20951
+ app25.delete("/", requireAdminSession, async (c) => {
20832
20952
  const sessionKey = c.var.sessionKey;
20833
20953
  const accountId = getAccountIdForSession(sessionKey);
20834
20954
  if (!accountId) {
@@ -20895,13 +21015,13 @@ app24.delete("/", requireAdminSession, async (c) => {
20895
21015
  return c.json({ error: message }, 500);
20896
21016
  }
20897
21017
  });
20898
- var files_default = app24;
21018
+ var files_default = app25;
20899
21019
 
20900
21020
  // server/routes/admin/graph-search.ts
20901
21021
  var DEFAULT_LIMIT = 20;
20902
21022
  var MAX_LIMIT = 100;
20903
- var app25 = new Hono2();
20904
- app25.get("/", requireAdminSession, async (c) => {
21023
+ var app26 = new Hono2();
21024
+ app26.get("/", requireAdminSession, async (c) => {
20905
21025
  const sessionKey = c.var.sessionKey;
20906
21026
  const q = (c.req.query("q") ?? "").trim();
20907
21027
  const rawLimit = c.req.query("limit");
@@ -20926,7 +21046,10 @@ app25.get("/", requireAdminSession, async (c) => {
20926
21046
  return c.json({ error: `Graph search unavailable: ${message}` }, 503);
20927
21047
  }
20928
21048
  });
20929
- var graph_search_default = app25;
21049
+ var graph_search_default = app26;
21050
+
21051
+ // server/routes/admin/graph-subgraph.ts
21052
+ import neo4j3 from "neo4j-driver";
20930
21053
 
20931
21054
  // app/lib/graph-labels.ts
20932
21055
  var GRAPH_LABEL_COLOURS = {
@@ -21002,8 +21125,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
21002
21125
  "otpCode",
21003
21126
  "sessionKey"
21004
21127
  ]);
21005
- var app26 = new Hono2();
21006
- app26.get("/", requireAdminSession, async (c) => {
21128
+ var app27 = new Hono2();
21129
+ app27.get("/", requireAdminSession, async (c) => {
21007
21130
  const sessionKey = c.var.sessionKey;
21008
21131
  const accountId = getAccountIdForSession(sessionKey);
21009
21132
  if (!accountId) {
@@ -21228,22 +21351,31 @@ var NEIGHBOURHOOD_CYPHER = `
21228
21351
  [x IN windowNodes | {id: elementId(x), labels: labels(x), properties: properties(x)}] AS nodes,
21229
21352
  [e IN rawEdges WHERE e IS NOT NULL] AS edges
21230
21353
  `;
21354
+ function convertNeo4jValue(value) {
21355
+ if (neo4j3.isDateTime(value) || neo4j3.isDate(value) || neo4j3.isLocalDateTime(value) || neo4j3.isLocalTime(value) || neo4j3.isTime(value) || neo4j3.isDuration(value)) {
21356
+ return value.toString();
21357
+ }
21358
+ if (neo4j3.isInt(value)) {
21359
+ return value.inSafeRange() ? value.toNumber() : value.toString();
21360
+ }
21361
+ return value;
21362
+ }
21231
21363
  function pruneNode(node) {
21232
21364
  const properties = {};
21233
21365
  for (const [key, value] of Object.entries(node.properties ?? {})) {
21234
21366
  if (STRIPPED_PROPERTIES.has(key)) continue;
21235
- properties[key] = value;
21367
+ properties[key] = convertNeo4jValue(value);
21236
21368
  }
21237
21369
  const trashed = (node.labels ?? []).includes("Trashed");
21238
21370
  const labels = (node.labels ?? []).filter((l) => l !== "Trashed");
21239
21371
  return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
21240
21372
  }
21241
- var graph_subgraph_default = app26;
21373
+ var graph_subgraph_default = app27;
21242
21374
 
21243
21375
  // server/routes/admin/graph-delete.ts
21244
21376
  var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
21245
- var app27 = new Hono2();
21246
- app27.post("/", requireAdminSession, async (c) => {
21377
+ var app28 = new Hono2();
21378
+ app28.post("/", requireAdminSession, async (c) => {
21247
21379
  const sessionKey = c.var.sessionKey;
21248
21380
  const accountId = getAccountIdForSession(sessionKey);
21249
21381
  if (!accountId) {
@@ -21314,11 +21446,11 @@ app27.post("/", requireAdminSession, async (c) => {
21314
21446
  }
21315
21447
  }
21316
21448
  });
21317
- var graph_delete_default = app27;
21449
+ var graph_delete_default = app28;
21318
21450
 
21319
21451
  // server/routes/admin/graph-restore.ts
21320
- var app28 = new Hono2();
21321
- app28.post("/", requireAdminSession, async (c) => {
21452
+ var app29 = new Hono2();
21453
+ app29.post("/", requireAdminSession, async (c) => {
21322
21454
  const sessionKey = c.var.sessionKey;
21323
21455
  const accountId = getAccountIdForSession(sessionKey);
21324
21456
  if (!accountId) {
@@ -21382,11 +21514,11 @@ app28.post("/", requireAdminSession, async (c) => {
21382
21514
  }
21383
21515
  }
21384
21516
  });
21385
- var graph_restore_default = app28;
21517
+ var graph_restore_default = app29;
21386
21518
 
21387
21519
  // server/routes/admin/graph-labels-in-graph.ts
21388
- var app29 = new Hono2();
21389
- app29.get("/", requireAdminSession, async (c) => {
21520
+ var app30 = new Hono2();
21521
+ app30.get("/", requireAdminSession, async (c) => {
21390
21522
  const sessionKey = c.var.sessionKey;
21391
21523
  const accountId = getAccountIdForSession(sessionKey);
21392
21524
  if (!accountId) {
@@ -21403,13 +21535,14 @@ app29.get("/", requireAdminSession, async (c) => {
21403
21535
  const labels = result.records.map((r) => ({
21404
21536
  label: String(r.get("label")),
21405
21537
  nodeCount: toNumber(r.get("nodeCount")),
21406
- relDegree: toNumber(r.get("relDegree"))
21538
+ relDegree: toNumber(r.get("relDegree")),
21539
+ childOnly: toBool(r.get("childOnly"))
21407
21540
  })).filter((row) => row.nodeCount > 0).sort((a, b) => {
21408
21541
  if (b.relDegree !== a.relDegree) return b.relDegree - a.relDegree;
21409
21542
  return a.label.localeCompare(b.label);
21410
21543
  });
21411
21544
  const elapsed = Date.now() - started;
21412
- const summary = labels.map((l) => `${l.label}:${l.nodeCount}:${l.relDegree}`).join(",");
21545
+ const summary = labels.map((l) => `${l.label}:${l.nodeCount}:${l.relDegree}:${l.childOnly ? 1 : 0}`).join(",");
21413
21546
  console.error(
21414
21547
  `[graph-page] labels-in-graph account=${accountId} labels=${summary} ms=${elapsed}`
21415
21548
  );
@@ -21433,21 +21566,39 @@ function toNumber(v) {
21433
21566
  if (typeof v === "number") return v;
21434
21567
  return Number(v ?? 0);
21435
21568
  }
21569
+ function toBool(v) {
21570
+ return v === true;
21571
+ }
21436
21572
  var LABELS_IN_GRAPH_CYPHER = `
21437
21573
  MATCH (n)
21438
21574
  WHERE n.accountId = $accountId
21439
21575
  AND NOT n:Trashed
21440
21576
  AND n.deletedAt IS NULL
21441
- WITH n, [l IN labels(n) WHERE NOT l IN $excluded] AS keptLabels
21577
+ WITH n,
21578
+ [l IN labels(n) WHERE NOT l IN $excluded] AS keptLabels,
21579
+ size([(n)--() | 1]) AS halfEdges
21442
21580
  UNWIND keptLabels AS label
21443
- WITH label, count(DISTINCT n) AS nodeCount, sum(size([(n)--() | 1])) AS relDegree
21444
- RETURN label, nodeCount, relDegree
21581
+ WITH label, n, halfEdges,
21582
+ EXISTS {
21583
+ MATCH (other)-[]->(n)
21584
+ WHERE NOT other:Trashed
21585
+ AND other.deletedAt IS NULL
21586
+ AND NONE(ol IN labels(other) WHERE ol = label)
21587
+ } AS hasNonSelfInbound
21588
+ WITH label,
21589
+ count(DISTINCT n) AS nodeCount,
21590
+ sum(halfEdges) AS relDegree,
21591
+ count(DISTINCT CASE WHEN hasNonSelfInbound THEN n END) AS qualifyingCount
21592
+ RETURN label,
21593
+ nodeCount,
21594
+ relDegree,
21595
+ (nodeCount > 0 AND qualifyingCount = nodeCount) AS childOnly
21445
21596
  `;
21446
- var graph_labels_in_graph_default = app29;
21597
+ var graph_labels_in_graph_default = app30;
21447
21598
 
21448
21599
  // server/routes/admin/graph-default-view.ts
21449
- var app30 = new Hono2();
21450
- app30.get("/", requireAdminSession, async (c) => {
21600
+ var app31 = new Hono2();
21601
+ app31.get("/", requireAdminSession, async (c) => {
21451
21602
  const sessionKey = c.var.sessionKey;
21452
21603
  const accountId = getAccountIdForSession(sessionKey);
21453
21604
  const userId = getUserIdForSession(sessionKey);
@@ -21485,7 +21636,7 @@ app30.get("/", requireAdminSession, async (c) => {
21485
21636
  }
21486
21637
  }
21487
21638
  });
21488
- app30.put("/", requireAdminSession, async (c) => {
21639
+ app31.put("/", requireAdminSession, async (c) => {
21489
21640
  const sessionKey = c.var.sessionKey;
21490
21641
  const accountId = getAccountIdForSession(sessionKey);
21491
21642
  const userId = getUserIdForSession(sessionKey);
@@ -21567,11 +21718,11 @@ var WRITE_CYPHER = `
21567
21718
  p.updatedAt = $updatedAt
21568
21719
  RETURN p.labels AS labels
21569
21720
  `;
21570
- var graph_default_view_default = app30;
21721
+ var graph_default_view_default = app31;
21571
21722
 
21572
21723
  // server/routes/admin/file-attach.ts
21573
- var app31 = new Hono2();
21574
- app31.post("/", async (c) => {
21724
+ var app32 = new Hono2();
21725
+ app32.post("/", async (c) => {
21575
21726
  try {
21576
21727
  const body = await c.req.json();
21577
21728
  const { filePath, accountId } = body;
@@ -21594,11 +21745,11 @@ app31.post("/", async (c) => {
21594
21745
  return c.json({ error: message }, 500);
21595
21746
  }
21596
21747
  });
21597
- var file_attach_default = app31;
21748
+ var file_attach_default = app32;
21598
21749
 
21599
21750
  // server/routes/admin/adherence.ts
21600
- var app32 = new Hono2();
21601
- app32.get("/", requireAdminSession, async (c) => {
21751
+ var app33 = new Hono2();
21752
+ app33.get("/", requireAdminSession, async (c) => {
21602
21753
  const agent = c.req.query("agent") ?? "admin";
21603
21754
  const includeBlock = c.req.query("block") === "1";
21604
21755
  const account = resolveAccount();
@@ -21619,34 +21770,35 @@ app32.get("/", requireAdminSession, async (c) => {
21619
21770
  return c.json({ error: "Failed to read adherence ledger", agent }, 500);
21620
21771
  }
21621
21772
  });
21622
- var adherence_default = app32;
21773
+ var adherence_default = app33;
21623
21774
 
21624
21775
  // server/routes/admin/index.ts
21625
- var app33 = new Hono2();
21626
- app33.route("/session", session_default2);
21627
- app33.route("/chat", chat_default2);
21628
- app33.route("/compact", compact_default);
21629
- app33.route("/logs", logs_default);
21630
- app33.route("/claude-info", claude_info_default);
21631
- app33.route("/attachment", attachment_default);
21632
- app33.route("/account", account_default);
21633
- app33.route("/agents", agents_default);
21634
- app33.route("/version", version_default);
21635
- app33.route("/sessions", sessions_default);
21636
- app33.route("/browser", browser_default);
21637
- app33.route("/device-browser", device_browser_default);
21638
- app33.route("/events", events_default);
21639
- app33.route("/cloudflare", cloudflare_default);
21640
- app33.route("/files", files_default);
21641
- app33.route("/graph-search", graph_search_default);
21642
- app33.route("/graph-subgraph", graph_subgraph_default);
21643
- app33.route("/graph-delete", graph_delete_default);
21644
- app33.route("/graph-restore", graph_restore_default);
21645
- app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
21646
- app33.route("/graph-default-view", graph_default_view_default);
21647
- app33.route("/file-attach", file_attach_default);
21648
- app33.route("/adherence", adherence_default);
21649
- var admin_default = app33;
21776
+ var app34 = new Hono2();
21777
+ app34.route("/session", session_default2);
21778
+ app34.route("/chat", chat_default2);
21779
+ app34.route("/compact", compact_default);
21780
+ app34.route("/logs", logs_default);
21781
+ app34.route("/claude-info", claude_info_default);
21782
+ app34.route("/attachment", attachment_default);
21783
+ app34.route("/account", account_default);
21784
+ app34.route("/agents", agents_default);
21785
+ app34.route("/version", version_default);
21786
+ app34.route("/sessions", sessions_default);
21787
+ app34.route("/browser", browser_default);
21788
+ app34.route("/terminal", terminal_default);
21789
+ app34.route("/device-browser", device_browser_default);
21790
+ app34.route("/events", events_default);
21791
+ app34.route("/cloudflare", cloudflare_default);
21792
+ app34.route("/files", files_default);
21793
+ app34.route("/graph-search", graph_search_default);
21794
+ app34.route("/graph-subgraph", graph_subgraph_default);
21795
+ app34.route("/graph-delete", graph_delete_default);
21796
+ app34.route("/graph-restore", graph_restore_default);
21797
+ app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
21798
+ app34.route("/graph-default-view", graph_default_view_default);
21799
+ app34.route("/file-attach", file_attach_default);
21800
+ app34.route("/adherence", adherence_default);
21801
+ var admin_default = app34;
21650
21802
 
21651
21803
  // server/index.ts
21652
21804
  var PLATFORM_ROOT11 = process.env.MAXY_PLATFORM_ROOT || "";
@@ -21704,9 +21856,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
21704
21856
  function isPublicHost(host) {
21705
21857
  return host.startsWith("public.") || aliasDomains.has(host);
21706
21858
  }
21707
- var app34 = new Hono2();
21708
- app34.use("*", clientIpMiddleware);
21709
- app34.use("*", async (c, next) => {
21859
+ var app35 = new Hono2();
21860
+ app35.use("*", clientIpMiddleware);
21861
+ app35.use("*", async (c, next) => {
21710
21862
  await next();
21711
21863
  c.header("X-Content-Type-Options", "nosniff");
21712
21864
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -21729,7 +21881,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
21729
21881
  "/g/"
21730
21882
  ];
21731
21883
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
21732
- app34.use("*", async (c, next) => {
21884
+ app35.use("*", async (c, next) => {
21733
21885
  const host = (c.req.header("host") ?? "").split(":")[0];
21734
21886
  if (!isPublicHost(host)) {
21735
21887
  await next();
@@ -21769,7 +21921,7 @@ function resolveRemoteAuthOpts() {
21769
21921
  return brandLoginOpts;
21770
21922
  }
21771
21923
  var MAX_LOGIN_BODY = 8 * 1024;
21772
- app34.post("/__remote-auth/login", async (c) => {
21924
+ app35.post("/__remote-auth/login", async (c) => {
21773
21925
  const clientIp = c.var.clientIp || "unknown";
21774
21926
  const rateLimited = checkRateLimit(clientIp);
21775
21927
  if (rateLimited) {
@@ -21805,7 +21957,7 @@ app34.post("/__remote-auth/login", async (c) => {
21805
21957
  }
21806
21958
  });
21807
21959
  });
21808
- app34.get("/__remote-auth/logout", (c) => {
21960
+ app35.get("/__remote-auth/logout", (c) => {
21809
21961
  const cookieHeader = c.req.header("cookie");
21810
21962
  const token = parseCookie(cookieHeader, "__remote_session");
21811
21963
  if (token) invalidateRemoteSession(token);
@@ -21818,7 +21970,7 @@ app34.get("/__remote-auth/logout", (c) => {
21818
21970
  }
21819
21971
  });
21820
21972
  });
21821
- app34.post("/__remote-auth/change-password", async (c) => {
21973
+ app35.post("/__remote-auth/change-password", async (c) => {
21822
21974
  const clientIp = c.var.clientIp || "unknown";
21823
21975
  const rateLimited = checkRateLimit(clientIp);
21824
21976
  if (rateLimited) {
@@ -21867,13 +22019,13 @@ app34.post("/__remote-auth/change-password", async (c) => {
21867
22019
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
21868
22020
  }
21869
22021
  });
21870
- app34.get("/__remote-auth/setup", (c) => {
22022
+ app35.get("/__remote-auth/setup", (c) => {
21871
22023
  if (isRemoteAuthConfigured()) {
21872
22024
  return c.redirect("/");
21873
22025
  }
21874
22026
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
21875
22027
  });
21876
- app34.post("/__remote-auth/set-initial-password", async (c) => {
22028
+ app35.post("/__remote-auth/set-initial-password", async (c) => {
21877
22029
  if (isRemoteAuthConfigured()) {
21878
22030
  return c.redirect("/");
21879
22031
  }
@@ -21909,10 +22061,10 @@ app34.post("/__remote-auth/set-initial-password", async (c) => {
21909
22061
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
21910
22062
  }
21911
22063
  });
21912
- app34.get("/api/remote-auth/status", (c) => {
22064
+ app35.get("/api/remote-auth/status", (c) => {
21913
22065
  return c.json({ configured: isRemoteAuthConfigured() });
21914
22066
  });
21915
- app34.post("/api/remote-auth/set-password", async (c) => {
22067
+ app35.post("/api/remote-auth/set-password", async (c) => {
21916
22068
  let body;
21917
22069
  try {
21918
22070
  body = await c.req.json();
@@ -21942,9 +22094,9 @@ app34.post("/api/remote-auth/set-password", async (c) => {
21942
22094
  return c.json({ error: "Failed to save password" }, 500);
21943
22095
  }
21944
22096
  });
21945
- app34.route("/api/_client-error", client_error_default);
22097
+ app35.route("/api/_client-error", client_error_default);
21946
22098
  console.log("[client-error-route] mounted");
21947
- app34.use("*", async (c, next) => {
22099
+ app35.use("*", async (c, next) => {
21948
22100
  const host = (c.req.header("host") ?? "").split(":")[0];
21949
22101
  const path2 = c.req.path;
21950
22102
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -21984,15 +22136,15 @@ function parseCookie(cookieHeader, name) {
21984
22136
  return null;
21985
22137
  }
21986
22138
  }
21987
- app34.route("/api/health", health_default);
21988
- app34.route("/api/session", session_default);
21989
- app34.route("/api/chat", chat_default);
21990
- app34.route("/api/group", group_default);
21991
- app34.route("/api/access", access_default);
21992
- app34.route("/api/telegram", telegram_default);
21993
- app34.route("/api/whatsapp", whatsapp_default);
21994
- app34.route("/api/onboarding", onboarding_default);
21995
- app34.route("/api/admin", admin_default);
22139
+ app35.route("/api/health", health_default);
22140
+ app35.route("/api/session", session_default);
22141
+ app35.route("/api/chat", chat_default);
22142
+ app35.route("/api/group", group_default);
22143
+ app35.route("/api/access", access_default);
22144
+ app35.route("/api/telegram", telegram_default);
22145
+ app35.route("/api/whatsapp", whatsapp_default);
22146
+ app35.route("/api/onboarding", onboarding_default);
22147
+ app35.route("/api/admin", admin_default);
21996
22148
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
21997
22149
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
21998
22150
  var IMAGE_MIME = {
@@ -22004,7 +22156,7 @@ var IMAGE_MIME = {
22004
22156
  ".svg": "image/svg+xml",
22005
22157
  ".ico": "image/x-icon"
22006
22158
  };
22007
- app34.get("/agent-assets/:slug/:filename", (c) => {
22159
+ app35.get("/agent-assets/:slug/:filename", (c) => {
22008
22160
  const slug = c.req.param("slug");
22009
22161
  const filename = c.req.param("filename");
22010
22162
  if (!SAFE_SLUG_RE.test(slug)) {
@@ -22039,7 +22191,7 @@ app34.get("/agent-assets/:slug/:filename", (c) => {
22039
22191
  "Cache-Control": "public, max-age=3600"
22040
22192
  });
22041
22193
  });
22042
- app34.get("/generated/:filename", (c) => {
22194
+ app35.get("/generated/:filename", (c) => {
22043
22195
  const filename = c.req.param("filename");
22044
22196
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
22045
22197
  console.error(`[generated] serve file=${filename} status=403`);
@@ -22204,7 +22356,7 @@ function brandedPublicHtml(agentSlug) {
22204
22356
  function escapeHtml2(s) {
22205
22357
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
22206
22358
  }
22207
- app34.get("/", (c) => {
22359
+ app35.get("/", (c) => {
22208
22360
  const host = (c.req.header("host") ?? "").split(":")[0];
22209
22361
  if (isPublicHost(host)) {
22210
22362
  const defaultSlug = resolveDefaultSlug();
@@ -22212,12 +22364,12 @@ app34.get("/", (c) => {
22212
22364
  }
22213
22365
  return c.html(cachedHtml("index.html"));
22214
22366
  });
22215
- app34.get("/public", (c) => {
22367
+ app35.get("/public", (c) => {
22216
22368
  const host = (c.req.header("host") ?? "").split(":")[0];
22217
22369
  if (isPublicHost(host)) return c.text("Not found", 404);
22218
22370
  return c.html(cachedHtml("public.html"));
22219
22371
  });
22220
- app34.get("/chat", (c) => {
22372
+ app35.get("/chat", (c) => {
22221
22373
  const host = (c.req.header("host") ?? "").split(":")[0];
22222
22374
  if (isPublicHost(host)) return c.text("Not found", 404);
22223
22375
  return c.html(cachedHtml("public.html"));
@@ -22236,9 +22388,9 @@ async function logViewerFetch(c, next) {
22236
22388
  duration_ms: Date.now() - start
22237
22389
  });
22238
22390
  }
22239
- app34.use("/vnc-viewer.html", logViewerFetch);
22240
- app34.use("/vnc-popout.html", logViewerFetch);
22241
- app34.get("/vnc-popout.html", (c) => {
22391
+ app35.use("/vnc-viewer.html", logViewerFetch);
22392
+ app35.use("/vnc-popout.html", logViewerFetch);
22393
+ app35.get("/vnc-popout.html", (c) => {
22242
22394
  let html = htmlCache.get("vnc-popout.html");
22243
22395
  if (!html) {
22244
22396
  html = readFileSync26(resolve30(process.cwd(), "public", "vnc-popout.html"), "utf-8");
@@ -22251,7 +22403,7 @@ app34.get("/vnc-popout.html", (c) => {
22251
22403
  }
22252
22404
  return c.html(html);
22253
22405
  });
22254
- app34.post("/api/vnc/client-event", async (c) => {
22406
+ app35.post("/api/vnc/client-event", async (c) => {
22255
22407
  let body;
22256
22408
  try {
22257
22409
  body = await c.req.json();
@@ -22272,20 +22424,20 @@ app34.post("/api/vnc/client-event", async (c) => {
22272
22424
  });
22273
22425
  return c.json({ ok: true });
22274
22426
  });
22275
- app34.get("/g/:slug", (c) => {
22427
+ app35.get("/g/:slug", (c) => {
22276
22428
  return c.html(brandedPublicHtml());
22277
22429
  });
22278
- app34.get("/graph", (c) => {
22430
+ app35.get("/graph", (c) => {
22279
22431
  const host = (c.req.header("host") ?? "").split(":")[0];
22280
22432
  if (isPublicHost(host)) return c.text("Not found", 404);
22281
22433
  return c.html(cachedHtml("graph.html"));
22282
22434
  });
22283
- app34.get("/data", (c) => {
22435
+ app35.get("/data", (c) => {
22284
22436
  const host = (c.req.header("host") ?? "").split(":")[0];
22285
22437
  if (isPublicHost(host)) return c.text("Not found", 404);
22286
22438
  return c.html(cachedHtml("data.html"));
22287
22439
  });
22288
- app34.get("/:slug", async (c, next) => {
22440
+ app35.get("/:slug", async (c, next) => {
22289
22441
  const slug = c.req.param("slug");
22290
22442
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
22291
22443
  const branding = loadBrandingCache(slug);
@@ -22294,10 +22446,10 @@ app34.get("/:slug", async (c, next) => {
22294
22446
  }
22295
22447
  await next();
22296
22448
  });
22297
- app34.use("/*", serveStatic({ root: "./public" }));
22449
+ app35.use("/*", serveStatic({ root: "./public" }));
22298
22450
  var port = parseInt(process.env.PORT ?? "19200", 10);
22299
22451
  var hostname = process.env.HOSTNAME ?? "0.0.0.0";
22300
- var httpServer = serve({ fetch: app34.fetch, port, hostname });
22452
+ var httpServer = serve({ fetch: app35.fetch, port, hostname });
22301
22453
  attachVncWsProxy(httpServer, {
22302
22454
  isPublicHost,
22303
22455
  upstreamHost: "127.0.0.1",
@@ -22343,7 +22495,7 @@ for (const m of SUBAPP_MANIFEST) {
22343
22495
  }
22344
22496
  try {
22345
22497
  const registered = [];
22346
- for (const r of app34.routes ?? []) {
22498
+ for (const r of app35.routes ?? []) {
22347
22499
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
22348
22500
  if (AGENT_SLUG_PATTERN.test(r.path)) {
22349
22501
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });