@rubytech/create-realagent 1.0.826 → 1.0.829

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 (103) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +35 -2
  3. package/payload/platform/package.json +2 -2
  4. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +39 -54
  5. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +26 -52
  6. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +7 -7
  7. package/payload/platform/plugins/docs/references/cloudflare.md +1 -1
  8. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  9. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -0
  10. package/payload/platform/plugins/memory/PLUGIN.md +5 -5
  11. package/payload/platform/plugins/memory/mcp/dist/index.js +18 -253
  12. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  13. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +51 -0
  14. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
  15. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +103 -0
  16. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  17. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +19 -4
  18. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
  19. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +149 -56
  20. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
  21. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +16 -1
  22. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +12 -3
  24. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +2 -138
  26. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
  27. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts +2 -0
  28. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts.map +1 -0
  29. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +66 -0
  30. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -0
  31. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts +2 -0
  32. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts.map +1 -0
  33. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +148 -0
  34. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -0
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +1 -64
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +6 -336
  38. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  39. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +30 -0
  40. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  41. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +231 -0
  42. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  43. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +21 -17
  44. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +77 -37
  46. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  47. package/payload/platform/plugins/memory/references/schema-base.md +7 -2
  48. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +54 -4
  49. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  50. package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.d.ts +18 -0
  51. package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.d.ts.map +1 -0
  52. package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.js +31 -0
  53. package/payload/platform/plugins/whatsapp-import/lib/dist/delta-cursor.js.map +1 -0
  54. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts +27 -12
  55. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts.map +1 -1
  56. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js +40 -20
  57. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js.map +1 -1
  58. package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts +7 -4
  59. package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts.map +1 -1
  60. package/payload/platform/plugins/whatsapp-import/lib/dist/index.js +9 -6
  61. package/payload/platform/plugins/whatsapp-import/lib/dist/index.js.map +1 -1
  62. package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.d.ts +25 -0
  63. package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.d.ts.map +1 -0
  64. package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.js +48 -0
  65. package/payload/platform/plugins/whatsapp-import/lib/dist/sessionize.js.map +1 -0
  66. package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.d.ts +3 -0
  67. package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.d.ts.map +1 -0
  68. package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.js +47 -0
  69. package/payload/platform/plugins/whatsapp-import/lib/dist/to-classifier-input.js.map +1 -0
  70. package/payload/platform/scripts/seed-neo4j.sh +15 -14
  71. package/payload/platform/templates/specialists/agents/database-operator.md +10 -17
  72. package/payload/server/chunk-CUSH3UXP.js +2305 -0
  73. package/payload/server/chunk-IWNDVGKT.js +10077 -0
  74. package/payload/server/chunk-KC7NUABI.js +654 -0
  75. package/payload/server/chunk-T2OPNP3L.js +654 -0
  76. package/payload/server/chunk-WUVXPZIV.js +1116 -0
  77. package/payload/server/client-pool-3TM3SRIA.js +32 -0
  78. package/payload/server/cloudflare-task-tracker-4NIODMGL.js +19 -0
  79. package/payload/server/cloudflare-task-tracker-CR6TL4VL.js +19 -0
  80. package/payload/server/maxy-edge.js +3 -3
  81. package/payload/server/neo4j-migrations-XTQ4WEV6.js +428 -0
  82. package/payload/server/public/assets/{admin-DOkUspG1.js → admin-BNwPsMhJ.js} +2 -2
  83. package/payload/server/public/assets/{graph-LLMJa4Ch.js → graph-N_Bw-8oT.js} +1 -1
  84. package/payload/server/public/assets/{page-DoaF3DB0.js → page-BKLGP-th.js} +1 -1
  85. package/payload/server/public/graph.html +2 -2
  86. package/payload/server/public/index.html +2 -2
  87. package/payload/server/server.js +281 -168
  88. package/payload/platform/plugins/whatsapp-import/PLUGIN.md +0 -46
  89. package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +0 -670
  90. package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +0 -131
  91. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/filter-gate.test.ts +0 -172
  92. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/ingest-idempotence.test.ts +0 -141
  93. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export-lrm.test.ts +0 -83
  94. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +0 -678
  95. package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +0 -59
  96. package/payload/platform/plugins/whatsapp-import/lib/src/filter.ts +0 -136
  97. package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +0 -19
  98. package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +0 -471
  99. package/payload/platform/plugins/whatsapp-import/lib/tsconfig.json +0 -9
  100. package/payload/platform/plugins/whatsapp-import/lib/vitest.config.ts +0 -9
  101. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +0 -131
  102. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +0 -109
  103. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import-enrich/SKILL.md +0 -333
@@ -51,7 +51,7 @@ import {
51
51
  vncLog,
52
52
  waitForExit,
53
53
  writeChromiumWrapper
54
- } from "./chunk-HAXOJNAM.js";
54
+ } from "./chunk-IWNDVGKT.js";
55
55
  import {
56
56
  agentLogStream,
57
57
  clearSessionHistory,
@@ -79,7 +79,7 @@ import {
79
79
  sigtermFlushStreamLogs,
80
80
  unregisterSession,
81
81
  validateSession
82
- } from "./chunk-F5QBVHLS.js";
82
+ } from "./chunk-WUVXPZIV.js";
83
83
  import {
84
84
  ACCOUNTS_DIR,
85
85
  PLATFORM_ROOT,
@@ -95,8 +95,9 @@ import {
95
95
  appendCloudflareSteps,
96
96
  completeCloudflareTask,
97
97
  openCloudflareTask,
98
- readTunnelState
99
- } from "./chunk-ZTBTX3IO.js";
98
+ readTunnelState,
99
+ resolveUnitGoneVerdict
100
+ } from "./chunk-KC7NUABI.js";
100
101
  import {
101
102
  GREETING_DIRECTIVE,
102
103
  HAIKU_MODEL,
@@ -128,7 +129,7 @@ import {
128
129
  verifyAndGetConversationUpdatedAt,
129
130
  verifyConversationOwnership,
130
131
  writeAdminUserAndPerson
131
- } from "./chunk-AEHTLEC3.js";
132
+ } from "./chunk-CUSH3UXP.js";
132
133
 
133
134
  // ../lib/graph-trash/dist/index.js
