@rubytech/create-maxy-code 0.1.442 → 0.1.443

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 (37) hide show
  1. package/dist/__tests__/converge-client-admins.test.js +50 -0
  2. package/dist/converge-client-admins.js +67 -0
  3. package/dist/index.js +8 -0
  4. package/package.json +1 -1
  5. package/payload/platform/docs/superpowers/plans/2026-07-13-account-schema-ontology-projection.md +547 -0
  6. package/payload/platform/docs/superpowers/plans/2026-07-14-graph-top-level-labels-ontology-single-source.md +458 -0
  7. package/payload/platform/docs/superpowers/specs/2026-07-13-account-schema-ontology-projection-design.md +178 -0
  8. package/payload/platform/docs/superpowers/specs/2026-07-14-graph-top-level-labels-ontology-single-source-design.md +119 -0
  9. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  10. package/payload/platform/plugins/admin/PLUGIN.md +7 -1
  11. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +19 -2
  12. package/payload/platform/plugins/admin/mcp/dist/index.js +126 -1
  13. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  14. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +30 -0
  15. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
  16. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +78 -0
  17. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
  18. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
  19. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  20. package/payload/platform/plugins/memory/PLUGIN.md +2 -0
  21. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js +12 -0
  22. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts +9 -1
  24. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js +19 -2
  26. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js.map +1 -1
  27. package/payload/platform/plugins/memory/references/schema-estate-agent.md +8 -3
  28. package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +58 -0
  29. package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +6 -0
  30. package/payload/platform/scripts/lib/account-schema-owned-dirs.py +143 -10
  31. package/payload/platform/scripts/lib/provision-account-dir.sh +5 -0
  32. package/payload/platform/scripts/name-glsmith-owner.sh +239 -0
  33. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
  35. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  36. package/payload/server/server.js +341 -169
  37. package/payload/platform/plugins/memory/references/schema-trades.md +0 -34
@@ -1413,10 +1413,10 @@ var serveStatic = (options = { root: "" }) => {
1413
1413
  };
1414
1414
 
1415
1415
  // server/index.ts
1416
- import { readFileSync as readFileSync36, existsSync as existsSync35, watchFile } from "fs";
1416
+ import { readFileSync as readFileSync37, existsSync as existsSync35, watchFile } from "fs";
1417
1417
  import { spawn as spawn3 } from "child_process";
1418
1418
  import { createHash as createHash7 } from "crypto";
1419
- import { resolve as resolve33, join as join36, basename as basename12 } from "path";
1419
+ import { resolve as resolve34, join as join37, basename as basename12 } from "path";
1420
1420
  import { homedir as homedir4 } from "os";
1421
1421
  import { monitorEventLoopDelay } from "perf_hooks";
1422
1422
 
@@ -2129,7 +2129,7 @@ var credsSaveQueue = Promise.resolve();
2129
2129
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
2130
2130
  console.error(`${TAG2} draining credential save queue\u2026`);
2131
2131
  const timer2 = new Promise(
2132
- (resolve34) => setTimeout(() => resolve34("timeout"), timeoutMs)
2132
+ (resolve35) => setTimeout(() => resolve35("timeout"), timeoutMs)
2133
2133
  );
