@rubytech/create-maxy 1.0.808 → 1.0.809

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 (39) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/memory/mcp/dist/index.js +86 -0
  3. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  4. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts +23 -0
  5. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts.map +1 -0
  6. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js +401 -0
  7. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js.map +1 -0
  8. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts +28 -0
  9. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts.map +1 -0
  10. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js +34 -0
  11. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js.map +1 -0
  12. package/payload/platform/plugins/memory/references/schema-base.md +12 -0
  13. package/payload/platform/plugins/whatsapp/PLUGIN.md +3 -1
  14. package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +225 -346
  15. package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +28 -10
  16. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts +21 -0
  17. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.d.ts.map +1 -0
  18. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js +41 -0
  19. package/payload/platform/plugins/whatsapp-import/lib/dist/derive-keys.js.map +1 -0
  20. package/payload/platform/plugins/whatsapp-import/lib/dist/filter.d.ts +29 -0
  21. package/payload/platform/plugins/whatsapp-import/lib/dist/filter.d.ts.map +1 -0
  22. package/payload/platform/plugins/whatsapp-import/lib/dist/filter.js +123 -0
  23. package/payload/platform/plugins/whatsapp-import/lib/dist/filter.js.map +1 -0
  24. package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts +4 -0
  25. package/payload/platform/plugins/whatsapp-import/lib/dist/index.d.ts.map +1 -1
  26. package/payload/platform/plugins/whatsapp-import/lib/dist/index.js +9 -1
  27. package/payload/platform/plugins/whatsapp-import/lib/dist/index.js.map +1 -1
  28. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/filter-gate.test.ts +170 -0
  29. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/ingest-idempotence.test.ts +141 -0
  30. package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +59 -0
  31. package/payload/platform/plugins/whatsapp-import/lib/src/filter.ts +136 -0
  32. package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +12 -0
  33. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +80 -25
  34. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import-enrich/SKILL.md +22 -3
  35. package/payload/platform/templates/specialists/agents/database-operator.md +9 -4
  36. package/payload/server/public/assets/admin-Bwrd2DBq.js +352 -0
  37. package/payload/server/public/index.html +1 -1
  38. package/payload/server/server.js +271 -188
  39. package/payload/server/public/assets/admin-MxaCgGHZ.js +0 -352
@@ -619,15 +619,15 @@ var serveStatic = (options = { root: "" }) => {
619
619
  };
620
620
 
621
621
  // server/index.ts
622
- import { readFileSync as readFileSync18, existsSync as existsSync25, watchFile } from "fs";
623
- import { resolve as resolve24, join as join11, basename as basename7 } from "path";
622
+ import { readFileSync as readFileSync19, existsSync as existsSync25, watchFile } from "fs";
623
+ import { resolve as resolve25, join as join11, basename as basename7 } from "path";
624
624
  import { homedir as homedir2 } from "os";
625
625
 
626
626
  // app/lib/agent-slug-pattern.ts
627
627
  var AGENT_SLUG_PATTERN = /^\/([a-z][a-z0-9-]{2,49})$/;
628
628
 
629
629
  // server/routes/health.ts
630
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
630
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
631
631
  import { createConnection } from "net";
632
632
 
633
633
  // app/lib/network.ts
@@ -2836,7 +2836,7 @@ var credsSaveQueue = Promise.resolve();
2836
2836
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
2837
2837
  console.error(`${TAG3} draining credential save queue\u2026`);
2838
2838
  const timer2 = new Promise(
2839
- (resolve25) => setTimeout(() => resolve25("timeout"), timeoutMs)
2839
+ (resolve26) => setTimeout(() => resolve26("timeout"), timeoutMs)
2840
2840
  );