134
135
  var require_dist = __commonJS({
@@ -627,8 +628,8 @@ var serveStatic = (options = { root: "" }) => {
627
628
  };
628
629
 
629
630
  // server/index.ts
630
- import { readFileSync as readFileSync15, existsSync as existsSync21, watchFile } from "fs";
631
- import { resolve as resolve21, join as join9, basename as basename5 } from "path";
631
+ import { readFileSync as readFileSync16, existsSync as existsSync22, watchFile } from "fs";
632
+ import { resolve as resolve22, join as join10, basename as basename5 } from "path";
632
633
  import { homedir as homedir2 } from "os";
633
634
 
634
635
  // app/lib/agent-slug-pattern.ts
@@ -1272,7 +1273,7 @@ var credsSaveQueue = Promise.resolve();
1272
1273
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1273
1274
  console.error(`${TAG3} draining credential save queue\u2026`);
1274
1275
  const timer2 = new Promise(
1275
- (resolve22) => setTimeout(() => resolve22("timeout"), timeoutMs)
1276
+ (resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
1276
1277
  );
1277
1278
  const result = await Promise.race([
1278
1279
  credsSaveQueue.then(() => "drained"),
@@ -1400,11 +1401,11 @@ async function createWaSocket(opts) {
1400
1401
  return sock;
1401
1402
  }
1402
1403
  async function waitForConnection(sock) {
1403
- return new Promise((resolve22, reject) => {
1404
+ return new Promise((resolve23, reject) => {
1404
1405
  const handler = (update) => {
1405
1406
  if (update.connection === "open") {
1406
1407
  sock.ev.off("connection.update", handler);
1407
- resolve22();
1408
+ resolve23();
1408
1409
  }
1409
1410
  if (update.connection === "close") {
1410
1411
  sock.ev.off("connection.update", handler);
@@ -1518,14 +1519,14 @@ ${inspected}`;
1518
1519
  return inspect2(err, INSPECT_OPTS2);
1519
1520
  }
1520
1521
  function withTimeout(label, promise, timeoutMs) {
1521
- return new Promise((resolve22, reject) => {
1522
+ return new Promise((resolve23, reject) => {
1522
1523
  const timer2 = setTimeout(() => {
1523
1524
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1524
1525
  }, timeoutMs);
1525
1526
  promise.then(
1526
1527
  (value) => {
1527
1528
  clearTimeout(timer2);
1528
- resolve22(value);
1529
+ resolve23(value);
1529
1530
  },
1530
1531
  (err) => {
1531
1532
  clearTimeout(timer2);
@@ -2060,8 +2061,8 @@ async function persistWhatsAppMessage(input) {
2060
2061
  const { givenName, familyName } = splitName(input.pushName);
2061
2062
  const prev = sessionWriteLocks.get(input.sessionKey);
2062
2063
  let release;
2063
- const mine = new Promise((resolve22) => {
2064
- release = resolve22;
2064
+ const mine = new Promise((resolve23) => {
2065
+ release = resolve23;
2065
2066
  });
2066
2067
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2067
2068
  sessionWriteLocks.set(input.sessionKey, chained);
@@ -3068,11 +3069,11 @@ async function connectWithReconnect(conn) {
3068
3069
  console.error(
3069
3070
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3070
3071
  );
3071
- await new Promise((resolve22) => {
3072
- const timer2 = setTimeout(resolve22, delay);
3072
+ await new Promise((resolve23) => {
3073
+ const timer2 = setTimeout(resolve23, delay);
3073
3074
  conn.abortController.signal.addEventListener("abort", () => {
3074
3075
  clearTimeout(timer2);
3075
- resolve22();
3076
+ resolve23();
3076
3077
  }, { once: true });
3077
3078
  });
3078
3079
  }
@@ -3080,16 +3081,16 @@ async function connectWithReconnect(conn) {
3080
3081
  }
3081
3082
  }
3082
3083
  function waitForDisconnectEvent(conn) {
3083
- return new Promise((resolve22) => {
3084
+ return new Promise((resolve23) => {
3084
3085
  if (!conn.sock) {
3085
- resolve22();
3086
+ resolve23();
3086
3087
  return;
3087
3088
  }
3088
3089
  const sock = conn.sock;
3089
3090
  const handler = (update) => {
3090
3091
  if (update.connection === "close") {
3091
3092
  sock.ev.off("connection.update", handler);
3092
- resolve22();
3093
+ resolve23();
3093
3094
  }
3094
3095
  };
3095
3096
  sock.ev.on("connection.update", handler);
@@ -3350,8 +3351,8 @@ async function handleInboundMessage(conn, msg) {
3350
3351
  const conversationKey = isGroup ? remoteJid : senderPhone;
3351
3352
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
3352
3353
  let resolvePending;
3353
- const sttPending = new Promise((resolve22) => {
3354
- resolvePending = resolve22;
3354
+ const sttPending = new Promise((resolve23) => {
3355
+ resolvePending = resolve23;
3355
3356
  });
3356
3357
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
3357
3358
  try {
@@ -3472,20 +3473,20 @@ async function probeApiKey() {
3472
3473
  return result.status;
3473
3474
  }
3474
3475
  function checkPort(port2, timeoutMs = 500) {
3475
- return new Promise((resolve22) => {
3476
+ return new Promise((resolve23) => {
3476
3477
  const socket = createConnection(port2, "127.0.0.1");
3477
3478
  socket.setTimeout(timeoutMs);
3478
3479
  socket.once("connect", () => {
3479
3480
  socket.destroy();
3480
- resolve22(true);
3481
+ resolve23(true);
3481
3482
  });
3482
3483
  socket.once("error", () => {
3483
3484
  socket.destroy();
3484
- resolve22(false);
3485
+ resolve23(false);
3485
3486
  });
3486
3487
  socket.once("timeout", () => {
3487
3488
  socket.destroy();
3488
- resolve22(false);
3489
+ resolve23(false);
3489
3490
  });
3490
3491
  });
3491
3492
  }
@@ -5686,8 +5687,8 @@ async function startLogin(opts) {
5686
5687
  resetActiveLogin(accountId);
5687
5688
  let resolveQr = null;
5688
5689
  let rejectQr = null;
5689
- const qrPromise = new Promise((resolve22, reject) => {
5690
- resolveQr = resolve22;
5690
+ const qrPromise = new Promise((resolve23, reject) => {
5691
+ resolveQr = resolve23;
5691
5692
  rejectQr = reject;
5692
5693
  });
5693
5694
  const qrTimer = setTimeout(
@@ -7284,7 +7285,7 @@ var app11 = new Hono();
7284
7285
  app11.post("/cancel", requireAdminSession, async (c) => {
7285
7286
  const session_key = c.var.sessionKey;
7286
7287
  try {
7287
- const { interruptClient: interruptClient2 } = await import("./client-pool-FXCFSUXR.js");
7288
+ const { interruptClient: interruptClient2 } = await import("./client-pool-3TM3SRIA.js");
7288
7289
  await interruptClient2(session_key);
7289
7290
  return c.json({ ok: true });
7290
7291
  } catch (err) {
@@ -8039,6 +8040,17 @@ var agents_default = app16;
8039
8040
  import crypto2 from "crypto";
8040
8041
  import { resolve as resolvePath } from "path";
8041
8042
  import { appendFileSync as appendFileSync4, existsSync as existsSync15 } from "fs";
8043
+
8044
+ // app/lib/synthetic-marker.ts
8045
+ var CLOUDFLARE_MARKER_PREFIX = "Cloudflare setup completed (actionId: ";
8046
+ var COMPONENT_DONE_PREFIX = '{"_componentDone"';
8047
+ var LIFECYCLE_PREFIX = '{"_lifecycle"';
8048
+ function isSyntheticUserMarker(content) {
8049
+ if (typeof content !== "string" || content.length === 0) return false;
8050
+ return content.startsWith(COMPONENT_DONE_PREFIX) || content.startsWith(LIFECYCLE_PREFIX) || content.startsWith(CLOUDFLARE_MARKER_PREFIX);
8051
+ }
8052
+
8053
+ // server/routes/admin/sessions.ts
8042
8054
  function validateAndShapeAttachments(raws, conversationAccountId, conversationId, messageId, streamLogPath) {
8043
8055
  const chips = [];
8044
8056
  let valid = 0;
@@ -8310,6 +8322,7 @@ app17.post("/:id/resume", async (c) => {
8310
8322
  let totalComponents = 0;
8311
8323
  let totalAttachments = 0;
8312
8324
  let totalAttachmentInvalid = 0;
8325
+ let syntheticHidden = 0;
8313
8326
  const rehydrated = messages.map((m) => {
8314
8327
  const components = m.components ?? [];
8315
8328
  const rawAttachments = m.attachments ?? [];
@@ -8318,6 +8331,7 @@ app17.post("/:id/resume", async (c) => {
8318
8331
  totalAttachments += valid2;
8319
8332
  totalAttachmentInvalid += invalid2;
8320
8333
  const cleanedContent = chips.length > 0 ? stripAttachmentMetaSuffix(m.content) : m.content;
8334
+ if (m.role === "user" && isSyntheticUserMarker(cleanedContent)) syntheticHidden += 1;
8321
8335
  return {
8322
8336
  messageId: m.messageId,
8323
8337
  role: m.role,
@@ -8344,7 +8358,7 @@ app17.post("/:id/resume", async (c) => {
8344
8358
  const userMessageCount = rehydrated.filter((m) => m.role !== "assistant").length;
8345
8359
  const reason = bridged ? "post-restart" : "page-refresh";
8346
8360
  try {
8347
- appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} sessionKey=${sessionKey.slice(0, 8)} conversationId=${conversationId.slice(0, 8)} ${tag} loadedMessages=${messages.length} componentCount=${totalComponents} userAttachmentCount=${totalAttachments}
8361
+ appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} sessionKey=${sessionKey.slice(0, 8)} conversationId=${conversationId.slice(0, 8)} ${tag} loadedMessages=${messages.length} componentCount=${totalComponents} userAttachmentCount=${totalAttachments} syntheticHidden=${syntheticHidden}
8348
8362
  `);
8349
8363
  if (totalComponents > 0) {
8350
8364
  appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [component-rehydrate] conversationId=${conversationId.slice(0, 8)} count=${totalComponents} valid=${totalValid} invalid=${totalInvalid} textRuns=${textRuns}
@@ -8357,7 +8371,7 @@ app17.post("/:id/resume", async (c) => {
8357
8371
  } catch {
8358
8372
  }
8359
8373
  const age = formatAge(updatedAt);
8360
- console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} sessionKey=${sessionKey.slice(0, 8)}\u2026`);
8374
+ console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} syntheticHidden=${syntheticHidden} sessionKey=${sessionKey.slice(0, 8)}\u2026`);
8361
8375
  return c.json({ conversationId, messages: rehydrated });
8362
8376
  });
8363
8377
  app17.post("/:id/label", requireAdminSession, async (c) => {
@@ -8880,8 +8894,8 @@ app21.get("/tunnels", requireAdminSession, async (c) => {
8880
8894
  if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
8881
8895
  streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
8882
8896
  const certPath = resolve14(homedir(), brand.configDir, "cloudflared", "cert.pem");
8883
- const { existsSync: existsSync22 } = await import("fs");
8884
- if (!existsSync22(certPath)) {
8897
+ const { existsSync: existsSync23 } = await import("fs");
8898
+ if (!existsSync23(certPath)) {
8885
8899
  return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
8886
8900
  }
8887
8901
  const result = await runFormSpawn({
@@ -9061,38 +9075,63 @@ app21.post("/setup", requireAdminSession, async (c) => {
9061
9075
  } catch (e) {
9062
9076
  logErr(`phase=task-steps-append-failed reason="${e instanceof Error ? e.message : String(e)}"`);
9063
9077
  }
9064
- if (!status || status.execMainStatus !== 0) {
9065
- logErr(`phase=post-exit-skipped reason=${status ? `exit=${status.execMainStatus}` : "unit-gone"} id=${actionId}`);
9078
+ let unitGoneWithDiskProof = false;
9079
+ if (status === null) {
9080
+ const verdict = resolveUnitGoneVerdict({
9081
+ tunnelState: readTunnelState(brand.configDir),
9082
+ expected: { tunnelName: body.tunnelName, tunnelId: body.tunnelId }
9083
+ });
9084
+ const resolution = verdict.kind === "close-completed" ? "close-completed" : "close-failed-diagnostic";
9085
+ log(`phase=post-exit-disk-check tunnel-state-found=${verdict.tunnelStateFound} identity-match=${verdict.identityMatch} resolution=${resolution}`);
9086
+ if (verdict.kind === "close-failed") {
9087
+ try {
9088
+ await completeCloudflareTask({
9089
+ taskId: cloudflareTask.taskId,
9090
+ taskElementId: cloudflareTask.taskElementId,
9091
+ accountId,
9092
+ conversationKey: sessionKey,
9093
+ status: "failed",
9094
+ errorMessage: CLOUDFLARE_TASK_DIAGNOSTICS.endpointDiedPreReconcile
9095
+ });
9096
+ } catch (e) {
9097
+ logErr(`phase=task-close-failed status=failed reason="${e instanceof Error ? e.message : String(e)}"`);
9098
+ }
9099
+ return;
9100
+ }
9101
+ unitGoneWithDiskProof = true;
9102
+ } else if (status.execMainStatus !== 0) {
9103
+ logErr(`phase=post-exit-skipped reason=exit=${status.execMainStatus} id=${actionId}`);
9066
9104
  try {
9067
- const diagnostic = status ? `${CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero} exit=${status.execMainStatus}` : CLOUDFLARE_TASK_DIAGNOSTICS.endpointDiedPreReconcile;
9068
9105
  await completeCloudflareTask({
9069
9106
  taskId: cloudflareTask.taskId,
9070
9107
  taskElementId: cloudflareTask.taskElementId,
9071
9108
  accountId,
9072
9109
  conversationKey: sessionKey,
9073
9110
  status: "failed",
9074
- errorMessage: diagnostic
9111
+ errorMessage: `${CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero} exit=${status.execMainStatus}`
9075
9112
  });
9076
9113
  } catch (e) {
9077
9114
  logErr(`phase=task-close-failed status=failed reason="${e instanceof Error ? e.message : String(e)}"`);
9078
9115
  }
9079
9116
  return;
9080
9117
  }
9081
- const candidates = [publicFqdn, apex].filter((h) => typeof h === "string" && h.length > 0);
9082
- for (const host of candidates) {
9083
- if (host === adminFqdn) {
9084
- log(`phase=alias-domain-write host=${host} result=skipped-admin`);
9085
- continue;
9086
- }
9087
- if (host.startsWith("public.")) {
9088
- log(`phase=alias-domain-write host=${host} result=skipped-public-prefix`);
9089
- continue;
9090
- }
9091
- try {
9092
- addAliasDomain(host);
9093
- log(`phase=alias-domain-write host=${host} result=written`);
9094
- } catch (e) {
9095
- logErr(`phase=alias-domain-write host=${host} result=error reason="${e instanceof Error ? e.message : String(e)}"`);
9118
+ if (!unitGoneWithDiskProof) {
9119
+ const candidates = [publicFqdn, apex].filter((h) => typeof h === "string" && h.length > 0);
9120
+ for (const host of candidates) {
9121
+ if (host === adminFqdn) {
9122
+ log(`phase=alias-domain-write host=${host} result=skipped-admin`);
9123
+ continue;
9124
+ }
9125
+ if (host.startsWith("public.")) {
9126
+ log(`phase=alias-domain-write host=${host} result=skipped-public-prefix`);
9127
+ continue;
9128
+ }
9129
+ try {
9130
+ addAliasDomain(host);
9131
+ log(`phase=alias-domain-write host=${host} result=written`);
9132
+ } catch (e) {
9133
+ logErr(`phase=alias-domain-write host=${host} result=error reason="${e instanceof Error ? e.message : String(e)}"`);
9134
+ }
9096
9135
  }
9097
9136
  }
9098
9137
  try {
@@ -10276,6 +10315,11 @@ var GRAPH_LABEL_COLOURS = {
10276
10315
  AccessGrant: "#66381F",
10277
10316
  // Knowledge — moss family (organic)
10278
10317
  KnowledgeDocument: "#6E8A5A",
10318
+ // Task 891 — chunked WhatsApp/messaging archive parent. Sits in the
10319
+ // knowledge moss family because it's structurally a document parent
10320
+ // (HAS_SECTION → :Section:Conversation chunks); the conversational
10321
+ // plum family is reserved for the live Conversation/Message labels.
10322
+ ConversationArchive: "#82A06A",
10279
10323
  Section: "#8AA876",
10280
10324
  Chunk: "#A6C194",
10281
10325
  DigitalDocument: "#5A7548",
@@ -11742,37 +11786,106 @@ app33.get("/", requireAdminSession, async (c) => {
11742
11786
  });
11743
11787
  var sidebar_artefact_content_default = app33;
11744
11788
 
11745
- // server/routes/admin/index.ts
11789
+ // server/routes/admin/health.ts
11790
+ import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
11791
+ import { resolve as resolve20, join as join9 } from "path";
11792
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
11793
+ var brandHostname = "maxy";
11794
+ var brandJsonPath = join9(PLATFORM_ROOT7, "config", "brand.json");
11795
+ if (existsSync20(brandJsonPath)) {
11796
+ try {
11797
+ const brand = JSON.parse(readFileSync14(brandJsonPath, "utf-8"));
11798
+ if (brand.hostname) brandHostname = brand.hostname;
11799
+ } catch {
11800
+ }
11801
+ }
11802
+ var VERSION_FILE = resolve20(PLATFORM_ROOT7, `config/.${brandHostname}-version`);
11803
+ var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11804
+ var PROBE_TIMEOUT_MS = 1e3;
11805
+ function readVersion() {
11806
+ if (!existsSync20(VERSION_FILE)) return "unknown";
11807
+ return readFileSync14(VERSION_FILE, "utf-8").trim() || "unknown";
11808
+ }
11809
+ async function probeConversationDb() {
11810
+ let session;
11811
+ try {
11812
+ session = getSession();
11813
+ } catch (err) {
11814
+ return { state: "error", reason: err instanceof Error ? err.message : String(err) };
11815
+ }
11816
+ let timer2;
11817
+ try {
11818
+ const probe = session.run("RETURN 1");
11819
+ const timeout = new Promise((_, reject) => {
11820
+ timer2 = setTimeout(() => reject(new Error("timeout")), PROBE_TIMEOUT_MS);
11821
+ });
11822
+ await Promise.race([probe, timeout]);
11823
+ return { state: "ok" };
11824
+ } catch (err) {
11825
+ return { state: "error", reason: err instanceof Error ? err.message : String(err) };
11826
+ } finally {
11827
+ if (timer2) clearTimeout(timer2);
11828
+ session.close().catch(() => {
11829
+ });
11830
+ }
11831
+ }
11746
11832
  var app34 = new Hono();
11747
- app34.route("/session", session_default2);
11748
- app34.route("/chat", chat_default2);
11749
- app34.route("/compact", compact_default);
11750
- app34.route("/logs", logs_default);
11751
- app34.route("/claude-info", claude_info_default);
11752
- app34.route("/attachment", attachment_default);
11753
- app34.route("/agents", agents_default);
11754
- app34.route("/sessions", sessions_default);
11755
- app34.route("/browser", browser_default);
11756
- app34.route("/device-browser", device_browser_default);
11757
- app34.route("/events", events_default);
11758
- app34.route("/cloudflare", cloudflare_default);
11759
- app34.route("/files", files_default);
11760
- app34.route("/graph-search", graph_search_default);
11761
- app34.route("/graph-subgraph", graph_subgraph_default);
11762
- app34.route("/graph-delete", graph_delete_default);
11763
- app34.route("/graph-restore", graph_restore_default);
11764
- app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
11765
- app34.route("/graph-default-view", graph_default_view_default);
11766
- app34.route("/file-attach", file_attach_default);
11767
- app34.route("/adherence", adherence_default);
11768
- app34.route("/sidebar-artefacts", sidebar_artefacts_default);
11769
- app34.route("/sidebar-artefact-save", sidebar_artefact_save_default);
11770
- app34.route("/sidebar-artefact-content", sidebar_artefact_content_default);
11771
- var admin_default = app34;
11833
+ app34.get("/", async (c) => {
11834
+ const version = readVersion();
11835
+ const probe = await probeConversationDb();
11836
+ const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
11837
+ if (probe.state === "error") {
11838
+ const reason = (probe.reason ?? "").replace(/\s+/g, " ").trim() || "unknown";
11839
+ console.log(
11840
+ `[admin/health-brand] processStartedAt=${PROCESS_STARTED_AT} uptimeMs=${uptimeMs} version=${version} conversationDb=error errorReason=${reason}`
11841
+ );
11842
+ } else {
11843
+ console.log(
11844
+ `[admin/health-brand] processStartedAt=${PROCESS_STARTED_AT} uptimeMs=${uptimeMs} version=${version} conversationDb=ok`
11845
+ );
11846
+ }
11847
+ return c.json({
11848
+ ok: true,
11849
+ processStartedAt: PROCESS_STARTED_AT,
11850
+ version,
11851
+ conversationDb: probe.state,
11852
+ uptimeMs
11853
+ });
11854
+ });
11855
+ var health_default2 = app34;
11856
+
11857
+ // server/routes/admin/index.ts
11858
+ var app35 = new Hono();
11859
+ app35.route("/session", session_default2);
11860
+ app35.route("/chat", chat_default2);
11861
+ app35.route("/compact", compact_default);
11862
+ app35.route("/logs", logs_default);
11863
+ app35.route("/claude-info", claude_info_default);
11864
+ app35.route("/attachment", attachment_default);
11865
+ app35.route("/agents", agents_default);
11866
+ app35.route("/sessions", sessions_default);
11867
+ app35.route("/browser", browser_default);
11868
+ app35.route("/device-browser", device_browser_default);
11869
+ app35.route("/events", events_default);
11870
+ app35.route("/cloudflare", cloudflare_default);
11871
+ app35.route("/files", files_default);
11872
+ app35.route("/graph-search", graph_search_default);
11873
+ app35.route("/graph-subgraph", graph_subgraph_default);
11874
+ app35.route("/graph-delete", graph_delete_default);
11875
+ app35.route("/graph-restore", graph_restore_default);
11876
+ app35.route("/graph-labels-in-graph", graph_labels_in_graph_default);
11877
+ app35.route("/graph-default-view", graph_default_view_default);
11878
+ app35.route("/file-attach", file_attach_default);
11879
+ app35.route("/adherence", adherence_default);
11880
+ app35.route("/sidebar-artefacts", sidebar_artefacts_default);
11881
+ app35.route("/sidebar-artefact-save", sidebar_artefact_save_default);
11882
+ app35.route("/sidebar-artefact-content", sidebar_artefact_content_default);
11883
+ app35.route("/health-brand", health_default2);
11884
+ var admin_default = app35;
11772
11885
 
11773
11886
  // server/routes/sites.ts
11774
- import { existsSync as existsSync20, readFileSync as readFileSync14, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
11775
- import { resolve as resolve20 } from "path";
11887
+ import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
11888
+ import { resolve as resolve21 } from "path";
11776
11889
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
11777
11890
  var MIME = {
11778
11891
  ".html": "text/html; charset=utf-8",
@@ -11803,8 +11916,8 @@ function getExt(p) {
11803
11916
  if (idx < p.lastIndexOf("/")) return "";
11804
11917
  return p.slice(idx).toLowerCase();
11805
11918
  }
11806
- var app35 = new Hono();
11807
- app35.get("/:rel{.*}", (c) => {
11919
+ var app36 = new Hono();
11920
+ app36.get("/:rel{.*}", (c) => {
11808
11921
  const reqPath = c.req.path;
11809
11922
  const rawRel = c.req.param("rel") ?? "";
11810
11923
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -11830,28 +11943,28 @@ app35.get("/:rel{.*}", (c) => {
11830
11943
  }
11831
11944
  segments.push(seg);
11832
11945
  }
11833
- const rootDir = resolve20(account.accountDir, "sites");
11834
- let filePath = segments.length === 0 ? rootDir : resolve20(rootDir, ...segments);
11946
+ const rootDir = resolve21(account.accountDir, "sites");
11947
+ let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
11835
11948
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
11836
11949
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
11837
11950
  return c.text("Forbidden", 403);
11838
11951
  }
11839
11952
  let stat7;
11840
11953
  try {
11841
- stat7 = existsSync20(filePath) ? statSync5(filePath) : null;
11954
+ stat7 = existsSync21(filePath) ? statSync5(filePath) : null;
11842
11955
  } catch {
11843
11956
  stat7 = null;
11844
11957
  }
11845
11958
  if (stat7?.isDirectory()) {
11846
- filePath = resolve20(filePath, "index.html");
11959
+ filePath = resolve21(filePath, "index.html");
11847
11960
  } else if (stat7 === null && isDirRequest) {
11848
- filePath = resolve20(filePath, "index.html");
11961
+ filePath = resolve21(filePath, "index.html");
11849
11962
  }
11850
11963
  if (!filePath.startsWith(rootDir + "/")) {
11851
11964
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
11852
11965
  return c.text("Forbidden", 403);
11853
11966
  }
11854
- if (!existsSync20(filePath)) {
11967
+ if (!existsSync21(filePath)) {
11855
11968
  console.error(`[sites] not-found path=${reqPath} status=404`);
11856
11969
  return c.text("Not found", 404);
11857
11970
  }
@@ -11870,7 +11983,7 @@ app35.get("/:rel{.*}", (c) => {
11870
11983
  }
11871
11984
  let body;
11872
11985
  try {
11873
- body = readFileSync14(realPath);
11986
+ body = readFileSync15(realPath);
11874
11987
  } catch (err) {
11875
11988
  const code = err?.code;
11876
11989
  if (code === "EISDIR") {
@@ -11902,7 +12015,7 @@ app35.get("/:rel{.*}", (c) => {
11902
12015
  "X-Content-Type-Options": "nosniff"
11903
12016
  });
11904
12017
  });
11905
- var sites_default = app35;
12018
+ var sites_default = app36;
11906
12019
 
11907
12020
  // app/lib/graph-health.ts
11908
12021
  var HOUR_MS = 60 * 60 * 1e3;
@@ -12001,15 +12114,15 @@ function clientFrom(c) {
12001
12114
  c.req.header("x-forwarded-for")
12002
12115
  );
12003
12116
  }
12004
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
12005
- var BRAND_JSON_PATH = PLATFORM_ROOT7 ? join9(PLATFORM_ROOT7, "config", "brand.json") : "";
12117
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
12118
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join10(PLATFORM_ROOT8, "config", "brand.json") : "";
12006
12119
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
12007
- if (BRAND_JSON_PATH && !existsSync21(BRAND_JSON_PATH)) {
12120
+ if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
12008
12121
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
12009
12122
  }
12010
- if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
12123
+ if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12011
12124
  try {
12012
- const parsed = JSON.parse(readFileSync15(BRAND_JSON_PATH, "utf-8"));
12125
+ const parsed = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
12013
12126
  BRAND = { ...BRAND, ...parsed };
12014
12127
  } catch (err) {
12015
12128
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -12028,11 +12141,11 @@ var brandLoginOpts = {
12028
12141
  bodyFont: BRAND.defaultFonts?.body,
12029
12142
  logoContainsName: !!BRAND.logoContainsName
12030
12143
  };
12031
- var ALIAS_DOMAINS_PATH2 = join9(homedir2(), BRAND.configDir, "alias-domains.json");
12144
+ var ALIAS_DOMAINS_PATH2 = join10(homedir2(), BRAND.configDir, "alias-domains.json");
12032
12145
  function loadAliasDomains() {
12033
12146
  try {
12034
- if (!existsSync21(ALIAS_DOMAINS_PATH2)) return null;
12035
- const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH2, "utf-8"));
12147
+ if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
12148
+ const parsed = JSON.parse(readFileSync16(ALIAS_DOMAINS_PATH2, "utf-8"));
12036
12149
  if (!Array.isArray(parsed)) {
12037
12150
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
12038
12151
  return null;
@@ -12056,9 +12169,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
12056
12169
  function isPublicHost(host) {
12057
12170
  return host.startsWith("public.") || aliasDomains.has(host);
12058
12171
  }
12059
- var app36 = new Hono();
12060
- app36.use("*", clientIpMiddleware);
12061
- app36.use("*", async (c, next) => {
12172
+ var app37 = new Hono();
12173
+ app37.use("*", clientIpMiddleware);
12174
+ app37.use("*", async (c, next) => {
12062
12175
  await next();
12063
12176
  c.header("X-Content-Type-Options", "nosniff");
12064
12177
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -12082,7 +12195,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
12082
12195
  "/sites/"
12083
12196
  ];
12084
12197
  var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
12085
- app36.use("*", async (c, next) => {
12198
+ app37.use("*", async (c, next) => {
12086
12199
  const host = (c.req.header("host") ?? "").split(":")[0];
12087
12200
  if (!isPublicHost(host)) {
12088
12201
  await next();
@@ -12122,7 +12235,7 @@ function resolveRemoteAuthOpts() {
12122
12235
  return brandLoginOpts;
12123
12236
  }
12124
12237
  var MAX_LOGIN_BODY = 8 * 1024;
12125
- app36.post("/__remote-auth/login", async (c) => {
12238
+ app37.post("/__remote-auth/login", async (c) => {
12126
12239
  const client = clientFrom(c);
12127
12240
  const clientIp = client.ip || "unknown";
12128
12241
  if (!requestIsTlsTerminated(c)) {
@@ -12166,7 +12279,7 @@ app36.post("/__remote-auth/login", async (c) => {
12166
12279
  }
12167
12280
  });
12168
12281
  });
12169
- app36.get("/__remote-auth/logout", (c) => {
12282
+ app37.get("/__remote-auth/logout", (c) => {
12170
12283
  return new Response(null, {
12171
12284
  status: 302,
12172
12285
  headers: {
@@ -12176,7 +12289,7 @@ app36.get("/__remote-auth/logout", (c) => {
12176
12289
  }
12177
12290
  });
12178
12291
  });
12179
- app36.post("/__remote-auth/change-password", async (c) => {
12292
+ app37.post("/__remote-auth/change-password", async (c) => {
12180
12293
  const client = clientFrom(c);
12181
12294
  const clientIp = client.ip || "unknown";
12182
12295
  const rateLimited = checkRateLimit(client);
@@ -12226,13 +12339,13 @@ app36.post("/__remote-auth/change-password", async (c) => {
12226
12339
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
12227
12340
  }
12228
12341
  });
12229
- app36.get("/__remote-auth/setup", (c) => {
12342
+ app37.get("/__remote-auth/setup", (c) => {
12230
12343
  if (isRemoteAuthConfigured()) {
12231
12344
  return c.redirect("/");
12232
12345
  }
12233
12346
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
12234
12347
  });
12235
- app36.post("/__remote-auth/set-initial-password", async (c) => {
12348
+ app37.post("/__remote-auth/set-initial-password", async (c) => {
12236
12349
  if (isRemoteAuthConfigured()) {
12237
12350
  return c.redirect("/");
12238
12351
  }
@@ -12268,10 +12381,10 @@ app36.post("/__remote-auth/set-initial-password", async (c) => {
12268
12381
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
12269
12382
  }
12270
12383
  });
12271
- app36.get("/api/remote-auth/status", (c) => {
12384
+ app37.get("/api/remote-auth/status", (c) => {
12272
12385
  return c.json({ configured: isRemoteAuthConfigured() });
12273
12386
  });
12274
- app36.post("/api/remote-auth/set-password", async (c) => {
12387
+ app37.post("/api/remote-auth/set-password", async (c) => {
12275
12388
  let body;
12276
12389
  try {
12277
12390
  body = await c.req.json();
@@ -12301,9 +12414,9 @@ app36.post("/api/remote-auth/set-password", async (c) => {
12301
12414
  return c.json({ error: "Failed to save password" }, 500);
12302
12415
  }
12303
12416
  });
12304
- app36.route("/api/_client-error", client_error_default);
12417
+ app37.route("/api/_client-error", client_error_default);
12305
12418
  console.log("[client-error-route] mounted");
12306
- app36.use("*", async (c, next) => {
12419
+ app37.use("*", async (c, next) => {
12307
12420
  const host = (c.req.header("host") ?? "").split(":")[0];
12308
12421
  const path2 = c.req.path;
12309
12422
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -12336,15 +12449,15 @@ app36.use("*", async (c, next) => {
12336
12449
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
12337
12450
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
12338
12451
  });
12339
- app36.route("/api/health", health_default);
12340
- app36.route("/api/session", session_default);
12341
- app36.route("/api/chat", chat_default);
12342
- app36.route("/api/group", group_default);
12343
- app36.route("/api/access", access_default);
12344
- app36.route("/api/telegram", telegram_default);
12345
- app36.route("/api/whatsapp", whatsapp_default);
12346
- app36.route("/api/onboarding", onboarding_default);
12347
- app36.route("/api/admin", admin_default);
12452
+ app37.route("/api/health", health_default);
12453
+ app37.route("/api/session", session_default);
12454
+ app37.route("/api/chat", chat_default);
12455
+ app37.route("/api/group", group_default);
12456
+ app37.route("/api/access", access_default);
12457
+ app37.route("/api/telegram", telegram_default);
12458
+ app37.route("/api/whatsapp", whatsapp_default);
12459
+ app37.route("/api/onboarding", onboarding_default);
12460
+ app37.route("/api/admin", admin_default);
12348
12461
  var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
12349
12462
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12350
12463
  var IMAGE_MIME = {
@@ -12356,7 +12469,7 @@ var IMAGE_MIME = {
12356
12469
  ".svg": "image/svg+xml",
12357
12470
  ".ico": "image/x-icon"
12358
12471
  };
12359
- app36.get("/agent-assets/:slug/:filename", (c) => {
12472
+ app37.get("/agent-assets/:slug/:filename", (c) => {
12360
12473
  const slug = c.req.param("slug");
12361
12474
  const filename = c.req.param("filename");
12362
12475
  if (!SAFE_SLUG_RE.test(slug)) {
@@ -12372,26 +12485,26 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
12372
12485
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
12373
12486
  return c.text("Not found", 404);
12374
12487
  }
12375
- const filePath = resolve21(account.accountDir, "agents", slug, "assets", filename);
12376
- const expectedDir = resolve21(account.accountDir, "agents", slug, "assets");
12488
+ const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
12489
+ const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
12377
12490
  if (!filePath.startsWith(expectedDir + "/")) {
12378
12491
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
12379
12492
  return c.text("Forbidden", 403);
12380
12493
  }
12381
- if (!existsSync21(filePath)) {
12494
+ if (!existsSync22(filePath)) {
12382
12495
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
12383
12496
  return c.text("Not found", 404);
12384
12497
  }
12385
12498
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12386
12499
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12387
12500
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
12388
- const body = readFileSync15(filePath);
12501
+ const body = readFileSync16(filePath);
12389
12502
  return c.body(body, 200, {
12390
12503
  "Content-Type": contentType,
12391
12504
  "Cache-Control": "public, max-age=3600"
12392
12505
  });
12393
12506
  });
12394
- app36.get("/generated/:filename", (c) => {
12507
+ app37.get("/generated/:filename", (c) => {
12395
12508
  const filename = c.req.param("filename");
12396
12509
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
12397
12510
  console.error(`[generated] serve file=${filename} status=403`);
@@ -12402,32 +12515,32 @@ app36.get("/generated/:filename", (c) => {
12402
12515
  console.error(`[generated] serve file=${filename} status=404`);
12403
12516
  return c.text("Not found", 404);
12404
12517
  }
12405
- const filePath = resolve21(account.accountDir, "generated", filename);
12406
- const expectedDir = resolve21(account.accountDir, "generated");
12518
+ const filePath = resolve22(account.accountDir, "generated", filename);
12519
+ const expectedDir = resolve22(account.accountDir, "generated");
12407
12520
  if (!filePath.startsWith(expectedDir + "/")) {
12408
12521
  console.error(`[generated] serve file=${filename} status=403`);
12409
12522
  return c.text("Forbidden", 403);
12410
12523
  }
12411
- if (!existsSync21(filePath)) {
12524
+ if (!existsSync22(filePath)) {
12412
12525
  console.error(`[generated] serve file=${filename} status=404`);
12413
12526
  return c.text("Not found", 404);
12414
12527
  }
12415
12528
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12416
12529
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12417
12530
  console.log(`[generated] serve file=${filename} status=200`);
12418
- const body = readFileSync15(filePath);
12531
+ const body = readFileSync16(filePath);
12419
12532
  return c.body(body, 200, {
12420
12533
  "Content-Type": contentType,
12421
12534
  "Cache-Control": "public, max-age=86400"
12422
12535
  });
12423
12536
  });
12424
- app36.route("/sites", sites_default);
12537
+ app37.route("/sites", sites_default);
12425
12538
  var htmlCache = /* @__PURE__ */ new Map();
12426
12539
  var brandLogoPath = "/brand/maxy-monochrome.png";
12427
12540
  var brandIconPath = "/brand/maxy-monochrome.png";
12428
- if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
12541
+ if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12429
12542
  try {
12430
- const fullBrand = JSON.parse(readFileSync15(BRAND_JSON_PATH, "utf-8"));
12543
+ const fullBrand = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
12431
12544
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
12432
12545
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
12433
12546
  } catch {
@@ -12443,10 +12556,10 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
12443
12556
  })}</script>`;
12444
12557
  function readInstalledVersion() {
12445
12558
  try {
12446
- if (!PLATFORM_ROOT7) return "unknown";
12447
- const versionFile = join9(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
12448
- if (!existsSync21(versionFile)) return "unknown";
12449
- const content = readFileSync15(versionFile, "utf-8").trim();
12559
+ if (!PLATFORM_ROOT8) return "unknown";
12560
+ const versionFile = join10(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
12561
+ if (!existsSync22(versionFile)) return "unknown";
12562
+ const content = readFileSync16(versionFile, "utf-8").trim();
12450
12563
  return content || "unknown";
12451
12564
  } catch {
12452
12565
  return "unknown";
@@ -12487,7 +12600,7 @@ var clientErrorReporterScript = `<script>
12487
12600
  function cachedHtml(file) {
12488
12601
  let html = htmlCache.get(file);
12489
12602
  if (!html) {
12490
- html = readFileSync15(resolve21(process.cwd(), "public", file), "utf-8");
12603
+ html = readFileSync16(resolve22(process.cwd(), "public", file), "utf-8");
12491
12604
  const productNameEsc = escapeHtml(BRAND.productName);
12492
12605
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
12493
12606
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -12503,26 +12616,26 @@ ${clientErrorReporterScript}
12503
12616
  }
12504
12617
  var brandedHtmlCache = /* @__PURE__ */ new Map();
12505
12618
  function loadBrandingCache(agentSlug) {
12506
- const configDir2 = join9(homedir2(), BRAND.configDir);
12619
+ const configDir2 = join10(homedir2(), BRAND.configDir);
12507
12620
  try {
12508
- const accountJsonPath = join9(configDir2, "account.json");
12509
- if (!existsSync21(accountJsonPath)) return null;
12510
- const account = JSON.parse(readFileSync15(accountJsonPath, "utf-8"));
12621
+ const accountJsonPath = join10(configDir2, "account.json");
12622
+ if (!existsSync22(accountJsonPath)) return null;
12623
+ const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
12511
12624
  const accountId = account.accountId;
12512
12625
  if (!accountId) return null;
12513
- const cachePath = join9(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
12514
- if (!existsSync21(cachePath)) return null;
12515
- return JSON.parse(readFileSync15(cachePath, "utf-8"));
12626
+ const cachePath = join10(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
12627
+ if (!existsSync22(cachePath)) return null;
12628
+ return JSON.parse(readFileSync16(cachePath, "utf-8"));
12516
12629
  } catch {
12517
12630
  return null;
12518
12631
  }
12519
12632
  }
12520
12633
  function resolveDefaultSlug() {
12521
12634
  try {
12522
- const configDir2 = join9(homedir2(), BRAND.configDir);
12523
- const accountJsonPath = join9(configDir2, "account.json");
12524
- if (!existsSync21(accountJsonPath)) return null;
12525
- const account = JSON.parse(readFileSync15(accountJsonPath, "utf-8"));
12635
+ const configDir2 = join10(homedir2(), BRAND.configDir);
12636
+ const accountJsonPath = join10(configDir2, "account.json");
12637
+ if (!existsSync22(accountJsonPath)) return null;
12638
+ const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
12526
12639
  return account.defaultAgent || null;
12527
12640
  } catch {
12528
12641
  return null;
@@ -12558,7 +12671,7 @@ function brandedPublicHtml(agentSlug) {
12558
12671
  function escapeHtml(s) {
12559
12672
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
12560
12673
  }
12561
- app36.get("/", (c) => {
12674
+ app37.get("/", (c) => {
12562
12675
  const host = (c.req.header("host") ?? "").split(":")[0];
12563
12676
  if (isPublicHost(host)) {
12564
12677
  const defaultSlug = resolveDefaultSlug();
@@ -12566,12 +12679,12 @@ app36.get("/", (c) => {
12566
12679
  }
12567
12680
  return c.html(cachedHtml("index.html"));
12568
12681
  });
12569
- app36.get("/public", (c) => {
12682
+ app37.get("/public", (c) => {
12570
12683
  const host = (c.req.header("host") ?? "").split(":")[0];
12571
12684
  if (isPublicHost(host)) return c.text("Not found", 404);
12572
12685
  return c.html(cachedHtml("public.html"));
12573
12686
  });
12574
- app36.get("/chat", (c) => {
12687
+ app37.get("/chat", (c) => {
12575
12688
  const host = (c.req.header("host") ?? "").split(":")[0];
12576
12689
  if (isPublicHost(host)) return c.text("Not found", 404);
12577
12690
  return c.html(cachedHtml("public.html"));
@@ -12590,12 +12703,12 @@ async function logViewerFetch(c, next) {
12590
12703
  duration_ms: Date.now() - start
12591
12704
  });
12592
12705
  }
12593
- app36.use("/vnc-viewer.html", logViewerFetch);
12594
- app36.use("/vnc-popout.html", logViewerFetch);
12595
- app36.get("/vnc-popout.html", (c) => {
12706
+ app37.use("/vnc-viewer.html", logViewerFetch);
12707
+ app37.use("/vnc-popout.html", logViewerFetch);
12708
+ app37.get("/vnc-popout.html", (c) => {
12596
12709
  let html = htmlCache.get("vnc-popout.html");
12597
12710
  if (!html) {
12598
- html = readFileSync15(resolve21(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12711
+ html = readFileSync16(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12599
12712
  const name = escapeHtml(BRAND.productName);
12600
12713
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
12601
12714
  html = html.replace("</head>", ` ${brandScript}
@@ -12605,7 +12718,7 @@ app36.get("/vnc-popout.html", (c) => {
12605
12718
  }
12606
12719
  return c.html(html);
12607
12720
  });
12608
- app36.post("/api/vnc/client-event", async (c) => {
12721
+ app37.post("/api/vnc/client-event", async (c) => {
12609
12722
  let body;
12610
12723
  try {
12611
12724
  body = await c.req.json();
@@ -12626,20 +12739,20 @@ app36.post("/api/vnc/client-event", async (c) => {
12626
12739
  });
12627
12740
  return c.json({ ok: true });
12628
12741
  });
12629
- app36.get("/g/:slug", (c) => {
12742
+ app37.get("/g/:slug", (c) => {
12630
12743
  return c.html(brandedPublicHtml());
12631
12744
  });
12632
- app36.get("/graph", (c) => {
12745
+ app37.get("/graph", (c) => {
12633
12746
  const host = (c.req.header("host") ?? "").split(":")[0];
12634
12747
  if (isPublicHost(host)) return c.text("Not found", 404);
12635
12748
  return c.html(cachedHtml("graph.html"));
12636
12749
  });
12637
- app36.get("/data", (c) => {
12750
+ app37.get("/data", (c) => {
12638
12751
  const host = (c.req.header("host") ?? "").split(":")[0];
12639
12752
  if (isPublicHost(host)) return c.text("Not found", 404);
12640
12753
  return c.html(cachedHtml("data.html"));
12641
12754
  });
12642
- app36.get("/:slug", async (c, next) => {
12755
+ app37.get("/:slug", async (c, next) => {
12643
12756
  const slug = c.req.param("slug");
12644
12757
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
12645
12758
  const branding = loadBrandingCache(slug);
@@ -12648,10 +12761,10 @@ app36.get("/:slug", async (c, next) => {
12648
12761
  }
12649
12762
  await next();
12650
12763
  });
12651
- app36.use("/*", serveStatic({ root: "./public" }));
12764
+ app37.use("/*", serveStatic({ root: "./public" }));
12652
12765
  var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
12653
12766
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
12654
- var httpServer = serve({ fetch: app36.fetch, port, hostname });
12767
+ var httpServer = serve({ fetch: app37.fetch, port, hostname });
12655
12768
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
12656
12769
  var SUBAPP_MANIFEST = [
12657
12770
  { prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
@@ -12671,7 +12784,7 @@ for (const m of SUBAPP_MANIFEST) {
12671
12784
  }
12672
12785
  try {
12673
12786
  const registered = [];
12674
- for (const r of app36.routes ?? []) {
12787
+ for (const r of app37.routes ?? []) {
12675
12788
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
12676
12789
  if (AGENT_SLUG_PATTERN.test(r.path)) {
12677
12790
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -12685,8 +12798,8 @@ try {
12685
12798
  (async () => {
12686
12799
  try {
12687
12800
  let userId = "";
12688
- if (existsSync21(USERS_FILE)) {
12689
- const users = JSON.parse(readFileSync15(USERS_FILE, "utf-8").trim() || "[]");
12801
+ if (existsSync22(USERS_FILE)) {
12802
+ const users = JSON.parse(readFileSync16(USERS_FILE, "utf-8").trim() || "[]");
12690
12803
  userId = users[0]?.userId ?? "";
12691
12804
  }
12692
12805
  await backfillNullUserIdConversations(userId);
@@ -12719,7 +12832,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
12719
12832
  (async () => {
12720
12833
  if (!bootAccount) return;
12721
12834
  try {
12722
- const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-BAMJY4MH.js");
12835
+ const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-4NIODMGL.js");
12723
12836
  const result = await recoverRunningCloudflareTasks(
12724
12837
  bootAccount.accountId,
12725
12838
  configDirForWhatsApp,
@@ -12769,7 +12882,7 @@ if (bootAccountConfig?.whatsapp) {
12769
12882
  }
12770
12883
  init({
12771
12884
  configDir: configDirForWhatsApp,
12772
- platformRoot: resolve21(process.env.MAXY_PLATFORM_ROOT ?? join9(__dirname, "..")),
12885
+ platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
12773
12886
  accountConfig: bootAccountConfig,
12774
12887
  onMessage: async (msg) => {
12775
12888
  try {