2134
2134
  const result = await Promise.race([
2135
2135
  credsSaveQueue.then(() => "drained"),
@@ -2292,11 +2292,11 @@ async function createWaSocket(opts) {
2292
2292
  return sock;
2293
2293
  }
2294
2294
  async function waitForConnection(sock) {
2295
- return new Promise((resolve34, reject) => {
2295
+ return new Promise((resolve35, reject) => {
2296
2296
  const handler = (update) => {
2297
2297
  if (update.connection === "open") {
2298
2298
  sock.ev.off("connection.update", handler);
2299
- resolve34();
2299
+ resolve35();
2300
2300
  }
2301
2301
  if (update.connection === "close") {
2302
2302
  sock.ev.off("connection.update", handler);
@@ -2401,7 +2401,7 @@ import { inspect as inspect2 } from "util";
2401
2401
 
2402
2402
  // app/lib/whatsapp/with-timeout.ts
2403
2403
  function withTimeout(label, promise, timeoutMs) {
2404
- return new Promise((resolve34, reject) => {
2404
+ return new Promise((resolve35, reject) => {
2405
2405
  const timer2 = setTimeout(() => {
2406
2406
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2407
2407
  }, timeoutMs);
@@ -2409,7 +2409,7 @@ function withTimeout(label, promise, timeoutMs) {
2409
2409
  promise.then(
2410
2410
  (value) => {
2411
2411
  clearTimeout(timer2);
2412
- resolve34(value);
2412
+ resolve35(value);
2413
2413
  },
2414
2414
  (err) => {
2415
2415
  clearTimeout(timer2);
@@ -3489,10 +3489,10 @@ function readConversationSummaries(platformAccountId) {
3489
3489
  } catch {
3490
3490
  continue;
3491
3491
  }
3492
- const cached2 = summaryCache.get(file);
3493
- if (cached2 && cached2.size === size && cached2.mtimeMs === mtimeMs) {
3492
+ const cached3 = summaryCache.get(file);
3493
+ if (cached3 && cached3.size === size && cached3.mtimeMs === mtimeMs) {
3494
3494
  cacheHits++;
3495
- out.set(remoteJid, cached2.summary);
3495
+ out.set(remoteJid, cached3.summary);
3496
3496
  continue;
3497
3497
  }
3498
3498
  let summary;
@@ -3556,8 +3556,8 @@ async function persistWhatsAppMessage(input) {
3556
3556
  const { givenName, familyName } = splitName(input.pushName);
3557
3557
  const prev = sessionWriteLocks.get(input.cacheKey);
3558
3558
  let release;
3559
- const mine = new Promise((resolve34) => {
3560
- release = resolve34;
3559
+ const mine = new Promise((resolve35) => {
3560
+ release = resolve35;
3561
3561
  });
3562
3562
  const chained = (prev ?? Promise.resolve()).then(() => mine);
3563
3563
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3700,8 +3700,8 @@ import { resolve as resolve3 } from "path";
3700
3700
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3701
3701
  var cache = /* @__PURE__ */ new Map();
3702
3702
  function enumerateValidAccountIds(accountsDir) {
3703
- const cached2 = cache.get(accountsDir);
3704
- if (cached2 !== void 0) return cached2;
3703
+ const cached3 = cache.get(accountsDir);
3704
+ if (cached3 !== void 0) return cached3;
3705
3705
  let names;
3706
3706
  try {
3707
3707
  names = readdirSync2(accountsDir);
@@ -5259,11 +5259,11 @@ async function connectWithReconnect(conn) {
5259
5259
  console.error(
5260
5260
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
5261
5261
  );
5262
- await new Promise((resolve34) => {
5263
- const timer2 = setTimeout(resolve34, delay);
5262
+ await new Promise((resolve35) => {
5263
+ const timer2 = setTimeout(resolve35, delay);
5264
5264
  conn.abortController.signal.addEventListener("abort", () => {
5265
5265
  clearTimeout(timer2);
5266
- resolve34();
5266
+ resolve35();
5267
5267
  }, { once: true });
5268
5268
  });
5269
5269
  }
@@ -5271,16 +5271,16 @@ async function connectWithReconnect(conn) {
5271
5271
  }
5272
5272
  }
5273
5273
  function waitForDisconnectEvent(conn) {
5274
- return new Promise((resolve34) => {
5274
+ return new Promise((resolve35) => {
5275
5275
  if (!conn.sock) {
5276
- resolve34();
5276
+ resolve35();
5277
5277
  return;
5278
5278
  }
5279
5279
  const sock = conn.sock;
5280
5280
  const handler = (update) => {
5281
5281
  if (update.connection === "close") {
5282
5282
  sock.ev.off("connection.update", handler);
5283
- resolve34();
5283
+ resolve35();
5284
5284
  }
5285
5285
  };
5286
5286
  sock.ev.on("connection.update", handler);
@@ -5602,8 +5602,8 @@ async function handleInboundMessage(conn, msg) {
5602
5602
  const conversationKey = isGroup ? remoteJid : senderPhone;
5603
5603
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
5604
5604
  let resolvePending;
5605
- const sttPending = new Promise((resolve34) => {
5606
- resolvePending = resolve34;
5605
+ const sttPending = new Promise((resolve35) => {
5606
+ resolvePending = resolve35;
5607
5607
  });
5608
5608
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
5609
5609
  try {
@@ -6031,20 +6031,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
6031
6031
 
6032
6032
  // server/routes/health.ts
6033
6033
  function checkPort(port2, timeoutMs = 500) {
6034
- return new Promise((resolve34) => {
6034
+ return new Promise((resolve35) => {
6035
6035
  const socket = createConnection2(port2, "127.0.0.1");
6036
6036
  socket.setTimeout(timeoutMs);
6037
6037
  socket.once("connect", () => {
6038
6038
  socket.destroy();
6039
- resolve34(true);
6039
+ resolve35(true);
6040
6040
  });
6041
6041
  socket.once("error", () => {
6042
6042
  socket.destroy();
6043
- resolve34(false);
6043
+ resolve35(false);
6044
6044
  });
6045
6045
  socket.once("timeout", () => {
6046
6046
  socket.destroy();
6047
- resolve34(false);
6047
+ resolve35(false);
6048
6048
  });
6049
6049
  });
6050
6050
  }
@@ -7321,8 +7321,8 @@ async function startLogin(opts) {
7321
7321
  await clearAuth(authDir);
7322
7322
  let resolveCode = null;
7323
7323
  let rejectCode = null;
7324
- const codePromise = new Promise((resolve34, reject) => {
7325
- resolveCode = resolve34;
7324
+ const codePromise = new Promise((resolve35, reject) => {
7325
+ resolveCode = resolve35;
7326
7326
  rejectCode = reject;
7327
7327
  });
7328
7328
  const codeTimer = setTimeout(
@@ -9210,6 +9210,24 @@ function splitNewLines(buf, baseOffset) {
9210
9210
  };
9211
9211
  }
9212
9212
 
9213
+ // app/lib/whatsapp-reader/authorize-reply-file-ref.ts
9214
+ var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9215
+ function accountPartitionOwner(relative7) {
9216
+ const segs = relative7.split("/").filter(Boolean);
9217
+ if (segs.length < 2 || segs[0] !== "accounts") return null;
9218
+ return ACCOUNT_UUID_RE2.test(segs[1]) ? segs[1] : null;
9219
+ }
9220
+ function authorizeReplyFileRef(input) {
9221
+ const { relative: relative7, sendAccountId, sessionAccountId } = input;
9222
+ const segs = relative7.split("/").filter(Boolean);
9223
+ const inAccounts = segs.length >= 2 && segs[0] === "accounts";
9224
+ if (inAccounts && segs[1] === sendAccountId) return { allow: true, via: "own" };
9225
+ if (inAccounts && sessionAccountId && segs[1] === sessionAccountId) return { allow: true, via: "session" };
9226
+ if (accountPartitionOwner(relative7)) return { allow: false, reason: "cross-account" };
9227
+ if (segs[0] === "public" || inAccounts && segs[1] === "public") return { allow: false, reason: "public" };
9228
+ return { allow: false, reason: "foreign" };
9229
+ }
9230
+
9213
9231
  // server/routes/admin/manager-client.ts
9214
9232
  var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9215
9233
  function isSessionId(value) {
@@ -9244,6 +9262,11 @@ function isMimeAdmitted(mimeType, supportedSet) {
9244
9262
 
9245
9263
  // server/routes/whatsapp-reader.ts
9246
9264
  var app4 = new Hono();
9265
+ var DENY_COPY = {
9266
+ "cross-account": "This file belongs to another account. Open that account to send it.",
9267
+ public: "This file cannot be sent to a WhatsApp contact.",
9268
+ foreign: "This file cannot be sent to a WhatsApp contact."
9269
+ };
9247
9270
  app4.get("/conversations", requireAdminSession, async (c) => {
9248
9271
  const cacheKey = c.var.cacheKey;
9249
9272
  const scopeAccountId = getAccountIdForSession(cacheKey) ?? null;
@@ -9891,7 +9914,9 @@ app4.post("/reply", requireAdminSession, async (c) => {
9891
9914
  return c.json({ error: "invalid accountId" }, 400);
9892
9915
  }
9893
9916
  const validAccount = isValidAccountId(accountId);
9894
- console.log(`${MANUAL_TAG} op=scope sendId=${sendId} accountId=${accountId} validAccount=${validAccount}`);
9917
+ const cacheKey = c.var.cacheKey;
9918
+ const sessionAccountId = getAccountIdForSession(cacheKey) ?? null;
9919
+ console.log(`${MANUAL_TAG} op=scope sendId=${sendId} accountId=${accountId} validAccount=${validAccount} sessionAccount=${sessionAccountId ?? "null"} src=session`);
9895
9920
  if (!validAccount) {
9896
9921
  exit("rejected");
9897
9922
  return c.json({ error: "unknown account" }, 400);
@@ -9929,26 +9954,37 @@ app4.post("/reply", requireAdminSession, async (c) => {
9929
9954
  }
9930
9955
  }
9931
9956
  const resolvedRefs = [];
9957
+ const acct8 = accountId.slice(0, 8);
9958
+ const sess8 = sessionAccountId ? sessionAccountId.slice(0, 8) : "";
9932
9959
  for (const ref of fileRefs) {
9933
9960
  const resolved = resolveDataPath(ref);
9934
- const withinOwn = resolved.ok && !crossesForeignAccountPartition(resolved.relative, accountId) && isWithinOwnAccountPartition(resolved.relative, accountId);
9935
- let absolute = "";
9961
+ if (!resolved.ok) {
9962
+ console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner= sendAccount=${acct8} sessionAccount=${sess8} via=deny reason=unresolved ok=false`);
9963
+ exit("rejected");
9964
+ return c.json({ error: `device file not found: ${ref}`, reason: "file-ref-unresolved" }, 404);
9965
+ }
9966
+ const owner = accountPartitionOwner(resolved.relative);
9967
+ const owner8 = owner ? owner.slice(0, 8) : "";
9968
+ const decision = authorizeReplyFileRef({ relative: resolved.relative, sendAccountId: accountId, sessionAccountId });
9969
+ if (!decision.allow) {
9970
+ console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=deny reason=${decision.reason} ok=false`);
9971
+ exit("rejected");
9972
+ return c.json({ error: DENY_COPY[decision.reason], reason: `file-ref-${decision.reason}` }, 403);
9973
+ }
9974
+ const absolute = resolved.absolute;
9936
9975
  let size = -1;
9937
- if (withinOwn) {
9938
- absolute = resolved.absolute;
9939
- try {
9940
- const st = statSync5(absolute);
9941
- size = st.isFile() ? st.size : -1;
9942
- } catch {
9943
- size = -1;
9944
- }
9976
+ try {
9977
+ const st = statSync5(absolute);
9978
+ size = st.isFile() ? st.size : -1;
9979
+ } catch {
9980
+ size = -1;
9945
9981
  }
9946
- const ok = size >= 0;
9947
- console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} resolved=${absolute} ok=${ok}`);
9948
- if (!ok) {
9982
+ if (size < 0) {
9983
+ console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=missing ok=false`);
9949
9984
  exit("rejected");
9950
9985
  return c.json({ error: `device file not found: ${ref}`, reason: "file-ref-unresolved" }, 404);
9951
9986
  }
9987
+ console.log(`${MANUAL_TAG} op=reply-file-ref sendId=${sendId} path=${ref} owner=${owner8} sendAccount=${acct8} sessionAccount=${sess8} via=${decision.via} reason=none ok=true`);
9952
9988
  if (size > MAX_FILE_BYTES) {
9953
9989
  exit("rejected");
9954
9990
  return c.json({ error: `"${basename4(absolute)}" exceeds the 50 MB limit` }, 400);
@@ -17099,6 +17135,142 @@ function isHiddenByDefault(label) {
17099
17135
  return HIDDEN_BY_DEFAULT_LABELS.has(label);
17100
17136
  }
17101
17137
 
17138
+ // server/lib/top-level-labels.ts
17139
+ import { readdirSync as readdirSync19, readFileSync as readFileSync30 } from "fs";
17140
+ import { join as join30, resolve as resolve23 } from "path";
17141
+ var STATIC_TOP_LEVEL_LABELS = Object.freeze(
17142
+ /* @__PURE__ */ new Set([
17143
+ // Base-schema infra (schema-base.md has no top-level section).
17144
+ "LocalBusiness",
17145
+ "Service",
17146
+ "PriceSpecification",
17147
+ "OpeningHoursSpecification",
17148
+ "Organization",
17149
+ "Person",
17150
+ "UserProfile",
17151
+ "Preference",
17152
+ "AdminUser",
17153
+ "AccessGrant",
17154
+ "KnowledgeDocument",
17155
+ "DigitalDocument",
17156
+ "CreativeWork",
17157
+ "Question",
17158
+ "FAQPage",
17159
+ "DefinedTerm",
17160
+ "Review",
17161
+ "ImageObject",
17162
+ "Invoice",
17163
+ "Task",
17164
+ "Project",
17165
+ "Event",
17166
+ "Workflow",
17167
+ "Email",
17168
+ "EmailAccount",
17169
+ "Agent",
17170
+ // Knowledge-work vertical: schema-knowledge-work.md has no top-level
17171
+ // section yet.
17172
+ "Objective",
17173
+ "KeyResult",
17174
+ "Decision",
17175
+ "Risk",
17176
+ "Source",
17177
+ "Finding",
17178
+ "Hypothesis"
17179
+ ])
17180
+ );
17181
+ function splitPipeRow(row) {
17182
+ let trimmed = row.trim();
17183
+ if (trimmed.startsWith("|")) trimmed = trimmed.slice(1);
17184
+ if (trimmed.endsWith("|")) trimmed = trimmed.slice(0, -1);
17185
+ const cells = [];
17186
+ let inBacktick = false;
17187
+ let start = 0;
17188
+ for (let i = 0; i < trimmed.length; i++) {
17189
+ const ch = trimmed[i];
17190
+ if (ch === "`") inBacktick = !inBacktick;
17191
+ else if (ch === "|" && !inBacktick) {
17192
+ cells.push(trimmed.slice(start, i).trim());
17193
+ start = i + 1;
17194
+ }
17195
+ }
17196
+ cells.push(trimmed.slice(start).trim());
17197
+ return cells;
17198
+ }
17199
+ var stripBackticks = (s) => s.replace(/`/g, "").trim();
17200
+ function parseTopLevelLabels(content) {
17201
+ const lines = content.split(/\r?\n/);
17202
+ let i = 0;
17203
+ while (i < lines.length) {
17204
+ if (lines[i].toLowerCase().startsWith("## top-level node types")) break;
17205
+ i++;
17206
+ }
17207
+ if (i >= lines.length) return [];
17208
+ i++;
17209
+ for (; i < lines.length - 1; i++) {
17210
+ const line = lines[i];
17211
+ if (line.startsWith("## ")) return [];
17212
+ if (!line.includes("|")) continue;
17213
+ const sep9 = lines[i + 1];
17214
+ if (!/^\s*\|?[\s:|-]+\|?\s*$/.test(sep9) || !sep9.includes("-")) continue;
17215
+ const headers = splitPipeRow(line).map((h) => stripBackticks(h).toLowerCase());
17216
+ const labelCol = headers.findIndex((h) => h === "neo4j label");
17217
+ if (labelCol === -1) return [];
17218
+ const out = [];
17219
+ let j = i + 2;
17220
+ for (; j < lines.length; j++) {
17221
+ const row = lines[j];
17222
+ if (!row.trim() || !row.includes("|")) break;
17223
+ const cells = splitPipeRow(row);
17224
+ const label = stripBackticks(cells[labelCol] ?? "");
17225
+ if (label) out.push(label);
17226
+ }
17227
+ return out;
17228
+ }
17229
+ return [];
17230
+ }
17231
+ function resolveReferencesDir() {
17232
+ if (process.env.MAXY_PLATFORM_ROOT) {
17233
+ return join30(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
17234
+ }
17235
+ return resolve23(import.meta.dirname, "../../../plugins/memory/references");
17236
+ }
17237
+ function parseTableTopLevelLabels(referencesDir) {
17238
+ const labels = /* @__PURE__ */ new Set();
17239
+ const contributingFiles = [];
17240
+ try {
17241
+ const fileNames = readdirSync19(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
17242
+ for (const fileName of fileNames) {
17243
+ const content = readFileSync30(join30(referencesDir, fileName), "utf-8");
17244
+ const parsed = parseTopLevelLabels(content);
17245
+ if (parsed.length > 0) contributingFiles.push(fileName);
17246
+ for (const label of parsed) labels.add(label);
17247
+ }
17248
+ } catch (err) {
17249
+ const message = err instanceof Error ? err.message : String(err);
17250
+ process.stderr.write(
17251
+ `[graph-page] op=top-level-labels source=ontology status=error dir=${referencesDir} reason="${message}"
17252
+ `
17253
+ );
17254
+ throw err;
17255
+ }
17256
+ return { labels, contributingFiles };
17257
+ }
17258
+ var cached = null;
17259
+ function getTopLevelLabelAllowlist(opts = {}) {
17260
+ if (!opts.referencesDir && cached) return cached;
17261
+ const referencesDir = opts.referencesDir ?? resolveReferencesDir();
17262
+ const { labels: derived, contributingFiles } = parseTableTopLevelLabels(referencesDir);
17263
+ const derivedCount = derived.size;
17264
+ for (const label of STATIC_TOP_LEVEL_LABELS) derived.add(label);
17265
+ const result = Object.freeze(derived);
17266
+ process.stderr.write(
17267
+ `[graph-page] op=top-level-labels source=ontology count=${derived.size} files=${contributingFiles.join("|") || "none"} derived=${derivedCount} static=${STATIC_TOP_LEVEL_LABELS.size}
17268
+ `
17269
+ );
17270
+ if (!opts.referencesDir) cached = result;
17271
+ return result;
17272
+ }
17273
+
17102
17274
  // server/routes/admin/graph-subgraph.ts
17103
17275
  var CEILING = 2e3;
17104
17276
  var TOP_LEVEL_LIMIT = 1e3;
@@ -17220,7 +17392,7 @@ async function handleDefault(c, accountId) {
17220
17392
  }
17221
17393
  async function handleDefaultTopLevel(c, accountId, flags) {
17222
17394
  const { includeTrashed, includeAgentActions } = flags;
17223
- const labels = [...FILTER_TOP_LEVEL_LABELS].filter((l) => !HIDDEN_BY_DEFAULT_LABELS.has(l));
17395
+ const labels = [...getTopLevelLabelAllowlist()].filter((l) => !HIDDEN_BY_DEFAULT_LABELS.has(l));
17224
17396
  const agentActionLabels = [...AGENT_ACTION_LABELS];
17225
17397
  const started = Date.now();
17226
17398
  const session = getSession();
@@ -18031,7 +18203,7 @@ app26.get("/", requireAdminSession, async (c) => {
18031
18203
  const started = Date.now();
18032
18204
  const session = getSession();
18033
18205
  try {
18034
- const allowedSet = new Set(FILTER_TOP_LEVEL_LABELS);
18206
+ const allowedSet = new Set(getTopLevelLabelAllowlist());
18035
18207
  if (includeAgentActions) {
18036
18208
  for (const label of AGENT_ACTION_LABELS) allowedSet.add(label);
18037
18209
  }
@@ -18193,12 +18365,12 @@ function validateBody(body) {
18193
18365
  if (typeof lbl !== "string") {
18194
18366
  return { ok: false, code: "shape", reason: "labels must be an array of strings" };
18195
18367
  }
18196
- if (!FILTER_TOP_LEVEL_LABELS.has(lbl)) {
18368
+ if (!getTopLevelLabelAllowlist().has(lbl)) {
18197
18369
  return {
18198
18370
  ok: false,
18199
18371
  code: "not-eligible-chip",
18200
18372
  label: lbl,
18201
- reason: `label "${lbl}" is not eligible for default view \u2014 outside the chip allowlist (FILTER_TOP_LEVEL_LABELS)`
18373
+ reason: `label "${lbl}" is not eligible for default view \u2014 outside the chip allowlist`
18202
18374
  };
18203
18375
  }
18204
18376
  seen.add(lbl);
@@ -18221,7 +18393,7 @@ var graph_default_view_default = app27;
18221
18393
 
18222
18394
  // server/routes/admin/sidebar-artefacts.ts
18223
18395
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
18224
- import { resolve as resolve23, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
18396
+ import { resolve as resolve24, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
18225
18397
  import { existsSync as existsSync27 } from "fs";
18226
18398
  var LIMIT = 50;
18227
18399
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -18241,7 +18413,7 @@ app28.get("/", requireAdminSession, async (c) => {
18241
18413
  if (accountFiles === null) {
18242
18414
  return c.json({ error: "Failed to load artefacts" }, 500);
18243
18415
  }
18244
- const accountDir = resolve23(ACCOUNTS_DIR, accountId);
18416
+ const accountDir = resolve24(ACCOUNTS_DIR, accountId);
18245
18417
  const agents = await fetchAgentTemplateRows(accountDir);
18246
18418
  const artefacts = [...accountFiles, ...agents].sort(
18247
18419
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -18293,8 +18465,8 @@ async function fetchAccountFileArtefacts(accountId) {
18293
18465
  async function fetchAgentTemplateRows(accountDir) {
18294
18466
  const rows = [];
18295
18467
  for (const filename of ADMIN_AGENT_FILES) {
18296
- const overridePath = resolve23(accountDir, "agents", "admin", filename);
18297
- const bundledPath = resolve23(PLATFORM_ROOT, "templates", "agents", "admin", filename);
18468
+ const overridePath = resolve24(accountDir, "agents", "admin", filename);
18469
+ const bundledPath = resolve24(PLATFORM_ROOT, "templates", "agents", "admin", filename);
18298
18470
  const labelStem = filename.replace(/\.md$/, "");
18299
18471
  const row = await readAgentTemplateRow({
18300
18472
  id: `agent-template:admin:${filename}`,
@@ -18307,12 +18479,12 @@ async function fetchAgentTemplateRows(accountDir) {
18307
18479
  });
18308
18480
  if (row) rows.push(row);
18309
18481
  }
18310
- const overrideDir = resolve23(accountDir, "specialists", "agents");
18311
- const bundledDir = resolve23(PLATFORM_ROOT, "templates", "specialists", "agents");
18482
+ const overrideDir = resolve24(accountDir, "specialists", "agents");
18483
+ const bundledDir = resolve24(PLATFORM_ROOT, "templates", "specialists", "agents");
18312
18484
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
18313
18485
  for (const filename of specialistNames) {
18314
- const overridePath = resolve23(overrideDir, filename);
18315
- const bundledPath = resolve23(bundledDir, filename);
18486
+ const overridePath = resolve24(overrideDir, filename);
18487
+ const bundledPath = resolve24(bundledDir, filename);
18316
18488
  const row = await readAgentTemplateRow({
18317
18489
  id: `agent-template:specialist:${filename}`,
18318
18490
  displayName: filename.replace(/\.md$/, ""),
@@ -18594,7 +18766,7 @@ var session_usage_default = app33;
18594
18766
 
18595
18767
  // server/routes/admin/session-rc-spawn.ts
18596
18768
  import { randomUUID as randomUUID10 } from "crypto";
18597
- var ACCOUNT_UUID_RE2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
18769
+ var ACCOUNT_UUID_RE3 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
18598
18770
  function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID10, adminUserId, authenticatedName, callerAccountId) {
18599
18771
  const operator = isOperatorHost(host, operatorDomains);
18600
18772
  const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
@@ -18605,8 +18777,8 @@ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID10, ad
18605
18777
  const pickedModel = kind === "new" && typeof body.model === "string" && isSelectableModel(body.model) ? body.model : null;
18606
18778
  const pickedEffort = kind === "new" && typeof body.effort === "string" && isNewSessionEffortLevel(body.effort) ? body.effort : null;
18607
18779
  const paramsSource = pickedModel !== null && pickedEffort !== null ? "picker" : "default";
18608
- const callerTargetAccountId = typeof callerAccountId === "string" && ACCOUNT_UUID_RE2.test(callerAccountId) ? callerAccountId : void 0;
18609
- const bodyTargetAccountId = typeof body.targetAccountId === "string" && ACCOUNT_UUID_RE2.test(body.targetAccountId) ? body.targetAccountId : void 0;
18780
+ const callerTargetAccountId = typeof callerAccountId === "string" && ACCOUNT_UUID_RE3.test(callerAccountId) ? callerAccountId : void 0;
18781
+ const bodyTargetAccountId = typeof body.targetAccountId === "string" && ACCOUNT_UUID_RE3.test(body.targetAccountId) ? body.targetAccountId : void 0;
18610
18782
  const targetAccountId = kind === "new" ? callerTargetAccountId : bodyTargetAccountId;
18611
18783
  const payload = {};
18612
18784
  let sessionId;
@@ -18957,24 +19129,24 @@ app36.get("/", async (c) => {
18957
19129
  var system_stats_default = app36;
18958
19130
 
18959
19131
  // server/routes/admin/health.ts
18960
- import { existsSync as existsSync28, readFileSync as readFileSync30 } from "fs";
18961
- import { resolve as resolve24, join as join30 } from "path";
18962
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
19132
+ import { existsSync as existsSync28, readFileSync as readFileSync31 } from "fs";
19133
+ import { resolve as resolve25, join as join31 } from "path";
19134
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve25(process.cwd(), "..");
18963
19135
  var brandHostname = "maxy";
18964
- var brandJsonPath = join30(PLATFORM_ROOT6, "config", "brand.json");
19136
+ var brandJsonPath = join31(PLATFORM_ROOT6, "config", "brand.json");
18965
19137
  if (existsSync28(brandJsonPath)) {
18966
19138
  try {
18967
- const brand = JSON.parse(readFileSync30(brandJsonPath, "utf-8"));
19139
+ const brand = JSON.parse(readFileSync31(brandJsonPath, "utf-8"));
18968
19140
  if (brand.hostname) brandHostname = brand.hostname;
18969
19141
  } catch {
18970
19142
  }
18971
19143
  }
18972
- var VERSION_FILE = resolve24(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
19144
+ var VERSION_FILE = resolve25(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
18973
19145
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
18974
19146
  var PROBE_TIMEOUT_MS = 1e3;
18975
19147
  function readVersion() {
18976
19148
  if (!existsSync28(VERSION_FILE)) return "unknown";
18977
- return readFileSync30(VERSION_FILE, "utf-8").trim() || "unknown";
19149
+ return readFileSync31(VERSION_FILE, "utf-8").trim() || "unknown";
18978
19150
  }
18979
19151
  async function probeConversationDb() {
18980
19152
  let session;
@@ -19751,7 +19923,7 @@ var browser_default = app44;
19751
19923
 
19752
19924
  // server/routes/admin/calendar.ts
19753
19925
  import { existsSync as existsSync29 } from "fs";
19754
- import { join as join32 } from "path";
19926
+ import { join as join33 } from "path";
19755
19927
 
19756
19928
  // server/lib/calendar-ics.ts
19757
19929
  var CRLF = "\r\n";
@@ -19850,8 +20022,8 @@ function countVEvents(ics) {
19850
20022
  }
19851
20023
 
19852
20024
  // server/lib/calendar-availability.ts
19853
- import { readFileSync as readFileSync31 } from "fs";
19854
- import { join as join31 } from "path";
20025
+ import { readFileSync as readFileSync32 } from "fs";
20026
+ import { join as join32 } from "path";
19855
20027
  var AVAILABILITY_FILENAME = "calendar-availability.json";
19856
20028
  var REQUIRED_KEYS = [
19857
20029
  "timezone",
@@ -19860,10 +20032,10 @@ var REQUIRED_KEYS = [
19860
20032
  "weekly"
19861
20033
  ];
19862
20034
  function readAvailabilityConfig(accountDir) {
19863
- const path2 = join31(accountDir, AVAILABILITY_FILENAME);
20035
+ const path2 = join32(accountDir, AVAILABILITY_FILENAME);
19864
20036
  let raw;
19865
20037
  try {
19866
- raw = readFileSync31(path2, "utf-8");
20038
+ raw = readFileSync32(path2, "utf-8");
19867
20039
  } catch {
19868
20040
  throw new Error(`availability not configured: ${path2} not found`);
19869
20041
  }
@@ -20222,7 +20394,7 @@ app45.get("/booking-link", requireAdminSession, (c) => {
20222
20394
  console.error('[calendar] op=booking-link-fail err="no account configured"');
20223
20395
  return c.json({ bookingDomain: null });
20224
20396
  }
20225
- if (!existsSync29(join32(account.accountDir, AVAILABILITY_FILENAME))) {
20397
+ if (!existsSync29(join33(account.accountDir, AVAILABILITY_FILENAME))) {
20226
20398
  console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
20227
20399
  return c.json({ bookingDomain: null });
20228
20400
  }
@@ -20696,9 +20868,9 @@ var verify_token_default = app52;
20696
20868
 
20697
20869
  // app/lib/access-email.ts
20698
20870
  import { spawn as spawn2 } from "child_process";
20699
- import { resolve as resolve25 } from "path";
20700
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve25(process.cwd(), "..");
20701
- var SEND_SCRIPT = resolve25(
20871
+ import { resolve as resolve26 } from "path";
20872
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
20873
+ var SEND_SCRIPT = resolve26(
20702
20874
  PLATFORM_ROOT7,
20703
20875
  "plugins",
20704
20876
  "email",
@@ -20840,8 +21012,8 @@ app54.route("/request-magic-link", request_magic_link_default);
20840
21012
  var access_default = app54;
20841
21013
 
20842
21014
  // server/routes/sites.ts
20843
- import { existsSync as existsSync30, readFileSync as readFileSync32, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
20844
- import { resolve as resolve26 } from "path";
21015
+ import { existsSync as existsSync30, readFileSync as readFileSync33, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
21016
+ import { resolve as resolve27 } from "path";
20845
21017
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
20846
21018
  var MIME = {
20847
21019
  ".html": "text/html; charset=utf-8",
@@ -20898,8 +21070,8 @@ app55.get("/:rel{.*}", (c) => {
20898
21070
  }
20899
21071
  segments.push(seg);
20900
21072
  }
20901
- const rootDir = resolve26(account.accountDir, "sites");
20902
- let filePath = segments.length === 0 ? rootDir : resolve26(rootDir, ...segments);
21073
+ const rootDir = resolve27(account.accountDir, "sites");
21074
+ let filePath = segments.length === 0 ? rootDir : resolve27(rootDir, ...segments);
20903
21075
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
20904
21076
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
20905
21077
  return c.text("Forbidden", 403);
@@ -20919,7 +21091,7 @@ app55.get("/:rel{.*}", (c) => {
20919
21091
  return c.redirect(target, 301);
20920
21092
  }
20921
21093
  if (stat8?.isDirectory()) {
20922
- filePath = resolve26(filePath, "index.html");
21094
+ filePath = resolve27(filePath, "index.html");
20923
21095
  }
20924
21096
  if (!filePath.startsWith(rootDir + "/")) {
20925
21097
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -20944,7 +21116,7 @@ app55.get("/:rel{.*}", (c) => {
20944
21116
  }
20945
21117
  let body;
20946
21118
  try {
20947
- body = readFileSync32(realPath);
21119
+ body = readFileSync33(realPath);
20948
21120
  } catch (err) {
20949
21121
  const code = err?.code;
20950
21122
  if (code === "EISDIR") {
@@ -20980,7 +21152,7 @@ var sites_default = app55;
20980
21152
 
20981
21153
  // app/lib/visitor-token.ts
20982
21154
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
20983
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync33, writeFileSync as writeFileSync11 } from "fs";
21155
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync34, writeFileSync as writeFileSync11 } from "fs";
20984
21156
  import { dirname as dirname11 } from "path";
20985
21157
  var TOKEN_PREFIX = "v1.";
20986
21158
  var SECRET_BYTES = 32;
@@ -20989,7 +21161,7 @@ var cachedSecret = null;
20989
21161
  function getSecret() {
20990
21162
  if (cachedSecret) return cachedSecret;
20991
21163
  try {
20992
- const hex2 = readFileSync33(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
21164
+ const hex2 = readFileSync34(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
20993
21165
  if (hex2.length === SECRET_BYTES * 2) {
20994
21166
  cachedSecret = Buffer.from(hex2, "hex");
20995
21167
  return cachedSecret;
@@ -21003,7 +21175,7 @@ function getSecret() {
21003
21175
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
21004
21176
  } catch {
21005
21177
  }
21006
- const hex = readFileSync33(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
21178
+ const hex = readFileSync34(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
21007
21179
  cachedSecret = Buffer.from(hex, "hex");
21008
21180
  return cachedSecret;
21009
21181
  }
@@ -21056,20 +21228,20 @@ var VISITOR_COOKIE_NAME = "mxy_v";
21056
21228
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
21057
21229
 
21058
21230
  // app/lib/brand-config.ts
21059
- import { existsSync as existsSync31, readFileSync as readFileSync34 } from "fs";
21060
- import { join as join33 } from "path";
21061
- var cached = null;
21231
+ import { existsSync as existsSync31, readFileSync as readFileSync35 } from "fs";
21232
+ import { join as join34 } from "path";
21233
+ var cached2 = null;
21062
21234
  var cachedAttempted = false;
21063
21235
  function readBrandConfig() {
21064
- if (cachedAttempted) return cached;
21236
+ if (cachedAttempted) return cached2;
21065
21237
  cachedAttempted = true;
21066
21238
  const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
21067
21239
  if (!platformRoot3) return null;
21068
- const brandPath = join33(platformRoot3, "config", "brand.json");
21240
+ const brandPath = join34(platformRoot3, "config", "brand.json");
21069
21241
  if (!existsSync31(brandPath)) return null;
21070
21242
  try {
21071
- cached = JSON.parse(readFileSync34(brandPath, "utf-8"));
21072
- return cached;
21243
+ cached2 = JSON.parse(readFileSync35(brandPath, "utf-8"));
21244
+ return cached2;
21073
21245
  } catch {
21074
21246
  return null;
21075
21247
  }
@@ -21556,14 +21728,14 @@ async function writeEvent(opts) {
21556
21728
  var visitor_event_default = app58;
21557
21729
 
21558
21730
  // server/routes/session.ts
21559
- import { resolve as resolve27 } from "path";
21731
+ import { resolve as resolve28 } from "path";
21560
21732
  import { existsSync as existsSync32, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
21561
21733
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
21562
21734
  function writeBrandingCache(accountId, agentSlug, branding) {
21563
21735
  try {
21564
- const cacheDir = resolve27(MAXY_DIR, "branding-cache", accountId);
21736
+ const cacheDir = resolve28(MAXY_DIR, "branding-cache", accountId);
21565
21737
  mkdirSync8(cacheDir, { recursive: true });
21566
- writeFileSync12(resolve27(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
21738
+ writeFileSync12(resolve28(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
21567
21739
  } catch (err) {
21568
21740
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
21569
21741
  }
@@ -21640,8 +21812,8 @@ app59.post("/", async (c) => {
21640
21812
  }
21641
21813
  let agentConfig = null;
21642
21814
  if (account) {
21643
- const agentDir = resolve27(account.accountDir, "agents", agentSlug);
21644
- if (!existsSync32(agentDir) || !existsSync32(resolve27(agentDir, "config.json"))) {
21815
+ const agentDir = resolve28(account.accountDir, "agents", agentSlug);
21816
+ if (!existsSync32(agentDir) || !existsSync32(resolve28(agentDir, "config.json"))) {
21645
21817
  return c.json({ error: "Agent not found" }, 404);
21646
21818
  }
21647
21819
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -22087,8 +22259,8 @@ function startGraphHealthTimer() {
22087
22259
 
22088
22260
  // app/lib/file-watcher.ts
22089
22261
  import * as fsp2 from "fs/promises";
22090
- import { resolve as resolve28, sep as sep8 } from "path";
22091
- var ACCOUNT_UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22262
+ import { resolve as resolve29, sep as sep8 } from "path";
22263
+ var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22092
22264
  var DEFAULT_COALESCE_MS = 500;
22093
22265
  var ROOTS = ["accounts"];
22094
22266
  function _routeEvent(rootName, filename) {
@@ -22096,7 +22268,7 @@ function _routeEvent(rootName, filename) {
22096
22268
  const segs = filename.split(sep8).filter(Boolean);
22097
22269
  if (segs.length < 2) return null;
22098
22270
  const accountId = segs[0];
22099
- if (!ACCOUNT_UUID_RE3.test(accountId)) return null;
22271
+ if (!ACCOUNT_UUID_RE4.test(accountId)) return null;
22100
22272
  return { accountId, relativePath: `${rootName}/${segs.join("/")}` };
22101
22273
  }
22102
22274
  async function startFileWatcher(opts = {}) {
@@ -22106,7 +22278,7 @@ async function startFileWatcher(opts = {}) {
22106
22278
  const dropFn = opts.drop ?? dropFileIndex;
22107
22279
  for (const r of ROOTS) {
22108
22280
  try {
22109
- await fsp2.mkdir(resolve28(dataRoot, r), { recursive: true });
22281
+ await fsp2.mkdir(resolve29(dataRoot, r), { recursive: true });
22110
22282
  } catch (err) {
22111
22283
  console.error(
22112
22284
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -22127,7 +22299,7 @@ async function startFileWatcher(opts = {}) {
22127
22299
  timers.set(relativePath, t);
22128
22300
  }
22129
22301
  async function runHook(relativePath, accountId) {
22130
- const absolute = resolve28(dataRoot, relativePath);
22302
+ const absolute = resolve29(dataRoot, relativePath);
22131
22303
  let exists = false;
22132
22304
  try {
22133
22305
  const st = await fsp2.stat(absolute);
@@ -22151,7 +22323,7 @@ async function startFileWatcher(opts = {}) {
22151
22323
  }
22152
22324
  }
22153
22325
  async function watchRoot(rootName) {
22154
- const absRoot = resolve28(dataRoot, rootName);
22326
+ const absRoot = resolve29(dataRoot, rootName);
22155
22327
  try {
22156
22328
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
22157
22329
  for await (const event of iter) {
@@ -22190,8 +22362,8 @@ async function startFileWatcher(opts = {}) {
22190
22362
 
22191
22363
  // app/lib/migrate-uploads.ts
22192
22364
  import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
22193
- import { dirname as dirname12, relative as relative6, resolve as resolve29 } from "path";
22194
- var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22365
+ import { dirname as dirname12, relative as relative6, resolve as resolve30 } from "path";
22366
+ var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22195
22367
  async function walkFiles(dir) {
22196
22368
  const out = [];
22197
22369
  let entries;
@@ -22201,7 +22373,7 @@ async function walkFiles(dir) {
22201
22373
  return out;
22202
22374
  }
22203
22375
  for (const e of entries) {
22204
- const abs = resolve29(dir, e.name);
22376
+ const abs = resolve30(dir, e.name);
22205
22377
  if (e.isDirectory()) {
22206
22378
  out.push(...await walkFiles(abs));
22207
22379
  } else if (e.isFile()) {
@@ -22221,7 +22393,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
22221
22393
  let moved = 0;
22222
22394
  for (const oldAbs of files) {
22223
22395
  const suffix = relative6(srcDir, oldAbs);
22224
- const newAbs = resolve29(destDir, suffix);
22396
+ const newAbs = resolve30(destDir, suffix);
22225
22397
  await mkdir5(dirname12(newAbs), { recursive: true });
22226
22398
  await rename2(oldAbs, newAbs);
22227
22399
  moved++;
@@ -22248,7 +22420,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
22248
22420
  }
22249
22421
  async function migrateUploads(opts = {}) {
22250
22422
  const dataRoot = opts.dataRoot ?? DATA_ROOT;
22251
- const oldRoot = resolve29(dataRoot, "uploads");
22423
+ const oldRoot = resolve30(dataRoot, "uploads");
22252
22424
  let topEntries;
22253
22425
  try {
22254
22426
  topEntries = await readdir5(oldRoot, { withFileTypes: true });
@@ -22267,10 +22439,10 @@ async function migrateUploads(opts = {}) {
22267
22439
  try {
22268
22440
  for (const entry of topEntries) {
22269
22441
  const name = entry.name;
22270
- if (ACCOUNT_UUID_RE4.test(name)) {
22442
+ if (ACCOUNT_UUID_RE5.test(name)) {
22271
22443
  moved += await relocateTree(
22272
- resolve29(oldRoot, name),
22273
- resolve29(dataRoot, "accounts", name, "uploads"),
22444
+ resolve30(oldRoot, name),
22445
+ resolve30(dataRoot, "accounts", name, "uploads"),
22274
22446
  dataRoot,
22275
22447
  name,
22276
22448
  session
@@ -22282,8 +22454,8 @@ async function migrateUploads(opts = {}) {
22282
22454
  continue;
22283
22455
  }
22284
22456
  moved += await relocateTree(
22285
- resolve29(oldRoot, "public"),
22286
- resolve29(dataRoot, "accounts", installAccountId, "uploads", "public"),
22457
+ resolve30(oldRoot, "public"),
22458
+ resolve30(dataRoot, "accounts", installAccountId, "uploads", "public"),
22287
22459
  dataRoot,
22288
22460
  null,
22289
22461
  // public uploads carry no graph nodes
@@ -22314,7 +22486,7 @@ async function migrateUploads(opts = {}) {
22314
22486
  // app/lib/migrate-admin-webchat-sidecars.ts
22315
22487
  import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
22316
22488
  import { existsSync as existsSync33 } from "fs";
22317
- import { join as join34 } from "path";
22489
+ import { join as join35 } from "path";
22318
22490
  var ADMIN_ROLE2 = "admin";
22319
22491
  var WEBCHAT_CHANNEL2 = "webchat";
22320
22492
  var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
@@ -22359,7 +22531,7 @@ async function collectLiveSidecars(projectsRoot) {
22359
22531
  }
22360
22532
  for (const slug of slugs) {
22361
22533
  if (!slug.isDirectory()) continue;
22362
- const slugDir = join34(projectsRoot, slug.name);
22534
+ const slugDir = join35(projectsRoot, slug.name);
22363
22535
  let entries;
22364
22536
  try {
22365
22537
  entries = await readdir6(slugDir, { withFileTypes: true });
@@ -22368,9 +22540,9 @@ async function collectLiveSidecars(projectsRoot) {
22368
22540
  }
22369
22541
  for (const entry of entries) {
22370
22542
  if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
22371
- out.push(join34(slugDir, entry.name));
22543
+ out.push(join35(slugDir, entry.name));
22372
22544
  } else if (entry.isDirectory() && entry.name === "subagents") {
22373
- const subDir = join34(slugDir, entry.name);
22545
+ const subDir = join35(slugDir, entry.name);
22374
22546
  let subs;
22375
22547
  try {
22376
22548
  subs = await readdir6(subDir, { withFileTypes: true });
@@ -22378,7 +22550,7 @@ async function collectLiveSidecars(projectsRoot) {
22378
22550
  continue;
22379
22551
  }
22380
22552
  for (const s of subs) {
22381
- if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join34(subDir, s.name));
22553
+ if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join35(subDir, s.name));
22382
22554
  }
22383
22555
  }
22384
22556
  }
@@ -22390,7 +22562,7 @@ function shortId(path2) {
22390
22562
  return base.slice(0, 8);
22391
22563
  }
22392
22564
  async function migrateAdminWebchatSidecars(opts = {}) {
22393
- const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join34(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
22565
+ const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join35(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
22394
22566
  const usersFile = opts.usersFile ?? USERS_FILE;
22395
22567
  const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
22396
22568
  const resolveName = opts.resolveName ?? defaultResolveName;
@@ -23369,16 +23541,16 @@ var WebchatGateway = class _WebchatGateway {
23369
23541
  * The public /api/chat route awaits this to return the reply on the same SSE
23370
23542
  * response, preserving the pre-756 POST→single-blob browser contract. */
23371
23543
  awaitReply(key, timeoutMs) {
23372
- return new Promise((resolve34) => {
23544
+ return new Promise((resolve35) => {
23373
23545
  const timer2 = setTimeout(() => {
23374
23546
  this.replyAwaiters.delete(key);
23375
- resolve34({ timeout: true });
23547
+ resolve35({ timeout: true });
23376
23548
  }, timeoutMs);
23377
23549
  if (timer2.unref) timer2.unref();
23378
23550
  this.replyAwaiters.set(key, (r) => {
23379
23551
  clearTimeout(timer2);
23380
23552
  this.replyAwaiters.delete(key);
23381
- resolve34(r);
23553
+ resolve35(r);
23382
23554
  });
23383
23555
  });
23384
23556
  }
@@ -23389,11 +23561,11 @@ var WebchatGateway = class _WebchatGateway {
23389
23561
  * terminal dialog stays answerable). */
23390
23562
  awaitPermissionVerdict(p, timeoutMs) {
23391
23563
  const k = _WebchatGateway.promptKey(p.key, p.requestId);
23392
- return new Promise((resolve34) => {
23564
+ return new Promise((resolve35) => {
23393
23565
  this.pendingPrompts.get(k)?.resolve({ timeout: true });
23394
23566
  const timer2 = setTimeout(() => {
23395
23567
  this.pendingPrompts.delete(k);
23396
- resolve34({ timeout: true });
23568
+ resolve35({ timeout: true });
23397
23569
  }, timeoutMs);
23398
23570
  if (timer2.unref) timer2.unref();
23399
23571
  this.pendingPrompts.set(k, {
@@ -23402,7 +23574,7 @@ var WebchatGateway = class _WebchatGateway {
23402
23574
  resolve: (r) => {
23403
23575
  clearTimeout(timer2);
23404
23576
  this.pendingPrompts.delete(k);
23405
- resolve34(r);
23577
+ resolve35(r);
23406
23578
  }
23407
23579
  });
23408
23580
  console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
@@ -24398,7 +24570,7 @@ function buildTelegramSpawnRequest(input) {
24398
24570
  // app/lib/telegram/outbound/send-document.ts
24399
24571
  import { realpathSync as realpathSync7 } from "fs";
24400
24572
  import { readFile as readFile7, stat as stat7 } from "fs/promises";
24401
- import { resolve as resolve30, basename as basename11 } from "path";
24573
+ import { resolve as resolve31, basename as basename11 } from "path";
24402
24574
  var TAG42 = "[telegram:outbound]";
24403
24575
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
24404
24576
  async function sendTelegramDocument(input) {
@@ -24409,7 +24581,7 @@ async function sendTelegramDocument(input) {
24409
24581
  if (!maxyAccountId || !platformRoot3) {
24410
24582
  return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
24411
24583
  }
24412
- const accountDir = resolve30(platformRoot3, "..", "data/accounts", maxyAccountId);
24584
+ const accountDir = resolve31(platformRoot3, "..", "data/accounts", maxyAccountId);
24413
24585
  let resolvedPath;
24414
24586
  try {
24415
24587
  resolvedPath = realpathSync7(filePath);
@@ -24536,12 +24708,12 @@ function startTelegramNativeFileFollower(input) {
24536
24708
  }
24537
24709
 
24538
24710
  // server/telegram-descriptor.ts
24539
- import { resolve as resolve31, join as join35 } from "path";
24711
+ import { resolve as resolve32, join as join36 } from "path";
24540
24712
  function telegramGatewayUrl() {
24541
24713
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
24542
24714
  }
24543
24715
  function telegramServerPath() {
24544
- return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, ".."), "services/telegram-channel/dist/server.js");
24716
+ return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve32(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."), "services/telegram-channel/dist/server.js");
24545
24717
  }
24546
24718
 
24547
24719
  // app/lib/channel-pty-bridge/public-session-end-review.ts
@@ -24803,8 +24975,8 @@ function broadcastAdminShutdown(reason) {
24803
24975
 
24804
24976
  // ../lib/entitlement/src/index.ts
24805
24977
  import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
24806
- import { existsSync as existsSync34, readFileSync as readFileSync35, statSync as statSync13 } from "fs";
24807
- import { resolve as resolve32 } from "path";
24978
+ import { existsSync as existsSync34, readFileSync as readFileSync36, statSync as statSync13 } from "fs";
24979
+ import { resolve as resolve33 } from "path";
24808
24980
 
24809
24981
  // ../lib/entitlement/src/canonicalize.ts
24810
24982
  function canonicalize(value) {
@@ -24839,7 +25011,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
24839
25011
  var GRACE_DAYS = 7;
24840
25012
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
24841
25013
  function pubkeyPath(brand) {
24842
- return resolve32(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
25014
+ return resolve33(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
24843
25015
  }
24844
25016
  var memo = null;
24845
25017
  function memoKey(mtimeMs, account) {
@@ -24851,7 +25023,7 @@ function resolveEntitlement(brand, account) {
24851
25023
  if (brand.commercialMode !== true) {
24852
25024
  return logResolved(implicitTrust(account), null);
24853
25025
  }
24854
- const entitlementPath = resolve32(brand.configDir, "entitlement.json");
25026
+ const entitlementPath = resolve33(brand.configDir, "entitlement.json");
24855
25027
  if (!existsSync34(entitlementPath)) {
24856
25028
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
24857
25029
  }
@@ -24867,7 +25039,7 @@ function resolveEntitlement(brand, account) {
24867
25039
  function verifyAndResolve(brand, entitlementPath, account) {
24868
25040
  let pubkeyPem;
24869
25041
  try {
24870
- pubkeyPem = readFileSync35(pubkeyPath(brand), "utf-8");
25042
+ pubkeyPem = readFileSync36(pubkeyPath(brand), "utf-8");
24871
25043
  } catch (err) {
24872
25044
  return logResolved(anonymousFallback("pubkey-missing"), {
24873
25045
  reason: "pubkey-missing"
@@ -24881,7 +25053,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
24881
25053
  }
24882
25054
  let envelope;
24883
25055
  try {
24884
- envelope = JSON.parse(readFileSync35(entitlementPath, "utf-8"));
25056
+ envelope = JSON.parse(readFileSync36(entitlementPath, "utf-8"));
24885
25057
  } catch {
24886
25058
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
24887
25059
  }
@@ -25042,14 +25214,14 @@ function clientFrom(c) {
25042
25214
  );
25043
25215
  }
25044
25216
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
25045
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join36(PLATFORM_ROOT8, "config", "brand.json") : "";
25217
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join37(PLATFORM_ROOT8, "config", "brand.json") : "";
25046
25218
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
25047
25219
  if (BRAND_JSON_PATH && !existsSync35(BRAND_JSON_PATH)) {
25048
25220
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
25049
25221
  }
25050
25222
  if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
25051
25223
  try {
25052
- const parsed = JSON.parse(readFileSync36(BRAND_JSON_PATH, "utf-8"));
25224
+ const parsed = JSON.parse(readFileSync37(BRAND_JSON_PATH, "utf-8"));
25053
25225
  BRAND = { ...BRAND, ...parsed };
25054
25226
  } catch (err) {
25055
25227
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -25081,11 +25253,11 @@ var brandLoginOpts = {
25081
25253
  appleTouchIconPath: brandAppIcon512Path,
25082
25254
  themeColor: BRAND.defaultColors?.primary
25083
25255
  };
25084
- var ALIAS_DOMAINS_PATH = join36(homedir4(), BRAND.configDir, "alias-domains.json");
25256
+ var ALIAS_DOMAINS_PATH = join37(homedir4(), BRAND.configDir, "alias-domains.json");
25085
25257
  function loadAliasDomains() {
25086
25258
  try {
25087
25259
  if (!existsSync35(ALIAS_DOMAINS_PATH)) return null;
25088
- const parsed = JSON.parse(readFileSync36(ALIAS_DOMAINS_PATH, "utf-8"));
25260
+ const parsed = JSON.parse(readFileSync37(ALIAS_DOMAINS_PATH, "utf-8"));
25089
25261
  if (!Array.isArray(parsed)) {
25090
25262
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
25091
25263
  return null;
@@ -25148,7 +25320,7 @@ async function recordPassiveDispatch(input) {
25148
25320
  var waGateway = new WaGateway({
25149
25321
  fetchStandingRules: fetchAccountStandingRules,
25150
25322
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
25151
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
25323
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
25152
25324
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
25153
25325
  // path-validation scope) is the sender's effective SESSION account, resolved
25154
25326
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -25163,7 +25335,7 @@ var waGateway = new WaGateway({
25163
25335
  caption,
25164
25336
  accountId,
25165
25337
  maxyAccountId,
25166
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."))
25338
+ platformRoot: resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."))
25167
25339
  });
25168
25340
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
25169
25341
  },
@@ -25761,8 +25933,8 @@ app61.get("/agent-assets/:slug/:filename", (c) => {
25761
25933
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
25762
25934
  return c.text("Not found", 404);
25763
25935
  }
25764
- const filePath = resolve33(account.accountDir, "agents", slug, "assets", filename);
25765
- const expectedDir = resolve33(account.accountDir, "agents", slug, "assets");
25936
+ const filePath = resolve34(account.accountDir, "agents", slug, "assets", filename);
25937
+ const expectedDir = resolve34(account.accountDir, "agents", slug, "assets");
25766
25938
  if (!filePath.startsWith(expectedDir + "/")) {
25767
25939
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
25768
25940
  return c.text("Forbidden", 403);
@@ -25774,7 +25946,7 @@ app61.get("/agent-assets/:slug/:filename", (c) => {
25774
25946
  const ext = "." + filename.split(".").pop()?.toLowerCase();
25775
25947
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
25776
25948
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
25777
- const body = readFileSync36(filePath);
25949
+ const body = readFileSync37(filePath);
25778
25950
  return c.body(body, 200, {
25779
25951
  "Content-Type": contentType,
25780
25952
  "Cache-Control": "public, max-age=3600"
@@ -25791,8 +25963,8 @@ app61.get("/generated/:filename", (c) => {
25791
25963
  console.error(`[generated] serve file=${filename} status=404`);
25792
25964
  return c.text("Not found", 404);
25793
25965
  }
25794
- const filePath = resolve33(account.accountDir, "generated", filename);
25795
- const expectedDir = resolve33(account.accountDir, "generated");
25966
+ const filePath = resolve34(account.accountDir, "generated", filename);
25967
+ const expectedDir = resolve34(account.accountDir, "generated");
25796
25968
  if (!filePath.startsWith(expectedDir + "/")) {
25797
25969
  console.error(`[generated] serve file=${filename} status=403`);
25798
25970
  return c.text("Forbidden", 403);
@@ -25804,7 +25976,7 @@ app61.get("/generated/:filename", (c) => {
25804
25976
  const ext = "." + filename.split(".").pop()?.toLowerCase();
25805
25977
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
25806
25978
  console.log(`[generated] serve file=${filename} status=200`);
25807
- const body = readFileSync36(filePath);
25979
+ const body = readFileSync37(filePath);
25808
25980
  return c.body(body, 200, {
25809
25981
  "Content-Type": contentType,
25810
25982
  "Cache-Control": "public, max-age=86400"
@@ -25819,7 +25991,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
25819
25991
  var brandIconPath = "/brand/maxy-monochrome.png";
25820
25992
  if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
25821
25993
  try {
25822
- const fullBrand = JSON.parse(readFileSync36(BRAND_JSON_PATH, "utf-8"));
25994
+ const fullBrand = JSON.parse(readFileSync37(BRAND_JSON_PATH, "utf-8"));
25823
25995
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
25824
25996
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
25825
25997
  } catch {
@@ -25846,11 +26018,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
25846
26018
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
25847
26019
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
25848
26020
  var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
25849
- (p) => existsSync35(resolve33(process.cwd(), "public", p.replace(/^\//, "")))
26021
+ (p) => existsSync35(resolve34(process.cwd(), "public", p.replace(/^\//, "")))
25850
26022
  );
25851
26023
  var SW_SOURCE = (() => {
25852
26024
  try {
25853
- return readFileSync36(resolve33(process.cwd(), "public", "sw.js"), "utf-8");
26025
+ return readFileSync37(resolve34(process.cwd(), "public", "sw.js"), "utf-8");
25854
26026
  } catch {
25855
26027
  return null;
25856
26028
  }
@@ -25858,9 +26030,9 @@ var SW_SOURCE = (() => {
25858
26030
  function readInstalledVersion() {
25859
26031
  try {
25860
26032
  if (!PLATFORM_ROOT8) return "unknown";
25861
- const versionFile = join36(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
26033
+ const versionFile = join37(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
25862
26034
  if (!existsSync35(versionFile)) return "unknown";
25863
- const content = readFileSync36(versionFile, "utf-8").trim();
26035
+ const content = readFileSync37(versionFile, "utf-8").trim();
25864
26036
  return content || "unknown";
25865
26037
  } catch {
25866
26038
  return "unknown";
@@ -25901,7 +26073,7 @@ var clientErrorReporterScript = `<script>
25901
26073
  function cachedHtml(file) {
25902
26074
  let html = htmlCache.get(file);
25903
26075
  if (!html) {
25904
- html = readFileSync36(resolve33(process.cwd(), "public", file), "utf-8");
26076
+ html = readFileSync37(resolve34(process.cwd(), "public", file), "utf-8");
25905
26077
  const productNameEsc = escapeHtml(BRAND.productName);
25906
26078
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
25907
26079
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -25918,13 +26090,13 @@ ${clientErrorReporterScript}
25918
26090
  return html;
25919
26091
  }
25920
26092
  function loadBrandingCache(agentSlug) {
25921
- const configDir2 = join36(homedir4(), BRAND.configDir);
26093
+ const configDir2 = join37(homedir4(), BRAND.configDir);
25922
26094
  try {
25923
26095
  const accountId = getDefaultAccountId();
25924
26096
  if (!accountId) return null;
25925
- const cachePath = join36(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
26097
+ const cachePath = join37(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
25926
26098
  if (!existsSync35(cachePath)) return null;
25927
- return JSON.parse(readFileSync36(cachePath, "utf-8"));
26099
+ return JSON.parse(readFileSync37(cachePath, "utf-8"));
25928
26100
  } catch {
25929
26101
  return null;
25930
26102
  }
@@ -25941,11 +26113,11 @@ var brandedHtmlCache = /* @__PURE__ */ new Map();
25941
26113
  function brandedPublicHtml(agentSlug) {
25942
26114
  const baseHtml = cachedHtml("public.html");
25943
26115
  if (!agentSlug) return baseHtml;
25944
- const cached2 = brandedHtmlCache.get(agentSlug);
26116
+ const cached3 = brandedHtmlCache.get(agentSlug);
25945
26117
  const branding = loadBrandingCache(agentSlug);
25946
26118
  if (!branding) return baseHtml;
25947
26119
  const brandHash = JSON.stringify(branding).length;
25948
- if (cached2 && cached2.mtime === brandHash) return cached2.html;
26120
+ if (cached3 && cached3.mtime === brandHash) return cached3.html;
25949
26121
  const title = escapeHtml(branding.name);
25950
26122
  const description = branding.tagline ? escapeHtml(branding.tagline) : "";
25951
26123
  const themeColor = branding.primaryColor || "";
@@ -26019,7 +26191,7 @@ app61.use("/vnc-popout.html", logViewerFetch);
26019
26191
  app61.get("/vnc-popout.html", (c) => {
26020
26192
  let html = htmlCache.get("vnc-popout.html");
26021
26193
  if (!html) {
26022
- html = readFileSync36(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
26194
+ html = readFileSync37(resolve34(process.cwd(), "public", "vnc-popout.html"), "utf-8");
26023
26195
  const name = escapeHtml(BRAND.productName);
26024
26196
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
26025
26197
  html = html.replace("</head>", ` ${brandScript}
@@ -26151,8 +26323,8 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
26151
26323
  var httpServer = serve({ fetch: app61.fetch, port, hostname });
26152
26324
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
26153
26325
  {
26154
- const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
26155
- const reconcileScript = resolve33(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
26326
+ const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
26327
+ const reconcileScript = resolve34(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
26156
26328
  const RECONCILE_INTERVAL_MS = 12e4;
26157
26329
  const runReconcile = () => {
26158
26330
  if (!existsSync35(reconcileScript)) return;
@@ -26173,8 +26345,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
26173
26345
  loop.unref();
26174
26346
  }
26175
26347
  {
26176
- const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
26177
- const publishScript = resolve33(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
26348
+ const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
26349
+ const publishScript = resolve34(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
26178
26350
  const PUBLISH_INTERVAL_MS = 3e5;
26179
26351
  const currentAccount = () => {
26180
26352
  try {
@@ -26203,21 +26375,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
26203
26375
  }
26204
26376
  };
26205
26377
  const auditSnapshotAge = (account) => {
26206
- const availPath = resolve33(account.accountDir, "calendar-availability.json");
26378
+ const availPath = resolve34(account.accountDir, "calendar-availability.json");
26207
26379
  let hasBookingSite = false;
26208
26380
  try {
26209
26381
  if (existsSync35(availPath)) {
26210
- const cfg = JSON.parse(readFileSync36(availPath, "utf-8"));
26382
+ const cfg = JSON.parse(readFileSync37(availPath, "utf-8"));
26211
26383
  hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
26212
26384
  }
26213
26385
  } catch {
26214
26386
  }
26215
26387
  if (!hasBookingSite) return;
26216
- const statePath = resolve33(account.accountDir, "state", "booking-availability", "last-publish.json");
26388
+ const statePath = resolve34(account.accountDir, "state", "booking-availability", "last-publish.json");
26217
26389
  let lastSuccessAt = null;
26218
26390
  if (existsSync35(statePath)) {
26219
26391
  try {
26220
- const rec = JSON.parse(readFileSync36(statePath, "utf-8"));
26392
+ const rec = JSON.parse(readFileSync37(statePath, "utf-8"));
26221
26393
  lastSuccessAt = rec.lastSuccessAt ?? null;
26222
26394
  } catch {
26223
26395
  console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
@@ -26241,8 +26413,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
26241
26413
  }
26242
26414
  startTimeEntryCensus(() => getSession());
26243
26415
  {
26244
- const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
26245
- const auditScript = resolve33(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
26416
+ const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..");
26417
+ const auditScript = resolve34(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
26246
26418
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
26247
26419
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
26248
26420
  const runConnectorAudit = () => {
@@ -26360,7 +26532,7 @@ async function runAdminUserReconcileTick() {
26360
26532
  console.error("[adminuser-self-heal] skip reason=no-users-file");
26361
26533
  return;
26362
26534
  }
26363
- const usersRaw = readFileSync36(USERS_FILE, "utf-8").trim();
26535
+ const usersRaw = readFileSync37(USERS_FILE, "utf-8").trim();
26364
26536
  if (!usersRaw) {
26365
26537
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
26366
26538
  return;
@@ -26390,7 +26562,7 @@ if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer
26390
26562
  var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
26391
26563
  function countUsersRows() {
26392
26564
  if (!existsSync35(USERS_FILE)) return 0;
26393
- const raw = readFileSync36(USERS_FILE, "utf-8").trim();
26565
+ const raw = readFileSync37(USERS_FILE, "utf-8").trim();
26394
26566
  if (!raw) return 0;
26395
26567
  const users = JSON.parse(raw);
26396
26568
  return users.filter((u) => typeof u.userId === "string").length;
@@ -26510,7 +26682,7 @@ if (bootAccountConfig?.whatsapp) {
26510
26682
  }
26511
26683
  init({
26512
26684
  configDir: configDirForWhatsApp,
26513
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..")),
26685
+ platformRoot: resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, "..")),
26514
26686
  accountConfig: bootAccountConfig,
26515
26687
  onMessage: async (msg) => {
26516
26688
  if (msg.isOwnerMirror) {