2841
2841
  const result = await Promise.race([
2842
2842
  credsSaveQueue.then(() => "drained"),
@@ -2964,11 +2964,11 @@ async function createWaSocket(opts) {
2964
2964
  return sock;
2965
2965
  }
2966
2966
  async function waitForConnection(sock) {
2967
- return new Promise((resolve25, reject) => {
2967
+ return new Promise((resolve26, reject) => {
2968
2968
  const handler = (update) => {
2969
2969
  if (update.connection === "open") {
2970
2970
  sock.ev.off("connection.update", handler);
2971
- resolve25();
2971
+ resolve26();
2972
2972
  }
2973
2973
  if (update.connection === "close") {
2974
2974
  sock.ev.off("connection.update", handler);
@@ -3082,14 +3082,14 @@ ${inspected}`;
3082
3082
  return inspect2(err, INSPECT_OPTS2);
3083
3083
  }
3084
3084
  function withTimeout(label, promise, timeoutMs) {
3085
- return new Promise((resolve25, reject) => {
3085
+ return new Promise((resolve26, reject) => {
3086
3086
  const timer2 = setTimeout(() => {
3087
3087
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
3088
3088
  }, timeoutMs);
3089
3089
  promise.then(
3090
3090
  (value) => {
3091
3091
  clearTimeout(timer2);
3092
- resolve25(value);
3092
+ resolve26(value);
3093
3093
  },
3094
3094
  (err) => {
3095
3095
  clearTimeout(timer2);
@@ -3610,8 +3610,8 @@ async function persistWhatsAppMessage(input) {
3610
3610
  const { givenName, familyName } = splitName(input.pushName);
3611
3611
  const prev = sessionWriteLocks.get(input.sessionKey);
3612
3612
  let release;
3613
- const mine = new Promise((resolve25) => {
3614
- release = resolve25;
3613
+ const mine = new Promise((resolve26) => {
3614
+ release = resolve26;
3615
3615
  });
3616
3616
  const chained = (prev ?? Promise.resolve()).then(() => mine);
3617
3617
  sessionWriteLocks.set(input.sessionKey, chained);
@@ -3629,7 +3629,7 @@ async function persistWhatsAppMessage(input) {
3629
3629
  existingM IS NOT NULL AS messageExisted
3630
3630
  MERGE (s:Person {telephone: $senderTelephone})
3631
3631
  ON CREATE SET
3632
- s.accountId = $accountId,
3632
+ s.accountId = $platformAccountId,
3633
3633
  s.givenName = $givenName,
3634
3634
  s.familyName = $familyName,
3635
3635
  s.source = 'whatsapp-live',
@@ -3641,7 +3641,7 @@ async function persistWhatsAppMessage(input) {
3641
3641
  MERGE (m:Message {messageId: $messageId})
3642
3642
  ON CREATE SET
3643
3643
  m:WhatsAppMessage,
3644
- m.accountId = $accountId,
3644
+ m.accountId = $platformAccountId,
3645
3645
  m.conversationId = c.conversationId,
3646
3646
  m.source = 'whatsapp',
3647
3647
  m.createdByAgent = 'whatsapp-live',
@@ -3687,7 +3687,7 @@ async function persistWhatsAppMessage(input) {
3687
3687
  const params = {
3688
3688
  sessionKey: input.sessionKey,
3689
3689
  messageId,
3690
- accountId: input.accountId,
3690
+ platformAccountId: input.platformAccountId,
3691
3691
  senderTelephone,
3692
3692
  senderName: input.pushName ?? null,
3693
3693
  givenName,
@@ -3704,7 +3704,7 @@ async function persistWhatsAppMessage(input) {
3704
3704
  const result = await session.run(cypher, params);
3705
3705
  const ms = Date.now() - t0;
3706
3706
  if (result.records.length === 0) {
3707
- console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.accountId} sessionKey=${input.sessionKey} messageId=${messageId}`);
3707
+ console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.platformAccountId} sessionKey=${input.sessionKey} messageId=${messageId}`);
3708
3708
  return null;
3709
3709
  }
3710
3710
  const rec = result.records[0];
@@ -3725,14 +3725,14 @@ async function persistWhatsAppMessage(input) {
3725
3725
  console.error(`${TAG7} next-skip reason=no-prior msgId=${messageId}`);
3726
3726
  }
3727
3727
  console.error(
3728
- `${TAG7} write messageId=${messageId} sessionKey=${input.sessionKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
3728
+ `${TAG7} write messageId=${messageId} accountId=${input.platformAccountId} sessionKey=${input.sessionKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
3729
3729
  );
3730
3730
  return { messageId, created: true, senderElementId };
3731
3731
  } catch (err) {
3732
3732
  const ms = Date.now() - t0;
3733
3733
  const reason = sanitizeReason(err);
3734
3734
  console.error(
3735
- `${TAG7} FAIL accountId=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
3735
+ `${TAG7} FAIL accountId=${input.platformAccountId} waname=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
3736
3736
  );
3737
3737
  return null;
3738
3738
  } finally {
@@ -3770,7 +3770,7 @@ async function ensureWhatsAppConversation(input) {
3770
3770
  const t0 = Date.now();
3771
3771
  try {
3772
3772
  const result = await ensureConversation(
3773
- input.accountId,
3773
+ input.platformAccountId,
3774
3774
  input.agentType,
3775
3775
  input.sessionKey
3776
3776
  );
@@ -3795,6 +3795,52 @@ async function ensureWhatsAppConversation(input) {
3795
3795
  }
3796
3796
  }
3797
3797
 
3798
+ // app/lib/whatsapp/platform-account-id.ts
3799
+ import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
3800
+ import { resolve as resolve6 } from "path";
3801
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3802
+ var cached = null;
3803
+ var cachedAccountsDir = null;
3804
+ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
3805
+ if (cached !== null && cachedAccountsDir === accountsDir) return cached;
3806
+ const valid = enumerateValidAccountIds(accountsDir);
3807
+ if (valid.length === 0) {
3808
+ throw new Error(
3809
+ `[whatsapp-persist] resolvePlatformAccountId: no platform account found under ${accountsDir} \u2014 corrupt install? Cannot stamp n.accountId without a valid UUID.`
3810
+ );
3811
+ }
3812
+ if (valid.length > 1) {
3813
+ throw new Error(
3814
+ `[whatsapp-persist] resolvePlatformAccountId: multiple platform accounts found under ${accountsDir} (${valid.join(", ")}) \u2014 Phase 0 invariant requires exactly one. Loud-fail rather than picking one silently.`
3815
+ );
3816
+ }
3817
+ cached = valid[0];
3818
+ cachedAccountsDir = accountsDir;
3819
+ return cached;
3820
+ }
3821
+ function enumerateValidAccountIds(accountsDir) {
3822
+ let names;
3823
+ try {
3824
+ names = readdirSync2(accountsDir);
3825
+ } catch (err) {
3826
+ if (err.code === "ENOENT") return [];
3827
+ throw err;
3828
+ }
3829
+ const valid = [];
3830
+ for (const name of names) {
3831
+ if (!UUID_RE.test(name)) continue;
3832
+ const configPath2 = resolve6(accountsDir, name, "account.json");
3833
+ try {
3834
+ JSON.parse(readFileSync5(configPath2, "utf-8"));
3835
+ valid.push(name);
3836
+ } catch (err) {
3837
+ const code = err.code;
3838
+ if (code === "ENOENT") continue;
3839
+ }
3840
+ }
3841
+ return valid;
3842
+ }
3843
+
3798
3844
  // app/lib/whatsapp/inbound/media.ts
3799
3845
  import { randomUUID as randomUUID3 } from "crypto";
3800
3846
  import { writeFile, mkdir } from "fs/promises";
@@ -4273,9 +4319,23 @@ async function startConnection(accountId) {
4273
4319
  console.error(`${TAG13} no credentials for account=${accountId}`);
4274
4320
  return;
4275
4321
  }
4322
+ let platformAccountId;
4323
+ try {
4324
+ platformAccountId = resolvePlatformAccountId();
4325
+ console.error(
4326
+ `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
4327
+ );
4328
+ } catch (err) {
4329
+ const reason = err instanceof Error ? err.message : String(err);
4330
+ console.error(
4331
+ `[whatsapp-persist] resolved-account-id FAIL waname=${accountId} reason=${reason}`
4332
+ );
4333
+ throw err;
4334
+ }
4276
4335
  await stopConnection(accountId);
4277
4336
  const conn = {
4278
4337
  accountId,
4338
+ platformAccountId,
4279
4339
  accountName: whatsAppConfig.accounts?.[accountId]?.name,
4280
4340
  authDir,
4281
4341
  sock: null,
@@ -4330,11 +4390,25 @@ function getSocket(accountId) {
4330
4390
  }
4331
4391
  async function registerLoginSocket(accountId, sock, authDir) {
4332
4392
  if (!configDir) throw new Error("WhatsApp manager not initialized");
4393
+ let platformAccountId;
4394
+ try {
4395
+ platformAccountId = resolvePlatformAccountId();
4396
+ console.error(
4397
+ `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
4398
+ );
4399
+ } catch (err) {
4400
+ const reason = err instanceof Error ? err.message : String(err);
4401
+ console.error(
4402
+ `[whatsapp-persist] resolved-account-id FAIL waname=${accountId} reason=${reason}`
4403
+ );
4404
+ throw err;
4405
+ }
4333
4406
  await stopConnection(accountId);
4334
4407
  const selfId = readSelfId(authDir);
4335
4408
  const lidMapping = sock.signalRepository?.lidMapping ?? null;
4336
4409
  const conn = {
4337
4410
  accountId,
4411
+ platformAccountId,
4338
4412
  accountName: whatsAppConfig.accounts?.[accountId]?.name,
4339
4413
  authDir,
4340
4414
  sock,
@@ -4500,11 +4574,11 @@ async function connectWithReconnect(conn) {
4500
4574
  console.error(
4501
4575
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
4502
4576
  );
4503
- await new Promise((resolve25) => {
4504
- const timer2 = setTimeout(resolve25, delay);
4577
+ await new Promise((resolve26) => {
4578
+ const timer2 = setTimeout(resolve26, delay);
4505
4579
  conn.abortController.signal.addEventListener("abort", () => {
4506
4580
  clearTimeout(timer2);
4507
- resolve25();
4581
+ resolve26();
4508
4582
  }, { once: true });
4509
4583
  });
4510
4584
  }
@@ -4512,16 +4586,16 @@ async function connectWithReconnect(conn) {
4512
4586
  }
4513
4587
  }
4514
4588
  function waitForDisconnectEvent(conn) {
4515
- return new Promise((resolve25) => {
4589
+ return new Promise((resolve26) => {
4516
4590
  if (!conn.sock) {
4517
- resolve25();
4591
+ resolve26();
4518
4592
  return;
4519
4593
  }
4520
4594
  const sock = conn.sock;
4521
4595
  const handler = (update) => {
4522
4596
  if (update.connection === "close") {
4523
4597
  sock.ev.off("connection.update", handler);
4524
- resolve25();
4598
+ resolve26();
4525
4599
  }
4526
4600
  };
4527
4601
  sock.ev.on("connection.update", handler);
@@ -4542,8 +4616,8 @@ function watchForDisconnect(conn) {
4542
4616
  });
4543
4617
  }
4544
4618
  async function getGroupMeta(conn, jid) {
4545
- const cached = conn.groupMetaCache.get(jid);
4546
- if (cached && cached.expires > Date.now()) return cached;
4619
+ const cached2 = conn.groupMetaCache.get(jid);
4620
+ if (cached2 && cached2.expires > Date.now()) return cached2;
4547
4621
  if (!conn.sock) return null;
4548
4622
  console.error(`${TAG13} group metadata cache miss for ${jid}, fetching from Baileys account=${conn.accountId}`);
4549
4623
  try {
@@ -4655,6 +4729,7 @@ function monitorInbound(conn) {
4655
4729
  if (msg.key.id) {
4656
4730
  const merged = await ensureWhatsAppConversation({
4657
4731
  accountId: conn.accountId,
4732
+ platformAccountId: conn.platformAccountId,
4658
4733
  sessionKey,
4659
4734
  agentType: sessionKeyAgentType,
4660
4735
  groupJid: isGroup ? remoteJid : void 0
@@ -4662,6 +4737,7 @@ function monitorInbound(conn) {
4662
4737
  if (merged) {
4663
4738
  await persistWhatsAppMessage({
4664
4739
  accountId: conn.accountId,
4740
+ platformAccountId: conn.platformAccountId,
4665
4741
  remoteJid,
4666
4742
  sessionKey,
4667
4743
  msgKeyId: msg.key.id,
@@ -4780,8 +4856,8 @@ async function handleInboundMessage(conn, msg) {
4780
4856
  const conversationKey = isGroup ? remoteJid : senderPhone;
4781
4857
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
4782
4858
  let resolvePending;
4783
- const sttPending = new Promise((resolve25) => {
4784
- resolvePending = resolve25;
4859
+ const sttPending = new Promise((resolve26) => {
4860
+ resolvePending = resolve26;
4785
4861
  });
4786
4862
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
4787
4863
  try {
@@ -4894,20 +4970,20 @@ async function probeApiKey() {
4894
4970
  return result.status;
4895
4971
  }
4896
4972
  function checkPort(port2, timeoutMs = 500) {
4897
- return new Promise((resolve25) => {
4973
+ return new Promise((resolve26) => {
4898
4974
  const socket = createConnection(port2, "127.0.0.1");
4899
4975
  socket.setTimeout(timeoutMs);
4900
4976
  socket.once("connect", () => {
4901
4977
  socket.destroy();
4902
- resolve25(true);
4978
+ resolve26(true);
4903
4979
  });
4904
4980
  socket.once("error", () => {
4905
4981
  socket.destroy();
4906
- resolve25(false);
4982
+ resolve26(false);
4907
4983
  });
4908
4984
  socket.once("timeout", () => {
4909
4985
  socket.destroy();
4910
- resolve25(false);
4986
+ resolve26(false);
4911
4987
  });
4912
4988
  });
4913
4989
  }
@@ -4917,7 +4993,7 @@ app.get("/", async (c) => {
4917
4993
  let pinConfigured = false;
4918
4994
  try {
4919
4995
  if (existsSync6(USERS_FILE)) {
4920
- const raw = readFileSync5(USERS_FILE, "utf-8").trim();
4996
+ const raw = readFileSync6(USERS_FILE, "utf-8").trim();
4921
4997
  if (raw) {
4922
4998
  const users = JSON.parse(raw);
4923
4999
  pinConfigured = Array.isArray(users) && users.length > 0;
@@ -5002,14 +5078,14 @@ app.get("/", async (c) => {
5002
5078
  var health_default = app;
5003
5079
 
5004
5080
  // server/routes/session.ts
5005
- import { resolve as resolve6 } from "path";
5081
+ import { resolve as resolve7 } from "path";
5006
5082
  import { existsSync as existsSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
5007
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5083
+ var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5008
5084
  function writeBrandingCache(accountId, agentSlug, branding) {
5009
5085
  try {
5010
- const cacheDir = resolve6(MAXY_DIR, "branding-cache", accountId);
5086
+ const cacheDir = resolve7(MAXY_DIR, "branding-cache", accountId);
5011
5087
  mkdirSync4(cacheDir, { recursive: true });
5012
- writeFileSync5(resolve6(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
5088
+ writeFileSync5(resolve7(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
5013
5089
  } catch (err) {
5014
5090
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
5015
5091
  }
@@ -5019,7 +5095,7 @@ function parseVisitorCookie(cookieHeader) {
5019
5095
  const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
5020
5096
  if (!match) return null;
5021
5097
  const value = decodeURIComponent(match[1]).trim();
5022
- return UUID_RE.test(value) ? value : null;
5098
+ return UUID_RE2.test(value) ? value : null;
5023
5099
  }
5024
5100
  function withVisitorCookie(response, visitorId) {
5025
5101
  if (!visitorId) return response;
@@ -5079,8 +5155,8 @@ app2.post("/", async (c) => {
5079
5155
  }
5080
5156
  let agentConfig = null;
5081
5157
  if (account) {
5082
- const agentDir = resolve6(account.accountDir, "agents", agentSlug);
5083
- const agentConfigPath = resolve6(agentDir, "config.json");
5158
+ const agentDir = resolve7(account.accountDir, "agents", agentSlug);
5159
+ const agentConfigPath = resolve7(agentDir, "config.json");
5084
5160
  if (!existsSync7(agentDir) || !existsSync7(agentConfigPath)) {
5085
5161
  return c.json({ error: "Agent not found" }, 404);
5086
5162
  }
@@ -5334,9 +5410,9 @@ ${raw}`;
5334
5410
  import { randomUUID as randomUUID4 } from "crypto";
5335
5411
  import { mkdir as mkdir2, readFile, stat as stat2, writeFile as writeFile2 } from "fs/promises";
5336
5412
  import { realpathSync } from "fs";
5337
- import { resolve as resolve7, extname, basename as basename3 } from "path";
5338
- var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve7(process.cwd(), "../platform");
5339
- var ATTACHMENTS_ROOT = resolve7(PLATFORM_ROOT2, "..", "data/uploads");
5413
+ import { resolve as resolve8, extname, basename as basename3 } from "path";
5414
+ var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve8(process.cwd(), "../platform");
5415
+ var ATTACHMENTS_ROOT = resolve8(PLATFORM_ROOT2, "..", "data/uploads");
5340
5416
  var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
5341
5417
  "image/jpeg",
5342
5418
  "image/png",
@@ -5363,11 +5439,11 @@ function assertSupportedMime(mimeType) {
5363
5439
  }
5364
5440
  async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
5365
5441
  const attachmentId = randomUUID4();
5366
- const dir = resolve7(ATTACHMENTS_ROOT, scope, attachmentId);
5442
+ const dir = resolve8(ATTACHMENTS_ROOT, scope, attachmentId);
5367
5443
  await mkdir2(dir, { recursive: true });
5368
5444
  const ext = extname(filename) || "";
5369
- const storagePath = resolve7(dir, `${attachmentId}${ext}`);
5370
- const metaPath = resolve7(dir, `${attachmentId}.meta.json`);
5445
+ const storagePath = resolve8(dir, `${attachmentId}${ext}`);
5446
+ const metaPath = resolve8(dir, `${attachmentId}.meta.json`);
5371
5447
  const meta = {
5372
5448
  attachmentId,
5373
5449
  scope,
@@ -6045,16 +6121,16 @@ var group_default = app4;
6045
6121
 
6046
6122
  // app/lib/access-gate.ts
6047
6123
  import neo4j from "neo4j-driver";
6048
- import { readFileSync as readFileSync6 } from "fs";
6049
- import { resolve as resolve8 } from "path";
6124
+ import { readFileSync as readFileSync7 } from "fs";
6125
+ import { resolve as resolve9 } from "path";
6050
6126
  import { randomUUID as randomUUID5, randomInt } from "crypto";
6051
- var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve8(process.cwd(), "..");
6127
+ var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve9(process.cwd(), "..");
6052
6128
  var driver = null;
6053
6129
  function readPassword() {
6054
6130
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
6055
- const passwordFile = resolve8(PLATFORM_ROOT3, "config/.neo4j-password");
6131
+ const passwordFile = resolve9(PLATFORM_ROOT3, "config/.neo4j-password");
6056
6132
  try {
6057
- return readFileSync6(passwordFile, "utf-8").trim();
6133
+ return readFileSync7(passwordFile, "utf-8").trim();
6058
6134
  } catch {
6059
6135
  throw new Error(
6060
6136
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -6365,19 +6441,19 @@ async function findActiveGrantByContact(contactValue, agentSlug, accountId) {
6365
6441
  }
6366
6442
 
6367
6443
  // app/lib/brevo-sms.ts
6368
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, chmodSync } from "fs";
6444
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, chmodSync } from "fs";
6369
6445
  import { dirname as dirname4 } from "path";
6370
- import { resolve as resolve9 } from "path";
6371
- var BREVO_API_KEY_FILE = resolve9(MAXY_DIR, ".brevo-api-key");
6446
+ import { resolve as resolve10 } from "path";
6447
+ var BREVO_API_KEY_FILE = resolve10(MAXY_DIR, ".brevo-api-key");
6372
6448
  var BREVO_API_URL = "https://api.brevo.com/v3/transactionalSMS/sms";
6373
6449
  var BREVO_TIMEOUT_MS = 1e4;
6374
6450
  var BREVO_SENDER = "Maxy";
6375
6451
  var platformRoot = process.env.MAXY_PLATFORM_ROOT;
6376
6452
  if (platformRoot) {
6377
6453
  try {
6378
- const brandPath = resolve9(platformRoot, "config", "brand.json");
6454
+ const brandPath = resolve10(platformRoot, "config", "brand.json");
6379
6455
  if (existsSync8(brandPath)) {
6380
- const brand = JSON.parse(readFileSync7(brandPath, "utf-8"));
6456
+ const brand = JSON.parse(readFileSync8(brandPath, "utf-8"));
6381
6457
  if (brand.productName) BREVO_SENDER = brand.productName;
6382
6458
  }
6383
6459
  } catch {
@@ -6385,7 +6461,7 @@ if (platformRoot) {
6385
6461
  }
6386
6462
  function readBrevoApiKey() {
6387
6463
  try {
6388
- const key = readFileSync7(BREVO_API_KEY_FILE, "utf-8").trim();
6464
+ const key = readFileSync8(BREVO_API_KEY_FILE, "utf-8").trim();
6389
6465
  if (!key) {
6390
6466
  throw new Error(`Brevo API key file is empty: ${BREVO_API_KEY_FILE}`);
6391
6467
  }
@@ -6816,7 +6892,7 @@ app5.post("/send-otp", async (c) => {
6816
6892
  var access_default = app5;
6817
6893
 
6818
6894
  // server/routes/telegram.ts
6819
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
6895
+ import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
6820
6896
  import { timingSafeEqual } from "crypto";
6821
6897
 
6822
6898
  // app/lib/telegram/access-control.ts
@@ -6854,7 +6930,7 @@ function getWebhookSecret(botType) {
6854
6930
  const filePath = botType === "admin" ? TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE : TELEGRAM_WEBHOOK_SECRET_FILE;
6855
6931
  try {
6856
6932
  if (!existsSync9(filePath)) return null;
6857
- const secret = readFileSync8(filePath, "utf-8").trim();
6933
+ const secret = readFileSync9(filePath, "utf-8").trim();
6858
6934
  return secret || null;
6859
6935
  } catch {
6860
6936
  return null;
@@ -7012,9 +7088,9 @@ app6.post("/webhook", async (c) => {
7012
7088
  var telegram_default = app6;
7013
7089
 
7014
7090
  // server/routes/whatsapp.ts
7015
- import { join as join6, resolve as resolve10, basename as basename4 } from "path";
7091
+ import { join as join6, resolve as resolve11, basename as basename4 } from "path";
7016
7092
  import { readFile as readFile2, stat as stat3 } from "fs/promises";
7017
- import { realpathSync as realpathSync2, readdirSync as readdirSync2, readFileSync as readFileSync9, existsSync as existsSync10 } from "fs";
7093
+ import { realpathSync as realpathSync2, readdirSync as readdirSync3, readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
7018
7094
 
7019
7095
  // app/lib/whatsapp/login.ts
7020
7096
  import { randomUUID as randomUUID6 } from "crypto";
@@ -7120,8 +7196,8 @@ async function startLogin(opts) {
7120
7196
  resetActiveLogin(accountId);
7121
7197
  let resolveQr = null;
7122
7198
  let rejectQr = null;
7123
- const qrPromise = new Promise((resolve25, reject) => {
7124
- resolveQr = resolve25;
7199
+ const qrPromise = new Promise((resolve26, reject) => {
7200
+ resolveQr = resolve26;
7125
7201
  rejectQr = reject;
7126
7202
  });
7127
7203
  const qrTimer = setTimeout(
@@ -7515,17 +7591,17 @@ app7.post("/config", async (c) => {
7515
7591
  return c.json(result, result.ok ? 200 : 400);
7516
7592
  }
7517
7593
  case "list-public-agents": {
7518
- const agentsDir = resolve10(account.accountDir, "agents");
7594
+ const agentsDir = resolve11(account.accountDir, "agents");
7519
7595
  const agents = [];
7520
7596
  if (existsSync10(agentsDir)) {
7521
7597
  try {
7522
- const entries = readdirSync2(agentsDir, { withFileTypes: true });
7598
+ const entries = readdirSync3(agentsDir, { withFileTypes: true });
7523
7599
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
7524
7600
  if (!entry.isDirectory() || entry.name === "admin") continue;
7525
- const configPath2 = resolve10(agentsDir, entry.name, "config.json");
7601
+ const configPath2 = resolve11(agentsDir, entry.name, "config.json");
7526
7602
  if (!existsSync10(configPath2)) continue;
7527
7603
  try {
7528
- const config = JSON.parse(readFileSync9(configPath2, "utf-8"));
7604
+ const config = JSON.parse(readFileSync10(configPath2, "utf-8"));
7529
7605
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
7530
7606
  } catch {
7531
7607
  console.error(`${TAG18} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
@@ -7600,7 +7676,7 @@ app7.post("/send-document", async (c) => {
7600
7676
  if (!maxyAccountId || !PLATFORM_ROOT4) {
7601
7677
  return c.json({ error: "Cannot validate file path: missing account or platform context" }, 400);
7602
7678
  }
7603
- const accountDir = resolve10(PLATFORM_ROOT4, "..", "data/accounts", maxyAccountId);
7679
+ const accountDir = resolve11(PLATFORM_ROOT4, "..", "data/accounts", maxyAccountId);
7604
7680
  let resolvedPath;
7605
7681
  try {
7606
7682
  resolvedPath = realpathSync2(filePath);
@@ -7737,8 +7813,8 @@ var whatsapp_default = app7;
7737
7813
 
7738
7814
  // server/routes/onboarding.ts
7739
7815
  import { spawn, execFileSync } from "child_process";
7740
- import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync10, unlinkSync } from "fs";
7741
- import { resolve as resolve11, dirname as dirname5 } from "path";
7816
+ import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync } from "fs";
7817
+ import { resolve as resolve12, dirname as dirname5 } from "path";
7742
7818
  import { createHash, randomUUID as randomUUID7 } from "crypto";
7743
7819
  var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT || "";
7744
7820
  function hashPin(pin) {
@@ -7746,7 +7822,7 @@ function hashPin(pin) {
7746
7822
  }
7747
7823
  function readUsersFile() {
7748
7824
  if (!existsSync11(USERS_FILE)) return null;
7749
- const raw = readFileSync10(USERS_FILE, "utf-8").trim();
7825
+ const raw = readFileSync11(USERS_FILE, "utf-8").trim();
7750
7826
  if (!raw) return [];
7751
7827
  return JSON.parse(raw);
7752
7828
  }
@@ -7867,7 +7943,7 @@ app8.post("/set-pin", async (c) => {
7867
7943
  console.log(`[set-pin] wrote users.json: userId=${userId.slice(0, 8)}\u2026 hash=${hash.slice(0, 8)}\u2026`);
7868
7944
  if (account) {
7869
7945
  try {
7870
- const config = JSON.parse(readFileSync10(`${account.accountDir}/account.json`, "utf-8"));
7946
+ const config = JSON.parse(readFileSync11(`${account.accountDir}/account.json`, "utf-8"));
7871
7947
  if (!config.admins) config.admins = [];
7872
7948
  if (!config.admins.some((a) => a.userId === userId)) {
7873
7949
  config.admins.push({ userId, role: "owner" });
@@ -7943,16 +8019,16 @@ app8.post("/skip", async (c) => {
7943
8019
  }
7944
8020
  const { accountId, accountDir } = account;
7945
8021
  let agentName = "Maxy";
7946
- const brandPath = PLATFORM_ROOT5 ? resolve11(PLATFORM_ROOT5, "config", "brand.json") : "";
8022
+ const brandPath = PLATFORM_ROOT5 ? resolve12(PLATFORM_ROOT5, "config", "brand.json") : "";
7947
8023
  if (brandPath && existsSync11(brandPath)) {
7948
8024
  try {
7949
- const brand = JSON.parse(readFileSync10(brandPath, "utf-8"));
8025
+ const brand = JSON.parse(readFileSync11(brandPath, "utf-8"));
7950
8026
  if (brand.productName) agentName = brand.productName;
7951
8027
  } catch (err) {
7952
8028
  console.error(`[onboarding-skip] brand.json read failed: ${err instanceof Error ? err.message : String(err)}`);
7953
8029
  }
7954
8030
  }
7955
- const soulPath = resolve11(accountDir, "agents", "admin", "SOUL.md");
8031
+ const soulPath = resolve12(accountDir, "agents", "admin", "SOUL.md");
7956
8032
  try {
7957
8033
  mkdirSync6(dirname5(soulPath), { recursive: true });
7958
8034
  writeFileSync7(soulPath, `You are ${agentName}, an AI operations manager.
@@ -8115,9 +8191,16 @@ app9.post("/", async (c) => {
8115
8191
  const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
8116
8192
  return `${k}=${safe}`;
8117
8193
  }).join(" ");
8118
- console.log(
8119
- `[client-event] ts=${ts} ip=${ip} source=${source} version=${version || "unknown"}${extra ? " " + extra : ""}`
8120
- );
8194
+ const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["admin-chat-relay-poll"]);
8195
+ if (TAGGED_PREFIX_SOURCES.has(source)) {
8196
+ console.log(
8197
+ `[${source}] ts=${ts} ip=${ip} version=${version || "unknown"}${extra ? " " + extra : ""}`
8198
+ );
8199
+ } else {
8200
+ console.log(
8201
+ `[client-event] ts=${ts} ip=${ip} source=${source} version=${version || "unknown"}${extra ? " " + extra : ""}`
8202
+ );
8203
+ }
8121
8204
  } else {
8122
8205
  console.error(
8123
8206
  `[client-error] ts=${ts} ip=${ip} kind=${kind} url=${JSON.stringify(url)} version=${version || "unknown"} ua=${JSON.stringify(ua)} msg=${JSON.stringify(msg)} stack-head=${JSON.stringify(head)} file-line-col=${JSON.stringify(fileLineCol)}`
@@ -8151,7 +8234,7 @@ app9.post("/", async (c) => {
8151
8234
  var client_error_default = app9;
8152
8235
 
8153
8236
  // server/routes/admin/session.ts
8154
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync13 } from "fs";
8237
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, existsSync as existsSync13 } from "fs";
8155
8238
  import { createHash as createHash2 } from "crypto";
8156
8239
  var deprecationLogged = /* @__PURE__ */ new Set();
8157
8240
  function hashPin2(pin) {
@@ -8159,7 +8242,7 @@ function hashPin2(pin) {
8159
8242
  }
8160
8243
  function readUsersFile2() {
8161
8244
  if (!existsSync13(USERS_FILE)) return null;
8162
- const raw = readFileSync11(USERS_FILE, "utf-8").trim();
8245
+ const raw = readFileSync12(USERS_FILE, "utf-8").trim();
8163
8246
  if (!raw) return [];
8164
8247
  return JSON.parse(raw);
8165
8248
  }
@@ -8333,7 +8416,7 @@ app10.post("/", async (c) => {
8333
8416
  var session_default2 = app10;
8334
8417
 
8335
8418
  // server/routes/admin/chat.ts
8336
- import { resolve as resolve12 } from "path";
8419
+ import { resolve as resolve13 } from "path";
8337
8420
  import { appendFileSync as appendFileSync4 } from "fs";
8338
8421
 
8339
8422
  // app/lib/script-stream-tailer.ts
@@ -8788,7 +8871,7 @@ app11.post("/", requireAdminSession, async (c) => {
8788
8871
  function resolveTeeStreamLogPath() {
8789
8872
  const liveConvId = getConversationIdForSession(session_key);
8790
8873
  const key = liveConvId ?? preflushStreamLogKey(session_key);
8791
- return resolve12(account.accountDir, "logs", `claude-agent-stream-${key}.log`);
8874
+ return resolve13(account.accountDir, "logs", `claude-agent-stream-${key}.log`);
8792
8875
  }
8793
8876
  try {
8794
8877
  appendFileSync4(resolveTeeStreamLogPath(), `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task606-tee-path-resolve] sessionKey=${session_key.slice(0, 12)}\u2026
@@ -8890,7 +8973,7 @@ app11.post("/", requireAdminSession, async (c) => {
8890
8973
  try {
8891
8974
  registerAdminSSE(sseEntry);
8892
8975
  if (sseConvId) {
8893
- const streamLogPath = resolve12(account.accountDir, "logs", `claude-agent-stream-${sseConvId}.log`);
8976
+ const streamLogPath = resolve13(account.accountDir, "logs", `claude-agent-stream-${sseConvId}.log`);
8894
8977
  tailer = startScriptStreamTailer({
8895
8978
  path: streamLogPath,
8896
8979
  onEvent: (event) => {
@@ -9019,8 +9102,8 @@ app12.post("/", requireAdminSession, async (c) => {
9019
9102
  var compact_default = app12;
9020
9103
 
9021
9104
  // server/routes/admin/logs.ts
9022
- import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync12, statSync as statSync7 } from "fs";
9023
- import { resolve as resolve13, basename as basename5 } from "path";
9105
+ import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync7 } from "fs";
9106
+ import { resolve as resolve14, basename as basename5 } from "path";
9024
9107
 
9025
9108
  // app/lib/logs-read-resolve.ts
9026
9109
  import { existsSync as existsSync14 } from "fs";
@@ -9064,7 +9147,7 @@ app13.get("/", async (c) => {
9064
9147
  const sessionKeyParam = c.req.query("sessionKey");
9065
9148
  const download = c.req.query("download") === "1";
9066
9149
  const account = resolveAccount();
9067
- const accountLogDir2 = account ? resolve13(account.accountDir, "logs") : null;
9150
+ const accountLogDir2 = account ? resolve14(account.accountDir, "logs") : null;
9068
9151
  const logDirs = [];
9069
9152
  if (accountLogDir2) logDirs.push(accountLogDir2);
9070
9153
  logDirs.push(LOG_DIR);
@@ -9072,10 +9155,10 @@ app13.get("/", async (c) => {
9072
9155
  const safe = basename5(fileParam);
9073
9156
  const searched = [];
9074
9157
  for (const dir of logDirs) {
9075
- const filePath = resolve13(dir, safe);
9158
+ const filePath = resolve14(dir, safe);
9076
9159
  searched.push(filePath);
9077
9160
  try {
9078
- const buffer = readFileSync12(filePath);
9161
+ const buffer = readFileSync13(filePath);
9079
9162
  const onDiskBytes = statSync7(filePath).size;
9080
9163
  const headers = {
9081
9164
  "Content-Type": "text/plain; charset=utf-8",
@@ -9150,7 +9233,7 @@ app13.get("/", async (c) => {
9150
9233
  try {
9151
9234
  const filename = basename5(hit.path);
9152
9235
  if (stalePreflushCount > 0 && !download) {
9153
- const content = readFileSync12(hit.path, "utf-8");
9236
+ const content = readFileSync13(hit.path, "utf-8");
9154
9237
  return c.json({
9155
9238
  log: content,
9156
9239
  filename,
@@ -9158,7 +9241,7 @@ app13.get("/", async (c) => {
9158
9241
  warnings: stalePreflushPaths.map((path2) => ({ kind: "stale-preflush", path: path2 }))
9159
9242
  });
9160
9243
  }
9161
- const buffer = readFileSync12(hit.path);
9244
+ const buffer = readFileSync13(hit.path);
9162
9245
  const onDiskBytes = statSync7(hit.path).size;
9163
9246
  const headers = {
9164
9247
  "Content-Type": "text/plain; charset=utf-8",
@@ -9195,16 +9278,16 @@ app13.get("/", async (c) => {
9195
9278
  if (!existsSync15(dir)) continue;
9196
9279
  let files;
9197
9280
  try {
9198
- files = readdirSync3(dir).filter((f) => f.endsWith(".log"));
9281
+ files = readdirSync4(dir).filter((f) => f.endsWith(".log"));
9199
9282
  } catch (err) {
9200
9283
  const reason = err instanceof Error ? err.message : String(err);
9201
9284
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
9202
9285
  continue;
9203
9286
  }
9204
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve13(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9287
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve14(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9205
9288
  seen.add(name);
9206
9289
  try {
9207
- const content = readFileSync12(resolve13(dir, name));
9290
+ const content = readFileSync13(resolve14(dir, name));
9208
9291
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
9209
9292
  logs[name] = tail.trim() || "(empty)";
9210
9293
  } catch (err) {
@@ -9244,7 +9327,7 @@ var claude_info_default = app14;
9244
9327
  // server/routes/admin/attachment.ts
9245
9328
  import { readFile as readFile3, readdir } from "fs/promises";
9246
9329
  import { existsSync as existsSync16 } from "fs";
9247
- import { resolve as resolve14 } from "path";
9330
+ import { resolve as resolve15 } from "path";
9248
9331
  var app15 = new Hono();
9249
9332
  app15.get("/:attachmentId", requireAdminSession, async (c) => {
9250
9333
  const attachmentId = c.req.param("attachmentId");
@@ -9256,11 +9339,11 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
9256
9339
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
9257
9340
  return new Response("Not found", { status: 404 });
9258
9341
  }
9259
- const dir = resolve14(ATTACHMENTS_ROOT, accountId, attachmentId);
9342
+ const dir = resolve15(ATTACHMENTS_ROOT, accountId, attachmentId);
9260
9343
  if (!existsSync16(dir)) {
9261
9344
  return new Response("Not found", { status: 404 });
9262
9345
  }
9263
- const metaPath = resolve14(dir, `${attachmentId}.meta.json`);
9346
+ const metaPath = resolve15(dir, `${attachmentId}.meta.json`);
9264
9347
  if (!existsSync16(metaPath)) {
9265
9348
  return new Response("Not found", { status: 404 });
9266
9349
  }
@@ -9275,7 +9358,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
9275
9358
  if (!dataFile) {
9276
9359
  return new Response("Not found", { status: 404 });
9277
9360
  }
9278
- const filePath = resolve14(dir, dataFile);
9361
+ const filePath = resolve15(dir, dataFile);
9279
9362
  const buffer = await readFile3(filePath);
9280
9363
  return new Response(new Uint8Array(buffer), {
9281
9364
  headers: {
@@ -9288,24 +9371,24 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
9288
9371
  var attachment_default = app15;
9289
9372
 
9290
9373
  // server/routes/admin/agents.ts
9291
- import { resolve as resolve15 } from "path";
9292
- import { readdirSync as readdirSync4, readFileSync as readFileSync13, existsSync as existsSync17, rmSync } from "fs";
9374
+ import { resolve as resolve16 } from "path";
9375
+ import { readdirSync as readdirSync5, readFileSync as readFileSync14, existsSync as existsSync17, rmSync } from "fs";
9293
9376
  var app16 = new Hono();
9294
9377
  app16.get("/", (c) => {
9295
9378
  const account = resolveAccount();
9296
9379
  if (!account) return c.json({ agents: [] });
9297
- const agentsDir = resolve15(account.accountDir, "agents");
9380
+ const agentsDir = resolve16(account.accountDir, "agents");
9298
9381
  if (!existsSync17(agentsDir)) return c.json({ agents: [] });
9299
9382
  const agents = [];
9300
9383
  try {
9301
- const entries = readdirSync4(agentsDir, { withFileTypes: true });
9384
+ const entries = readdirSync5(agentsDir, { withFileTypes: true });
9302
9385
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
9303
9386
  if (!entry.isDirectory()) continue;
9304
9387
  if (entry.name === "admin") continue;
9305
- const configPath2 = resolve15(agentsDir, entry.name, "config.json");
9388
+ const configPath2 = resolve16(agentsDir, entry.name, "config.json");
9306
9389
  if (!existsSync17(configPath2)) continue;
9307
9390
  try {
9308
- const config = JSON.parse(readFileSync13(configPath2, "utf-8"));
9391
+ const config = JSON.parse(readFileSync14(configPath2, "utf-8"));
9309
9392
  agents.push({
9310
9393
  slug: entry.name,
9311
9394
  displayName: config.displayName ?? entry.name,
@@ -9331,7 +9414,7 @@ app16.delete("/:slug", async (c) => {
9331
9414
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9332
9415
  return c.json({ error: "Invalid agent slug" }, 400);
9333
9416
  }
9334
- const agentDir = resolve15(account.accountDir, "agents", slug);
9417
+ const agentDir = resolve16(account.accountDir, "agents", slug);
9335
9418
  if (!existsSync17(agentDir)) {
9336
9419
  return c.json({ error: "Agent not found" }, 404);
9337
9420
  }
@@ -9361,7 +9444,7 @@ app16.post("/:slug/project", async (c) => {
9361
9444
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9362
9445
  return c.json({ error: "Invalid agent slug" }, 400);
9363
9446
  }
9364
- const agentDir = resolve15(account.accountDir, "agents", slug);
9447
+ const agentDir = resolve16(account.accountDir, "agents", slug);
9365
9448
  if (!existsSync17(agentDir)) {
9366
9449
  return c.json({ error: "Agent not found on disk" }, 404);
9367
9450
  }
@@ -9918,8 +10001,8 @@ var events_default = app20;
9918
10001
 
9919
10002
  // server/routes/admin/cloudflare.ts
9920
10003
  import { homedir } from "os";
9921
- import { resolve as resolve17 } from "path";
9922
- import { readFileSync as readFileSync16 } from "fs";
10004
+ import { resolve as resolve18 } from "path";
10005
+ import { readFileSync as readFileSync17 } from "fs";
9923
10006
 
9924
10007
  // app/lib/dns-label.ts
9925
10008
  var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
@@ -9935,14 +10018,14 @@ function isValidDomain(value) {
9935
10018
  }
9936
10019
 
9937
10020
  // app/lib/alias-domains.ts
9938
- import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "fs";
10021
+ import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
9939
10022
  import { dirname as dirname7 } from "path";
9940
- import { resolve as resolve16 } from "path";
9941
- var ALIAS_DOMAINS_PATH = resolve16(MAXY_DIR, "alias-domains.json");
10023
+ import { resolve as resolve17 } from "path";
10024
+ var ALIAS_DOMAINS_PATH = resolve17(MAXY_DIR, "alias-domains.json");
9942
10025
  function readExisting() {
9943
10026
  if (!existsSync19(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
9944
10027
  try {
9945
- const parsed = JSON.parse(readFileSync14(ALIAS_DOMAINS_PATH, "utf-8"));
10028
+ const parsed = JSON.parse(readFileSync15(ALIAS_DOMAINS_PATH, "utf-8"));
9946
10029
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
9947
10030
  return new Set(parsed.filter((h) => typeof h === "string"));
9948
10031
  } catch {
@@ -9961,8 +10044,8 @@ function addAliasDomain(hostname2) {
9961
10044
  import {
9962
10045
  existsSync as existsSync20,
9963
10046
  mkdirSync as mkdirSync9,
9964
- readdirSync as readdirSync5,
9965
- readFileSync as readFileSync15,
10047
+ readdirSync as readdirSync6,
10048
+ readFileSync as readFileSync16,
9966
10049
  unlinkSync as unlinkSync2,
9967
10050
  writeFileSync as writeFileSync10
9968
10051
  } from "fs";
@@ -10008,7 +10091,7 @@ function consumeActionCompletionRelays(accountDir) {
10008
10091
  if (!existsSync20(dir)) return [];
10009
10092
  let entries;
10010
10093
  try {
10011
- entries = readdirSync5(dir);
10094
+ entries = readdirSync6(dir);
10012
10095
  } catch (e) {
10013
10096
  console.error(
10014
10097
  `${TAG19} phase=readdir-failed dir=${dir} error=${e instanceof Error ? e.message : String(e)}`
@@ -10021,7 +10104,7 @@ function consumeActionCompletionRelays(accountDir) {
10021
10104
  const filePath = join9(dir, name);
10022
10105
  let raw;
10023
10106
  try {
10024
- raw = readFileSync15(filePath, "utf-8");
10107
+ raw = readFileSync16(filePath, "utf-8");
10025
10108
  } catch (e) {
10026
10109
  console.error(
10027
10110
  `${TAG19} phase=read-failed file=${name} error=${e instanceof Error ? e.message : String(e)}`
@@ -10078,10 +10161,10 @@ import { existsSync as existsSyncFs, readFileSync as readFileSyncFs } from "fs";
10078
10161
  var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
10079
10162
  var DOMAINS_TIMEOUT_MS = 40 * 1e3;
10080
10163
  function loadBrandInfo() {
10081
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
10082
- const brandPath = resolve17(platformRoot2, "config", "brand.json");
10164
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
10165
+ const brandPath = resolve18(platformRoot2, "config", "brand.json");
10083
10166
  try {
10084
- const parsed = JSON.parse(readFileSync16(brandPath, "utf-8"));
10167
+ const parsed = JSON.parse(readFileSync17(brandPath, "utf-8"));
10085
10168
  const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
10086
10169
  const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
10087
10170
  return { hostname: hostname2, configDir: configDir2 };
@@ -10184,7 +10267,7 @@ app21.get("/domains", requireAdminSession, async (c) => {
10184
10267
  streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
10185
10268
  log(`phase=stream-log-resolved path=${streamLogPath}`);
10186
10269
  const brand = loadBrandInfo();
10187
- const scriptPath = resolve17(homedir(), "list-cf-domains.sh");
10270
+ const scriptPath = resolve18(homedir(), "list-cf-domains.sh");
10188
10271
  const result = await runFormSpawn({
10189
10272
  scriptPath,
10190
10273
  args: [brand.hostname],
@@ -10449,17 +10532,17 @@ var cloudflare_default = app21;
10449
10532
  import { createReadStream as createReadStream3 } from "fs";
10450
10533
  import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
10451
10534
  import { realpathSync as realpathSync4 } from "fs";
10452
- import { basename as basename6, dirname as dirname8, join as join10, resolve as resolve19, sep as sep2 } from "path";
10535
+ import { basename as basename6, dirname as dirname8, join as join10, resolve as resolve20, sep as sep2 } from "path";
10453
10536
  import { Readable as Readable2 } from "stream";
10454
10537
 
10455
10538
  // app/lib/data-path.ts
10456
10539
  import { realpathSync as realpathSync3 } from "fs";
10457
- import { resolve as resolve18, normalize, sep, relative } from "path";
10458
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "../platform");
10459
- var DATA_ROOT = resolve18(PLATFORM_ROOT6, "..", "data");
10540
+ import { resolve as resolve19, normalize, sep, relative } from "path";
10541
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "../platform");
10542
+ var DATA_ROOT = resolve19(PLATFORM_ROOT6, "..", "data");
10460
10543
  function resolveDataPath(raw) {
10461
10544
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
10462
- const absolute = resolve18(DATA_ROOT, cleaned);
10545
+ const absolute = resolve19(DATA_ROOT, cleaned);
10463
10546
  let dataRootReal;
10464
10547
  try {
10465
10548
  dataRootReal = realpathSync3(DATA_ROOT);
@@ -10724,7 +10807,7 @@ async function restoreNode(params) {
10724
10807
  }
10725
10808
 
10726
10809
  // app/lib/file-delete-cascade.ts
10727
- var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10810
+ var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10728
10811
  function parseAttachmentPath(relPath2) {
10729
10812
  const segments = relPath2.split("/").filter(Boolean);
10730
10813
  if (segments.length !== 4) return null;
@@ -10732,7 +10815,7 @@ function parseAttachmentPath(relPath2) {
10732
10815
  const accountId = segments[1];
10733
10816
  const attachmentId = segments[2];
10734
10817
  const filename = segments[3];
10735
- if (!UUID_RE2.test(accountId) || !UUID_RE2.test(attachmentId)) return null;
10818
+ if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
10736
10819
  const dot = filename.lastIndexOf(".");
10737
10820
  if (dot === -1) return null;
10738
10821
  const stem = filename.slice(0, dot);
@@ -10804,7 +10887,7 @@ async function cascadeDeleteDocument(params) {
10804
10887
  }
10805
10888
 
10806
10889
  // server/routes/admin/files.ts
10807
- var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10890
+ var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10808
10891
  async function readMeta(absDir, baseName) {
10809
10892
  try {
10810
10893
  const raw = await readFile4(join10(absDir, `${baseName}.meta.json`), "utf8");
@@ -10818,7 +10901,7 @@ async function readMeta(absDir, baseName) {
10818
10901
  }
10819
10902
  async function readAccountNames() {
10820
10903
  const map = /* @__PURE__ */ new Map();
10821
- const accountsDir = resolve19(DATA_ROOT, "accounts");
10904
+ const accountsDir = resolve20(DATA_ROOT, "accounts");
10822
10905
  let names;
10823
10906
  try {
10824
10907
  names = await readdir2(accountsDir);
@@ -10826,8 +10909,8 @@ async function readAccountNames() {
10826
10909
  return map;
10827
10910
  }
10828
10911
  for (const name of names) {
10829
- if (!UUID_RE3.test(name)) continue;
10830
- const configPath2 = resolve19(accountsDir, name, "account.json");
10912
+ if (!UUID_RE4.test(name)) continue;
10913
+ const configPath2 = resolve20(accountsDir, name, "account.json");
10831
10914
  try {
10832
10915
  const raw = await readFile4(configPath2, "utf8");
10833
10916
  const parsed = JSON.parse(raw);
@@ -10844,7 +10927,7 @@ async function readAccountNames() {
10844
10927
  return map;
10845
10928
  }
10846
10929
  async function enrich(absolute, entry, accountNames) {
10847
- if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
10930
+ if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
10848
10931
  const meta = await readMeta(join10(absolute, entry.name), entry.name);
10849
10932
  if (meta?.filename) {
10850
10933
  entry.displayName = meta.filename;
@@ -10860,7 +10943,7 @@ async function enrich(absolute, entry, accountNames) {
10860
10943
  if (entry.kind === "file") {
10861
10944
  const dot = entry.name.lastIndexOf(".");
10862
10945
  const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
10863
- if (UUID_RE3.test(base)) {
10946
+ if (UUID_RE4.test(base)) {
10864
10947
  const meta = await readMeta(absolute, base);
10865
10948
  if (meta?.filename) {
10866
10949
  entry.displayName = meta.filename;
@@ -10872,7 +10955,7 @@ async function enrich(absolute, entry, accountNames) {
10872
10955
  function buildDisplayPath(relPath2, accountNames) {
10873
10956
  if (relPath2 === "." || relPath2 === "") return [];
10874
10957
  return relPath2.split("/").filter(Boolean).map((seg) => {
10875
- const dn = UUID_RE3.test(seg) ? accountNames.get(seg) : void 0;
10958
+ const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
10876
10959
  return dn ? { name: seg, displayName: dn } : { name: seg };
10877
10960
  });
10878
10961
  }
@@ -10900,7 +10983,7 @@ app22.get("/", requireAdminSession, async (c) => {
10900
10983
  const names = await readdir2(absolute);
10901
10984
  const entries = [];
10902
10985
  for (const name of names) {
10903
- if (UUID_RE3.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
10986
+ if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
10904
10987
  continue;
10905
10988
  }
10906
10989
  try {
@@ -11018,8 +11101,8 @@ app22.post("/upload", requireAdminSession, async (c) => {
11018
11101
  }
11019
11102
  const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
11020
11103
  const finalName = `${Date.now()}-${safeName}`;
11021
- const destDir = resolve19(DATA_ROOT, "uploads", accountId);
11022
- const destPath = resolve19(destDir, finalName);
11104
+ const destDir = resolve20(DATA_ROOT, "uploads", accountId);
11105
+ const destPath = resolve20(destDir, finalName);
11023
11106
  try {
11024
11107
  await mkdir3(destDir, { recursive: true });
11025
11108
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11077,7 +11160,7 @@ app22.delete("/", requireAdminSession, async (c) => {
11077
11160
  }
11078
11161
  const dot = base.lastIndexOf(".");
11079
11162
  const stem = dot === -1 ? base : base.slice(0, dot);
11080
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join10(dirname8(absolute), `${stem}.meta.json`) : null;
11163
+ const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join10(dirname8(absolute), `${stem}.meta.json`) : null;
11081
11164
  await unlink2(absolute);
11082
11165
  if (sidecarPath) {
11083
11166
  try {
@@ -12534,7 +12617,7 @@ var adherence_default = app30;
12534
12617
  // server/routes/admin/sidebar-artefacts.ts
12535
12618
  import neo4j3 from "neo4j-driver";
12536
12619
  import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
12537
- import { resolve as resolve20, relative as relative2, isAbsolute } from "path";
12620
+ import { resolve as resolve21, relative as relative2, isAbsolute } from "path";
12538
12621
  import { existsSync as existsSync21 } from "fs";
12539
12622
  var LIMIT = 50;
12540
12623
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
@@ -12551,7 +12634,7 @@ app31.get("/", requireAdminSession, async (c) => {
12551
12634
  if (docs === null) {
12552
12635
  return c.json({ error: "Failed to load artefacts" }, 500);
12553
12636
  }
12554
- const accountDir = resolve20(ACCOUNTS_DIR, accountId);
12637
+ const accountDir = resolve21(ACCOUNTS_DIR, accountId);
12555
12638
  const agents = await fetchAgentTemplateRows(accountDir);
12556
12639
  const artefacts = [...docs, ...agents].sort(
12557
12640
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -12614,8 +12697,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
12614
12697
  logSkip(displayName, "non-text-mime", mimeType);
12615
12698
  return { content: "", skipReason: "non-text-mime" };
12616
12699
  }
12617
- const accountDir = resolve20(ATTACHMENTS_ROOT, accountId);
12618
- const dir = resolve20(accountDir, attachmentId);
12700
+ const accountDir = resolve21(ATTACHMENTS_ROOT, accountId);
12701
+ const dir = resolve21(accountDir, attachmentId);
12619
12702
  try {
12620
12703
  validateFilePathInAccount(dir, accountDir);
12621
12704
  } catch {
@@ -12629,7 +12712,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
12629
12712
  logSkip(displayName, "missing-on-disk", mimeType);
12630
12713
  return { content: "", skipReason: "missing-on-disk" };
12631
12714
  }
12632
- return { content: await readFile5(resolve20(dir, dataFile), "utf-8"), skipReason: null };
12715
+ return { content: await readFile5(resolve21(dir, dataFile), "utf-8"), skipReason: null };
12633
12716
  } catch (err) {
12634
12717
  const message = err instanceof Error ? err.message : String(err);
12635
12718
  console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
@@ -12645,8 +12728,8 @@ function logSkip(name, reason, mimeType) {
12645
12728
  async function fetchAgentTemplateRows(accountDir) {
12646
12729
  const rows = [];
12647
12730
  for (const filename of ADMIN_AGENT_FILES) {
12648
- const overridePath = resolve20(accountDir, "agents", "admin", filename);
12649
- const bundledPath = resolve20(PLATFORM_ROOT, "templates", "agents", "admin", filename);
12731
+ const overridePath = resolve21(accountDir, "agents", "admin", filename);
12732
+ const bundledPath = resolve21(PLATFORM_ROOT, "templates", "agents", "admin", filename);
12650
12733
  const labelStem = filename.replace(/\.md$/, "");
12651
12734
  const row = await readAgentTemplateRow({
12652
12735
  id: `agent-template:admin:${filename}`,
@@ -12660,12 +12743,12 @@ async function fetchAgentTemplateRows(accountDir) {
12660
12743
  });
12661
12744
  if (row) rows.push(row);
12662
12745
  }
12663
- const overrideDir = resolve20(accountDir, "specialists", "agents");
12664
- const bundledDir = resolve20(PLATFORM_ROOT, "templates", "specialists", "agents");
12746
+ const overrideDir = resolve21(accountDir, "specialists", "agents");
12747
+ const bundledDir = resolve21(PLATFORM_ROOT, "templates", "specialists", "agents");
12665
12748
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
12666
12749
  for (const filename of specialistNames) {
12667
- const overridePath = resolve20(overrideDir, filename);
12668
- const bundledPath = resolve20(bundledDir, filename);
12750
+ const overridePath = resolve21(overrideDir, filename);
12751
+ const bundledPath = resolve21(bundledDir, filename);
12669
12752
  const row = await readAgentTemplateRow({
12670
12753
  id: `agent-template:specialist:${filename}`,
12671
12754
  displayName: filename.replace(/\.md$/, ""),
@@ -12750,10 +12833,10 @@ var sidebar_artefacts_default = app31;
12750
12833
 
12751
12834
  // server/routes/admin/sidebar-artefact-save.ts
12752
12835
  import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
12753
- import { resolve as resolve21 } from "path";
12836
+ import { resolve as resolve22 } from "path";
12754
12837
  import { existsSync as existsSync22 } from "fs";
12755
12838
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
12756
- var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12839
+ var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12757
12840
  var app32 = new Hono();
12758
12841
  app32.post("/", requireAdminSession, async (c) => {
12759
12842
  const sessionKey = c.var.sessionKey;
@@ -12763,7 +12846,7 @@ app32.post("/", requireAdminSession, async (c) => {
12763
12846
  if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
12764
12847
  return c.json({ error: "id and content required" }, 400);
12765
12848
  }
12766
- const accountDir = resolve21(ACCOUNTS_DIR, accountId);
12849
+ const accountDir = resolve22(ACCOUNTS_DIR, accountId);
12767
12850
  const resolved = await resolveSavePath(body.id, accountId, accountDir);
12768
12851
  if (resolved.kind === "reject") {
12769
12852
  console.error(
@@ -12804,22 +12887,22 @@ async function resolveSavePath(id, accountId, accountDir) {
12804
12887
  if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
12805
12888
  return { kind: "reject", status: 400, reason: "invalid-id" };
12806
12889
  }
12807
- const parent = resolve21(accountDir, "agents", "admin");
12890
+ const parent = resolve22(accountDir, "agents", "admin");
12808
12891
  await mkdir4(parent, { recursive: true });
12809
12892
  try {
12810
12893
  validateFilePathInAccount(parent, accountDir);
12811
12894
  } catch {
12812
12895
  return { kind: "reject", status: 400, reason: "containment-rejected" };
12813
12896
  }
12814
- return { kind: "admin-template", path: resolve21(parent, filename) };
12897
+ return { kind: "admin-template", path: resolve22(parent, filename) };
12815
12898
  }
12816
- if (UUID_RE4.test(id)) {
12817
- const dir = resolve21(ATTACHMENTS_ROOT, accountId, id);
12899
+ if (UUID_RE5.test(id)) {
12900
+ const dir = resolve22(ATTACHMENTS_ROOT, accountId, id);
12818
12901
  if (!existsSync22(dir)) {
12819
12902
  return { kind: "reject", status: 400, reason: "not-found" };
12820
12903
  }
12821
12904
  try {
12822
- validateFilePathInAccount(dir, resolve21(ATTACHMENTS_ROOT, accountId));
12905
+ validateFilePathInAccount(dir, resolve22(ATTACHMENTS_ROOT, accountId));
12823
12906
  } catch {
12824
12907
  return { kind: "reject", status: 400, reason: "containment-rejected" };
12825
12908
  }
@@ -12828,7 +12911,7 @@ async function resolveSavePath(id, accountId, accountDir) {
12828
12911
  if (!dataFile) {
12829
12912
  return { kind: "reject", status: 400, reason: "not-found" };
12830
12913
  }
12831
- return { kind: "knowledge-doc", path: resolve21(dir, dataFile) };
12914
+ return { kind: "knowledge-doc", path: resolve22(dir, dataFile) };
12832
12915
  }
12833
12916
  return { kind: "reject", status: 400, reason: "invalid-id" };
12834
12917
  }
@@ -12840,26 +12923,26 @@ var sidebar_artefact_save_default = app32;
12840
12923
  // server/routes/admin/sidebar-artefact-content.ts
12841
12924
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
12842
12925
  import { existsSync as existsSync23 } from "fs";
12843
- import { resolve as resolve22 } from "path";
12844
- var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12926
+ import { resolve as resolve23 } from "path";
12927
+ var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12845
12928
  var app33 = new Hono();
12846
12929
  app33.get("/", requireAdminSession, async (c) => {
12847
12930
  const sessionKey = c.var.sessionKey;
12848
12931
  const accountId = getAccountIdForSession(sessionKey);
12849
12932
  if (!accountId) return new Response("Unauthorized", { status: 401 });
12850
12933
  const id = c.req.query("id") ?? "";
12851
- if (!UUID_RE5.test(id)) {
12934
+ if (!UUID_RE6.test(id)) {
12852
12935
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
12853
12936
  return new Response("Not found", { status: 404 });
12854
12937
  }
12855
- const dir = resolve22(ATTACHMENTS_ROOT, accountId, id);
12938
+ const dir = resolve23(ATTACHMENTS_ROOT, accountId, id);
12856
12939
  if (!existsSync23(dir)) {
12857
12940
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
12858
12941
  return new Response("Not found", { status: 404 });
12859
12942
  }
12860
12943
  let meta;
12861
12944
  try {
12862
- meta = JSON.parse(await readFile6(resolve22(dir, `${id}.meta.json`), "utf-8"));
12945
+ meta = JSON.parse(await readFile6(resolve23(dir, `${id}.meta.json`), "utf-8"));
12863
12946
  } catch {
12864
12947
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
12865
12948
  return new Response("Not found", { status: 404 });
@@ -12871,7 +12954,7 @@ app33.get("/", requireAdminSession, async (c) => {
12871
12954
  return new Response("Not found", { status: 404 });
12872
12955
  }
12873
12956
  const start = Date.now();
12874
- const buffer = await readFile6(resolve22(dir, dataFile));
12957
+ const buffer = await readFile6(resolve23(dir, dataFile));
12875
12958
  const ms = Date.now() - start;
12876
12959
  console.log(
12877
12960
  `[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
@@ -12915,8 +12998,8 @@ app34.route("/sidebar-artefact-content", sidebar_artefact_content_default);
12915
12998
  var admin_default = app34;
12916
12999
 
12917
13000
  // server/routes/sites.ts
12918
- import { existsSync as existsSync24, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
12919
- import { resolve as resolve23 } from "path";
13001
+ import { existsSync as existsSync24, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
13002
+ import { resolve as resolve24 } from "path";
12920
13003
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12921
13004
  var MIME = {
12922
13005
  ".html": "text/html; charset=utf-8",
@@ -12974,8 +13057,8 @@ app35.get("/:rel{.*}", (c) => {
12974
13057
  }
12975
13058
  segments.push(seg);
12976
13059
  }
12977
- const rootDir = resolve23(account.accountDir, "sites");
12978
- let filePath = segments.length === 0 ? rootDir : resolve23(rootDir, ...segments);
13060
+ const rootDir = resolve24(account.accountDir, "sites");
13061
+ let filePath = segments.length === 0 ? rootDir : resolve24(rootDir, ...segments);
12979
13062
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
12980
13063
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
12981
13064
  return c.text("Forbidden", 403);
@@ -12987,9 +13070,9 @@ app35.get("/:rel{.*}", (c) => {
12987
13070
  stat7 = null;
12988
13071
  }
12989
13072
  if (stat7?.isDirectory()) {
12990
- filePath = resolve23(filePath, "index.html");
13073
+ filePath = resolve24(filePath, "index.html");
12991
13074
  } else if (stat7 === null && isDirRequest) {
12992
- filePath = resolve23(filePath, "index.html");
13075
+ filePath = resolve24(filePath, "index.html");
12993
13076
  }
12994
13077
  if (!filePath.startsWith(rootDir + "/")) {
12995
13078
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -13014,7 +13097,7 @@ app35.get("/:rel{.*}", (c) => {
13014
13097
  }
13015
13098
  let body;
13016
13099
  try {
13017
- body = readFileSync17(realPath);
13100
+ body = readFileSync18(realPath);
13018
13101
  } catch (err) {
13019
13102
  const code = err?.code;
13020
13103
  if (code === "EISDIR") {
@@ -13153,7 +13236,7 @@ if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
13153
13236
  }
13154
13237
  if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
13155
13238
  try {
13156
- const parsed = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
13239
+ const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
13157
13240
  BRAND = { ...BRAND, ...parsed };
13158
13241
  } catch (err) {
13159
13242
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -13176,7 +13259,7 @@ var ALIAS_DOMAINS_PATH2 = join11(homedir2(), BRAND.configDir, "alias-domains.jso
13176
13259
  function loadAliasDomains() {
13177
13260
  try {
13178
13261
  if (!existsSync25(ALIAS_DOMAINS_PATH2)) return null;
13179
- const parsed = JSON.parse(readFileSync18(ALIAS_DOMAINS_PATH2, "utf-8"));
13262
+ const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH2, "utf-8"));
13180
13263
  if (!Array.isArray(parsed)) {
13181
13264
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
13182
13265
  return null;
@@ -13516,8 +13599,8 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
13516
13599
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
13517
13600
  return c.text("Not found", 404);
13518
13601
  }
13519
- const filePath = resolve24(account.accountDir, "agents", slug, "assets", filename);
13520
- const expectedDir = resolve24(account.accountDir, "agents", slug, "assets");
13602
+ const filePath = resolve25(account.accountDir, "agents", slug, "assets", filename);
13603
+ const expectedDir = resolve25(account.accountDir, "agents", slug, "assets");
13521
13604
  if (!filePath.startsWith(expectedDir + "/")) {
13522
13605
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
13523
13606
  return c.text("Forbidden", 403);
@@ -13529,7 +13612,7 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
13529
13612
  const ext = "." + filename.split(".").pop()?.toLowerCase();
13530
13613
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
13531
13614
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
13532
- const body = readFileSync18(filePath);
13615
+ const body = readFileSync19(filePath);
13533
13616
  return c.body(body, 200, {
13534
13617
  "Content-Type": contentType,
13535
13618
  "Cache-Control": "public, max-age=3600"
@@ -13546,8 +13629,8 @@ app36.get("/generated/:filename", (c) => {
13546
13629
  console.error(`[generated] serve file=${filename} status=404`);
13547
13630
  return c.text("Not found", 404);
13548
13631
  }
13549
- const filePath = resolve24(account.accountDir, "generated", filename);
13550
- const expectedDir = resolve24(account.accountDir, "generated");
13632
+ const filePath = resolve25(account.accountDir, "generated", filename);
13633
+ const expectedDir = resolve25(account.accountDir, "generated");
13551
13634
  if (!filePath.startsWith(expectedDir + "/")) {
13552
13635
  console.error(`[generated] serve file=${filename} status=403`);
13553
13636
  return c.text("Forbidden", 403);
@@ -13559,7 +13642,7 @@ app36.get("/generated/:filename", (c) => {
13559
13642
  const ext = "." + filename.split(".").pop()?.toLowerCase();
13560
13643
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
13561
13644
  console.log(`[generated] serve file=${filename} status=200`);
13562
- const body = readFileSync18(filePath);
13645
+ const body = readFileSync19(filePath);
13563
13646
  return c.body(body, 200, {
13564
13647
  "Content-Type": contentType,
13565
13648
  "Cache-Control": "public, max-age=86400"
@@ -13571,7 +13654,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
13571
13654
  var brandIconPath = "/brand/maxy-monochrome.png";
13572
13655
  if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
13573
13656
  try {
13574
- const fullBrand = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
13657
+ const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
13575
13658
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
13576
13659
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
13577
13660
  } catch {
@@ -13590,7 +13673,7 @@ function readInstalledVersion() {
13590
13673
  if (!PLATFORM_ROOT7) return "unknown";
13591
13674
  const versionFile = join11(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
13592
13675
  if (!existsSync25(versionFile)) return "unknown";
13593
- const content = readFileSync18(versionFile, "utf-8").trim();
13676
+ const content = readFileSync19(versionFile, "utf-8").trim();
13594
13677
  return content || "unknown";
13595
13678
  } catch {
13596
13679
  return "unknown";
@@ -13631,7 +13714,7 @@ var clientErrorReporterScript = `<script>
13631
13714
  function cachedHtml(file) {
13632
13715
  let html = htmlCache.get(file);
13633
13716
  if (!html) {
13634
- html = readFileSync18(resolve24(process.cwd(), "public", file), "utf-8");
13717
+ html = readFileSync19(resolve25(process.cwd(), "public", file), "utf-8");
13635
13718
  const productNameEsc = escapeHtml(BRAND.productName);
13636
13719
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
13637
13720
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -13651,12 +13734,12 @@ function loadBrandingCache(agentSlug) {
13651
13734
  try {
13652
13735
  const accountJsonPath = join11(configDir2, "account.json");
13653
13736
  if (!existsSync25(accountJsonPath)) return null;
13654
- const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
13737
+ const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13655
13738
  const accountId = account.accountId;
13656
13739
  if (!accountId) return null;
13657
13740
  const cachePath = join11(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
13658
13741
  if (!existsSync25(cachePath)) return null;
13659
- return JSON.parse(readFileSync18(cachePath, "utf-8"));
13742
+ return JSON.parse(readFileSync19(cachePath, "utf-8"));
13660
13743
  } catch {
13661
13744
  return null;
13662
13745
  }
@@ -13666,7 +13749,7 @@ function resolveDefaultSlug() {
13666
13749
  const configDir2 = join11(homedir2(), BRAND.configDir);
13667
13750
  const accountJsonPath = join11(configDir2, "account.json");
13668
13751
  if (!existsSync25(accountJsonPath)) return null;
13669
- const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
13752
+ const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
13670
13753
  return account.defaultAgent || null;
13671
13754
  } catch {
13672
13755
  return null;
@@ -13675,11 +13758,11 @@ function resolveDefaultSlug() {
13675
13758
  function brandedPublicHtml(agentSlug) {
13676
13759
  const baseHtml = cachedHtml("public.html");
13677
13760
  if (!agentSlug) return baseHtml;
13678
- const cached = brandedHtmlCache.get(agentSlug);
13761
+ const cached2 = brandedHtmlCache.get(agentSlug);
13679
13762
  const branding = loadBrandingCache(agentSlug);
13680
13763
  if (!branding) return baseHtml;
13681
13764
  const brandHash = JSON.stringify(branding).length;
13682
- if (cached && cached.mtime === brandHash) return cached.html;
13765
+ if (cached2 && cached2.mtime === brandHash) return cached2.html;
13683
13766
  const title = escapeHtml(branding.name);
13684
13767
  const description = branding.tagline ? escapeHtml(branding.tagline) : "";
13685
13768
  const themeColor = branding.primaryColor || "";
@@ -13739,7 +13822,7 @@ app36.use("/vnc-popout.html", logViewerFetch);
13739
13822
  app36.get("/vnc-popout.html", (c) => {
13740
13823
  let html = htmlCache.get("vnc-popout.html");
13741
13824
  if (!html) {
13742
- html = readFileSync18(resolve24(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13825
+ html = readFileSync19(resolve25(process.cwd(), "public", "vnc-popout.html"), "utf-8");
13743
13826
  const name = escapeHtml(BRAND.productName);
13744
13827
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
13745
13828
  html = html.replace("</head>", ` ${brandScript}
@@ -13830,7 +13913,7 @@ try {
13830
13913
  try {
13831
13914
  let userId = "";
13832
13915
  if (existsSync25(USERS_FILE)) {
13833
- const users = JSON.parse(readFileSync18(USERS_FILE, "utf-8").trim() || "[]");
13916
+ const users = JSON.parse(readFileSync19(USERS_FILE, "utf-8").trim() || "[]");
13834
13917
  userId = users[0]?.userId ?? "";
13835
13918
  }
13836
13919
  await backfillNullUserIdConversations(userId);
@@ -13939,7 +14022,7 @@ if (bootAccountConfig?.whatsapp) {
13939
14022
  }
13940
14023
  init({
13941
14024
  configDir: configDirForWhatsApp,
13942
- platformRoot: resolve24(process.env.MAXY_PLATFORM_ROOT ?? join11(__dirname, "..")),
14025
+ platformRoot: resolve25(process.env.MAXY_PLATFORM_ROOT ?? join11(__dirname, "..")),
13943
14026
  accountConfig: bootAccountConfig,
13944
14027
  onMessage: async (msg) => {
13945
14028
  try {