@rubytech/create-maxy-code 0.1.190 → 0.1.191

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 (24) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/docs/references/admin-ui.md +16 -0
  3. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.d.ts +9 -0
  4. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.d.ts.map +1 -1
  5. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js +1 -1
  6. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js.map +1 -1
  7. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +9 -0
  8. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  9. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +2 -0
  10. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +21 -0
  11. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  12. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +106 -1
  13. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  14. package/payload/server/public/assets/{admin-Cv2A5vnQ.js → admin-DFxXLXfg.js} +1 -1
  15. package/payload/server/public/assets/{data-DIa-MKNj.js → data-DtYcqL1G.js} +1 -1
  16. package/payload/server/public/assets/{graph-Y5y3kw6J.js → graph-C-XPyGsO.js} +1 -1
  17. package/payload/server/public/assets/graph-labels-CZin3myX.js +1 -0
  18. package/payload/server/public/assets/{page-BCCqlOmj.js → page-CKlvbjKn.js} +1 -1
  19. package/payload/server/public/assets/{page-DwNvJOvr.js → page-DSj21hpG.js} +1 -1
  20. package/payload/server/public/data.html +3 -3
  21. package/payload/server/public/graph.html +3 -3
  22. package/payload/server/public/index.html +4 -4
  23. package/payload/server/server.js +263 -119
  24. package/payload/server/public/assets/graph-labels-BIRCh328.js +0 -1
@@ -816,7 +816,7 @@ var serveStatic = (options = { root: "" }) => {
816
816
 
817
817
  // server/index.ts
818
818
  import { readFileSync as readFileSync20, existsSync as existsSync23, watchFile } from "fs";
819
- import { resolve as resolve23, join as join15, basename as basename5 } from "path";
819
+ import { resolve as resolve24, join as join15, basename as basename5 } from "path";
820
820
  import { homedir as homedir2 } from "os";
821
821
  import { monitorEventLoopDelay } from "perf_hooks";
822
822
 
@@ -1274,7 +1274,7 @@ var credsSaveQueue = Promise.resolve();
1274
1274
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1275
1275
  console.error(`${TAG2} draining credential save queue\u2026`);
1276
1276
  const timer2 = new Promise(
1277
- (resolve24) => setTimeout(() => resolve24("timeout"), timeoutMs)
1277
+ (resolve25) => setTimeout(() => resolve25("timeout"), timeoutMs)
1278
1278
  );
1279
1279
  const result = await Promise.race([
1280
1280
  credsSaveQueue.then(() => "drained"),
@@ -1402,11 +1402,11 @@ async function createWaSocket(opts) {
1402
1402
  return sock;
1403
1403
  }
1404
1404
  async function waitForConnection(sock) {
1405
- return new Promise((resolve24, reject) => {
1405
+ return new Promise((resolve25, reject) => {
1406
1406
  const handler = (update) => {
1407
1407
  if (update.connection === "open") {
1408
1408
  sock.ev.off("connection.update", handler);
1409
- resolve24();
1409
+ resolve25();
1410
1410
  }
1411
1411
  if (update.connection === "close") {
1412
1412
  sock.ev.off("connection.update", handler);
@@ -1520,14 +1520,14 @@ ${inspected}`;
1520
1520
  return inspect2(err, INSPECT_OPTS2);
1521
1521
  }
1522
1522
  function withTimeout(label, promise, timeoutMs) {
1523
- return new Promise((resolve24, reject) => {
1523
+ return new Promise((resolve25, reject) => {
1524
1524
  const timer2 = setTimeout(() => {
1525
1525
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1526
1526
  }, timeoutMs);
1527
1527
  promise.then(
1528
1528
  (value) => {
1529
1529
  clearTimeout(timer2);
1530
- resolve24(value);
1530
+ resolve25(value);
1531
1531
  },
1532
1532
  (err) => {
1533
1533
  clearTimeout(timer2);
@@ -2062,8 +2062,8 @@ async function persistWhatsAppMessage(input) {
2062
2062
  const { givenName, familyName } = splitName(input.pushName);
2063
2063
  const prev = sessionWriteLocks.get(input.cacheKey);
2064
2064
  let release;
2065
- const mine = new Promise((resolve24) => {
2066
- release = resolve24;
2065
+ const mine = new Promise((resolve25) => {
2066
+ release = resolve25;
2067
2067
  });
2068
2068
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2069
2069
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3099,11 +3099,11 @@ async function connectWithReconnect(conn) {
3099
3099
  console.error(
3100
3100
  `${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3101
3101
  );
3102
- await new Promise((resolve24) => {
3103
- const timer2 = setTimeout(resolve24, delay);
3102
+ await new Promise((resolve25) => {
3103
+ const timer2 = setTimeout(resolve25, delay);
3104
3104
  conn.abortController.signal.addEventListener("abort", () => {
3105
3105
  clearTimeout(timer2);
3106
- resolve24();
3106
+ resolve25();
3107
3107
  }, { once: true });
3108
3108
  });
3109
3109
  }
@@ -3111,16 +3111,16 @@ async function connectWithReconnect(conn) {
3111
3111
  }
3112
3112
  }
3113
3113
  function waitForDisconnectEvent(conn) {
3114
- return new Promise((resolve24) => {
3114
+ return new Promise((resolve25) => {
3115
3115
  if (!conn.sock) {
3116
- resolve24();
3116
+ resolve25();
3117
3117
  return;
3118
3118
  }
3119
3119
  const sock = conn.sock;
3120
3120
  const handler = (update) => {
3121
3121
  if (update.connection === "close") {
3122
3122
  sock.ev.off("connection.update", handler);
3123
- resolve24();
3123
+ resolve25();
3124
3124
  }
3125
3125
  };
3126
3126
  sock.ev.on("connection.update", handler);
@@ -3382,8 +3382,8 @@ async function handleInboundMessage(conn, msg) {
3382
3382
  const conversationKey = isGroup ? remoteJid : senderPhone;
3383
3383
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
3384
3384
  let resolvePending;
3385
- const sttPending = new Promise((resolve24) => {
3386
- resolvePending = resolve24;
3385
+ const sttPending = new Promise((resolve25) => {
3386
+ resolvePending = resolve25;
3387
3387
  });
3388
3388
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
3389
3389
  try {
@@ -3787,20 +3787,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
3787
3787
 
3788
3788
  // server/routes/health.ts
3789
3789
  function checkPort(port2, timeoutMs = 500) {
3790
- return new Promise((resolve24) => {
3790
+ return new Promise((resolve25) => {
3791
3791
  const socket = createConnection2(port2, "127.0.0.1");
3792
3792
  socket.setTimeout(timeoutMs);
3793
3793
  socket.once("connect", () => {
3794
3794
  socket.destroy();
3795
- resolve24(true);
3795
+ resolve25(true);
3796
3796
  });
3797
3797
  socket.once("error", () => {
3798
3798
  socket.destroy();
3799
- resolve24(false);
3799
+ resolve25(false);
3800
3800
  });
3801
3801
  socket.once("timeout", () => {
3802
3802
  socket.destroy();
3803
- resolve24(false);
3803
+ resolve25(false);
3804
3804
  });
3805
3805
  });
3806
3806
  }
@@ -4536,12 +4536,12 @@ async function dispatchOnce(input) {
4536
4536
  });
4537
4537
  if (!entry) return { error: "spawn-failed" };
4538
4538
  entry.lastInboundAt = Date.now();
4539
- let resolve24;
4539
+ let resolve25;
4540
4540
  const turnPromise = new Promise((r) => {
4541
- resolve24 = r;
4541
+ resolve25 = r;
4542
4542
  });
4543
4543
  const listener = (text) => {
4544
- resolve24(text);
4544
+ resolve25(text);
4545
4545
  };
4546
4546
  entry.subscribers.add(listener);
4547
4547
  const writeOk = await writeInput(entry, input.text);
@@ -4983,8 +4983,8 @@ async function startLogin(opts) {
4983
4983
  resetActiveLogin(accountId);
4984
4984
  let resolveQr = null;
4985
4985
  let rejectQr = null;
4986
- const qrPromise = new Promise((resolve24, reject) => {
4987
- resolveQr = resolve24;
4986
+ const qrPromise = new Promise((resolve25, reject) => {
4987
+ resolveQr = resolve25;
4988
4988
  rejectQr = reject;
4989
4989
  });
4990
4990
  const qrTimer = setTimeout(
@@ -8004,10 +8004,10 @@ function computeSpecialistDomains(accountId) {
8004
8004
  const resolveDesc = (qualified) => {
8005
8005
  if (!qualified.startsWith("mcp__")) return void 0;
8006
8006
  const rest = qualified.slice(5);
8007
- const sep6 = rest.indexOf("__");
8008
- if (sep6 < 0) return void 0;
8009
- const plugin = rest.slice(0, sep6);
8010
- const tool = rest.slice(sep6 + 2);
8007
+ const sep7 = rest.indexOf("__");
8008
+ if (sep7 < 0) return void 0;
8009
+ const plugin = rest.slice(0, sep7);
8010
+ const tool = rest.slice(sep7 + 2);
8011
8011
  let map = descByPlugin.get(plugin);
8012
8012
  if (!map) {
8013
8013
  const dir = pluginDirs.get(plugin);
@@ -8396,6 +8396,7 @@ import { realpathSync as realpathSync3 } from "fs";
8396
8396
  import { resolve as resolve12, normalize, sep as sep2, relative } from "path";
8397
8397
  var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve12(process.cwd(), "../platform");
8398
8398
  var DATA_ROOT = resolve12(PLATFORM_ROOT5, "..", "data");
8399
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve12(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
8399
8400
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
8400
8401
  var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
8401
8402
  function crossesForeignAccountPartition(relPath2, accountId) {
@@ -8406,17 +8407,17 @@ function crossesForeignAccountPartition(relPath2, accountId) {
8406
8407
  if (!ACCOUNT_UUID_RE.test(owner)) return false;
8407
8408
  return owner !== accountId;
8408
8409
  }
8409
- function resolveDataPath(raw) {
8410
+ function resolveUnderRoot(raw, rootAbs, rootLabel) {
8410
8411
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
8411
- const absolute = resolve12(DATA_ROOT, cleaned);
8412
- let dataRootReal;
8412
+ const absolute = resolve12(rootAbs, cleaned);
8413
+ let rootReal;
8413
8414
  try {
8414
- dataRootReal = realpathSync3(DATA_ROOT);
8415
+ rootReal = realpathSync3(rootAbs);
8415
8416
  } catch (err) {
8416
8417
  return {
8417
8418
  ok: false,
8418
8419
  status: 500,
8419
- error: `DATA_ROOT not accessible: ${err instanceof Error ? err.message : String(err)}`
8420
+ error: `${rootLabel} not accessible: ${err instanceof Error ? err.message : String(err)}`
8420
8421
  };
8421
8422
  }
8422
8423
  let resolvedReal;
@@ -8425,8 +8426,8 @@ function resolveDataPath(raw) {
8425
8426
  } catch (err) {
8426
8427
  const code = err.code;
8427
8428
  if (code === "ENOENT") {
8428
- if (absolute !== dataRootReal && !absolute.startsWith(dataRootReal + sep2)) {
8429
- return { ok: false, status: 403, error: "Path escapes DATA_ROOT", resolved: absolute };
8429
+ if (absolute !== rootReal && !absolute.startsWith(rootReal + sep2)) {
8430
+ return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: absolute };
8430
8431
  }
8431
8432
  return { ok: false, status: 404, error: "Not found" };
8432
8433
  }
@@ -8436,11 +8437,20 @@ function resolveDataPath(raw) {
8436
8437
  error: err instanceof Error ? err.message : String(err)
8437
8438
  };
8438
8439
  }
8439
- if (resolvedReal !== dataRootReal && !resolvedReal.startsWith(dataRootReal + sep2)) {
8440
- return { ok: false, status: 403, error: "Path escapes DATA_ROOT", resolved: resolvedReal };
8440
+ if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep2)) {
8441
+ return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: resolvedReal };
8442
+ }
8443
+ const relPath2 = relative(rootReal, resolvedReal) || ".";
8444
+ return { ok: true, absolute: resolvedReal, dataRootReal: rootReal, relative: relPath2 };
8445
+ }
8446
+ function resolveDataPath(raw) {
8447
+ return resolveUnderRoot(raw, DATA_ROOT, "DATA_ROOT");
8448
+ }
8449
+ function resolveClaudeUploadsPath(raw) {
8450
+ if (!CLAUDE_UPLOADS_ROOT) {
8451
+ return { ok: false, status: 404, error: "Not found" };
8441
8452
  }
8442
- const relPath2 = relative(dataRootReal, resolvedReal) || ".";
8443
- return { ok: true, absolute: resolvedReal, dataRootReal, relative: relPath2 };
8453
+ return resolveUnderRoot(raw, CLAUDE_UPLOADS_ROOT, "CLAUDE_UPLOADS_ROOT");
8444
8454
  }
8445
8455
 
8446
8456
  // ../lib/graph-trash/src/index.ts
@@ -9109,6 +9119,23 @@ function buildDisplayPath(relPath2, accountNames) {
9109
9119
  return dn ? { name: seg, displayName: dn } : { name: seg };
9110
9120
  });
9111
9121
  }
9122
+ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
9123
+ if (!attachmentId) return false;
9124
+ const session = getSession();
9125
+ try {
9126
+ const result = await session.run(
9127
+ `MATCH (d:KnowledgeDocument { accountId: $accountId, attachmentId: $attachmentId })
9128
+ RETURN count(d) > 0 AS owned`,
9129
+ { accountId, attachmentId }
9130
+ );
9131
+ return result.records[0]?.get("owned") === true;
9132
+ } catch (err) {
9133
+ console.error(`[data] kd-ownership-check-failed attachmentId="${attachmentId.slice(0, 8)}\u2026" err="${err instanceof Error ? err.message : String(err)}"`);
9134
+ return false;
9135
+ } finally {
9136
+ await session.close();
9137
+ }
9138
+ }
9112
9139
  var app15 = new Hono();
9113
9140
  app15.get("/", requireAdminSession, async (c) => {
9114
9141
  const cacheKey = c.var.cacheKey;
@@ -9180,15 +9207,26 @@ app15.get("/download", requireAdminSession, async (c) => {
9180
9207
  }
9181
9208
  const rawPath = c.req.query("path") ?? "";
9182
9209
  if (!rawPath) return c.json({ error: "path required" }, 400);
9183
- const resolution = resolveDataPath(rawPath);
9210
+ const root = c.req.query("root") ?? "data";
9211
+ if (root !== "data" && root !== "claude-uploads") {
9212
+ return c.json({ error: "invalid root" }, 400);
9213
+ }
9214
+ const resolution = root === "claude-uploads" ? resolveClaudeUploadsPath(rawPath) : resolveDataPath(rawPath);
9184
9215
  if (!resolution.ok) {
9185
9216
  if (resolution.status === 403) {
9186
- console.error(`[data] path-traversal-blocked requested="${rawPath}" resolved="${resolution.resolved ?? "n/a"}"`);
9217
+ console.error(`[data] path-traversal-blocked root="${root}" requested="${rawPath}" resolved="${resolution.resolved ?? "n/a"}"`);
9187
9218
  }
9188
9219
  return c.json({ error: resolution.error }, resolution.status);
9189
9220
  }
9190
9221
  const { absolute, relative: relPath2 } = resolution;
9191
- if (crossesForeignAccountPartition(relPath2, accountId)) {
9222
+ if (root === "claude-uploads") {
9223
+ const attachmentId = relPath2.split("/").filter(Boolean)[0] ?? "";
9224
+ const owned = await knowledgeDocOwnedByAccount(accountId, attachmentId);
9225
+ if (!owned) {
9226
+ console.error(`[data] account-scope-blocked root="claude-uploads" attachmentId="${attachmentId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
9227
+ return c.json({ error: "Not found" }, 404);
9228
+ }
9229
+ } else if (crossesForeignAccountPartition(relPath2, accountId)) {
9192
9230
  console.error(`[data] account-scope-blocked endpoint="/api/admin/files/download" path="${relPath2}" account=${accountId.slice(0, 8)}\u2026`);
9193
9231
  return c.json({ error: "Not found" }, 404);
9194
9232
  }
@@ -9201,7 +9239,7 @@ app15.get("/download", requireAdminSession, async (c) => {
9201
9239
  const mimeType = detectMimeType(absolute);
9202
9240
  const nodeStream = createReadStream2(absolute);
9203
9241
  const webStream = Readable2.toWeb(nodeStream);
9204
- console.error(`[data] file-download path="${relPath2}" size=${info.size}`);
9242
+ console.error(`[data] file-download root="${root}" path="${relPath2}" size=${info.size}`);
9205
9243
  const safeQuotedName = filename.replace(/[\r\n"\\]/g, "_");
9206
9244
  const encodedName = encodeURIComponent(filename);
9207
9245
  return new Response(webStream, {
@@ -11361,32 +11399,124 @@ var graph_default_view_default = app21;
11361
11399
  // server/routes/admin/sidebar-artefacts.ts
11362
11400
  import neo4j2 from "neo4j-driver";
11363
11401
  import { readFile as readFile5, readdir as readdir4, stat as stat5 } from "fs/promises";
11364
- import { resolve as resolve15, relative as relative3, isAbsolute, sep as sep5 } from "path";
11402
+ import { resolve as resolve16, relative as relative4, isAbsolute, sep as sep6 } from "path";
11365
11403
  import { existsSync as existsSync16 } from "fs";
11366
- var LIMIT = 50;
11367
- var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
11368
- var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
11369
- function toDataRootRelPath(absPath) {
11370
- if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep5)) return null;
11371
- return relative3(DATA_ROOT, absPath);
11372
- }
11373
- async function resolveDocAbsPath(accountId, attachmentId) {
11374
- if (!attachmentId) return null;
11375
- const accountDir = resolve15(ATTACHMENTS_ROOT, accountId);
11376
- const dir = resolve15(accountDir, attachmentId);
11404
+
11405
+ // app/lib/doc-source-resolve.ts
11406
+ import { readdirSync as readdirSync8, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
11407
+ import { relative as relative3, resolve as resolve15, sep as sep5 } from "path";
11408
+ function containedFile(absPath, root) {
11377
11409
  try {
11378
- validateFilePathInAccount(dir, accountDir);
11410
+ const real = realpathSync5(absPath);
11411
+ const rootReal = realpathSync5(root);
11412
+ if (real !== rootReal && !real.startsWith(rootReal + sep5)) return null;
11413
+ return statSync7(real).isFile() ? real : null;
11379
11414
  } catch {
11380
11415
  return null;
11381
11416
  }
11417
+ }
11418
+ function dataFileInDir(dir) {
11419
+ let entries;
11382
11420
  try {
11383
- const entries = await readdir4(dir);
11384
- const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
11385
- if (!dataFile) return null;
11386
- return resolve15(dir, dataFile);
11421
+ entries = readdirSync8(dir, { withFileTypes: true }).flatMap((e) => e.isFile() ? [e.name] : []);
11387
11422
  } catch {
11388
11423
  return null;
11389
11424
  }
11425
+ const file = entries.find((e) => !e.endsWith(".meta.json"));
11426
+ return file ? resolve15(dir, file) : null;
11427
+ }
11428
+ function mapToDownloadRoot(absPath, roots) {
11429
+ const underData = containedFile(absPath, roots.dataRoot);
11430
+ if (underData) {
11431
+ return { root: "data", relPath: relative3(realpathSync5(roots.dataRoot), underData), absReal: underData };
11432
+ }
11433
+ if (roots.claudeUploadsRoot) {
11434
+ const underClaude = containedFile(absPath, roots.claudeUploadsRoot);
11435
+ if (underClaude) {
11436
+ return {
11437
+ root: "claude-uploads",
11438
+ relPath: relative3(realpathSync5(roots.claudeUploadsRoot), underClaude),
11439
+ absReal: underClaude
11440
+ };
11441
+ }
11442
+ }
11443
+ return null;
11444
+ }
11445
+ function resolveDocDownload(input, roots) {
11446
+ const { accountId, attachmentId, name, sourcePath, sourceType } = input;
11447
+ if (sourcePath) {
11448
+ const mapped = mapToDownloadRoot(sourcePath, roots);
11449
+ if (mapped) {
11450
+ return { ok: true, absPath: mapped.absReal, root: mapped.root, relPath: mapped.relPath, via: "stored" };
11451
+ }
11452
+ }
11453
+ if (attachmentId) {
11454
+ const uploadsDir = resolve15(roots.attachmentsRoot, accountId, attachmentId);
11455
+ const file = dataFileInDir(uploadsDir);
11456
+ if (file) {
11457
+ const real = containedFile(file, roots.dataRoot);
11458
+ if (real) {
11459
+ return { ok: true, absPath: real, root: "data", relPath: relative3(realpathSync5(roots.dataRoot), real), via: "uploads" };
11460
+ }
11461
+ }
11462
+ }
11463
+ if (attachmentId && roots.claudeUploadsRoot) {
11464
+ const claudeDir = resolve15(roots.claudeUploadsRoot, attachmentId);
11465
+ const file = dataFileInDir(claudeDir);
11466
+ if (file) {
11467
+ const real = containedFile(file, roots.claudeUploadsRoot);
11468
+ if (real) {
11469
+ return {
11470
+ ok: true,
11471
+ absPath: real,
11472
+ root: "claude-uploads",
11473
+ relPath: relative3(realpathSync5(roots.claudeUploadsRoot), real),
11474
+ via: "claude-uploads"
11475
+ };
11476
+ }
11477
+ }
11478
+ }
11479
+ if (name) {
11480
+ const outputFile = resolve15(roots.accountsDir, accountId, "output", name);
11481
+ const real = containedFile(outputFile, roots.dataRoot);
11482
+ if (real) {
11483
+ return { ok: true, absPath: real, root: "data", relPath: relative3(realpathSync5(roots.dataRoot), real), via: "output" };
11484
+ }
11485
+ }
11486
+ return { ok: false, reason: sourceType === "web" ? "no-persisted-file" : "unresolved" };
11487
+ }
11488
+
11489
+ // server/routes/admin/sidebar-artefacts.ts
11490
+ var LIMIT = 50;
11491
+ var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
11492
+ var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
11493
+ function toDataRootRelPath(absPath) {
11494
+ if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep6)) return null;
11495
+ return relative4(DATA_ROOT, absPath);
11496
+ }
11497
+ function resolveDocDownloadRow(meta) {
11498
+ const result = resolveDocDownload(
11499
+ {
11500
+ accountId: meta.accountId,
11501
+ attachmentId: meta.attachmentId,
11502
+ name: meta.name,
11503
+ sourcePath: meta.sourcePath,
11504
+ sourceType: meta.sourceType
11505
+ },
11506
+ {
11507
+ dataRoot: DATA_ROOT,
11508
+ attachmentsRoot: ATTACHMENTS_ROOT,
11509
+ accountsDir: ACCOUNTS_DIR,
11510
+ claudeUploadsRoot: CLAUDE_UPLOADS_ROOT
11511
+ }
11512
+ );
11513
+ const aid = meta.attachmentId ? meta.attachmentId.slice(0, 8) : "none";
11514
+ if (result.ok) {
11515
+ console.log(`[admin/sidebar-artefacts] download-resolved id=${aid} via=${result.via} root=${result.root}`);
11516
+ return { downloadPath: result.relPath, downloadRoot: result.root };
11517
+ }
11518
+ console.log(`[admin/sidebar-artefacts] not-downloadable id=${aid} reason=${result.reason}`);
11519
+ return { downloadPath: null, downloadRoot: null };
11390
11520
  }
11391
11521
  var app22 = new Hono();
11392
11522
  app22.get("/", requireAdminSession, async (c) => {
@@ -11400,7 +11530,7 @@ app22.get("/", requireAdminSession, async (c) => {
11400
11530
  if (docs === null) {
11401
11531
  return c.json({ error: "Failed to load artefacts" }, 500);
11402
11532
  }
11403
- const accountDir = resolve15(ACCOUNTS_DIR, accountId);
11533
+ const accountDir = resolve16(ACCOUNTS_DIR, accountId);
11404
11534
  const agents = await fetchAgentTemplateRows(accountDir);
11405
11535
  const artefacts = [...docs, ...agents].sort(
11406
11536
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -11419,7 +11549,8 @@ async function fetchKnowledgeDocs(accountId) {
11419
11549
  `MATCH (d:KnowledgeDocument { accountId: $accountId })
11420
11550
  WHERE d.deletedAt IS NULL AND NOT d:Trashed
11421
11551
  RETURN d.attachmentId AS id, d.name AS name, d.updatedAt AS updatedAt,
11422
- d.attachmentId AS attachmentId, d.encodingFormat AS mimeType
11552
+ d.attachmentId AS attachmentId, d.encodingFormat AS mimeType,
11553
+ d.sourcePath AS sourcePath, d.sourceType AS sourceType
11423
11554
  ORDER BY d.updatedAt DESC
11424
11555
  LIMIT $limit`,
11425
11556
  { accountId, limit: neo4j2.int(LIMIT) }
@@ -11429,7 +11560,9 @@ async function fetchKnowledgeDocs(accountId) {
11429
11560
  name: r.get("name") ?? "",
11430
11561
  updatedAt: r.get("updatedAt") ?? "",
11431
11562
  attachmentId: r.get("attachmentId"),
11432
- mimeType: r.get("mimeType") ?? ""
11563
+ mimeType: r.get("mimeType") ?? "",
11564
+ sourcePath: r.get("sourcePath") ?? null,
11565
+ sourceType: r.get("sourceType") ?? null
11433
11566
  }));
11434
11567
  } catch (err) {
11435
11568
  const message = err instanceof Error ? err.message : String(err);
@@ -11441,7 +11574,13 @@ async function fetchKnowledgeDocs(accountId) {
11441
11574
  }
11442
11575
  return Promise.all(metas.map(async (m) => {
11443
11576
  const { content, skipReason } = await readArtefactContent(accountId, m.attachmentId, m.mimeType, m.name);
11444
- const absPath = await resolveDocAbsPath(accountId, m.attachmentId);
11577
+ const { downloadPath, downloadRoot } = resolveDocDownloadRow({
11578
+ accountId,
11579
+ attachmentId: m.attachmentId,
11580
+ name: m.name,
11581
+ sourcePath: m.sourcePath,
11582
+ sourceType: m.sourceType
11583
+ });
11445
11584
  return {
11446
11585
  id: m.id,
11447
11586
  name: m.name,
@@ -11451,7 +11590,8 @@ async function fetchKnowledgeDocs(accountId) {
11451
11590
  editable: skipReason === null,
11452
11591
  mimeType: m.mimeType,
11453
11592
  skipReason,
11454
- downloadPath: absPath ? toDataRootRelPath(absPath) : null
11593
+ downloadPath,
11594
+ downloadRoot
11455
11595
  };
11456
11596
  }));
11457
11597
  }
@@ -11465,8 +11605,8 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11465
11605
  logSkip(displayName, "non-text-mime", mimeType);
11466
11606
  return { content: "", skipReason: "non-text-mime" };
11467
11607
  }
11468
- const accountDir = resolve15(ATTACHMENTS_ROOT, accountId);
11469
- const dir = resolve15(accountDir, attachmentId);
11608
+ const accountDir = resolve16(ATTACHMENTS_ROOT, accountId);
11609
+ const dir = resolve16(accountDir, attachmentId);
11470
11610
  try {
11471
11611
  validateFilePathInAccount(dir, accountDir);
11472
11612
  } catch {
@@ -11480,7 +11620,7 @@ async function readArtefactContent(accountId, attachmentId, mimeType, displayNam
11480
11620
  logSkip(displayName, "missing-on-disk", mimeType);
11481
11621
  return { content: "", skipReason: "missing-on-disk" };
11482
11622
  }
11483
- return { content: await readFile5(resolve15(dir, dataFile), "utf-8"), skipReason: null };
11623
+ return { content: await readFile5(resolve16(dir, dataFile), "utf-8"), skipReason: null };
11484
11624
  } catch (err) {
11485
11625
  const message = err instanceof Error ? err.message : String(err);
11486
11626
  console.error(`[admin/sidebar-artefacts] read-failed attachmentId=${attachmentId.slice(0, 8)} error="${message}"`);
@@ -11496,8 +11636,8 @@ function logSkip(name, reason, mimeType) {
11496
11636
  async function fetchAgentTemplateRows(accountDir) {
11497
11637
  const rows = [];
11498
11638
  for (const filename of ADMIN_AGENT_FILES) {
11499
- const overridePath = resolve15(accountDir, "agents", "admin", filename);
11500
- const bundledPath = resolve15(PLATFORM_ROOT, "templates", "agents", "admin", filename);
11639
+ const overridePath = resolve16(accountDir, "agents", "admin", filename);
11640
+ const bundledPath = resolve16(PLATFORM_ROOT, "templates", "agents", "admin", filename);
11501
11641
  const labelStem = filename.replace(/\.md$/, "");
11502
11642
  const row = await readAgentTemplateRow({
11503
11643
  id: `agent-template:admin:${filename}`,
@@ -11511,12 +11651,12 @@ async function fetchAgentTemplateRows(accountDir) {
11511
11651
  });
11512
11652
  if (row) rows.push(row);
11513
11653
  }
11514
- const overrideDir = resolve15(accountDir, "specialists", "agents");
11515
- const bundledDir = resolve15(PLATFORM_ROOT, "templates", "specialists", "agents");
11654
+ const overrideDir = resolve16(accountDir, "specialists", "agents");
11655
+ const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
11516
11656
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
11517
11657
  for (const filename of specialistNames) {
11518
- const overridePath = resolve15(overrideDir, filename);
11519
- const bundledPath = resolve15(bundledDir, filename);
11658
+ const overridePath = resolve16(overrideDir, filename);
11659
+ const bundledPath = resolve16(bundledDir, filename);
11520
11660
  const row = await readAgentTemplateRow({
11521
11661
  id: `agent-template:specialist:${filename}`,
11522
11662
  displayName: filename.replace(/\.md$/, ""),
@@ -11575,6 +11715,7 @@ async function readAgentTemplateRow(inp) {
11575
11715
  readFile5(chosenPath, "utf-8"),
11576
11716
  stat5(chosenPath)
11577
11717
  ]);
11718
+ const dlPath = toDataRootRelPath(chosenPath);
11578
11719
  return {
11579
11720
  id: inp.id,
11580
11721
  name: inp.displayName,
@@ -11587,7 +11728,10 @@ async function readAgentTemplateRow(inp) {
11587
11728
  // Override paths live under <accountDir> (inside DATA_ROOT) and are
11588
11729
  // downloadable; bundled-fallback templates live under PLATFORM_ROOT
11589
11730
  // (outside DATA_ROOT) → null, so the client shows "not downloadable".
11590
- downloadPath: toDataRootRelPath(chosenPath)
11731
+ // Agent templates only ever resolve under DATA_ROOT, so the download
11732
+ // root is `data` whenever the path is non-null.
11733
+ downloadPath: dlPath,
11734
+ downloadRoot: dlPath ? "data" : null
11591
11735
  };
11592
11736
  } catch (err) {
11593
11737
  const message = err instanceof Error ? err.message : String(err);
@@ -11598,14 +11742,14 @@ async function readAgentTemplateRow(inp) {
11598
11742
  }
11599
11743
  }
11600
11744
  function isWithin(target, root) {
11601
- const rel = relative3(root, target);
11745
+ const rel = relative4(root, target);
11602
11746
  return !rel.startsWith("..") && !isAbsolute(rel);
11603
11747
  }
11604
11748
  var sidebar_artefacts_default = app22;
11605
11749
 
11606
11750
  // server/routes/admin/sidebar-artefact-save.ts
11607
11751
  import { mkdir as mkdir4, readdir as readdir5, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11608
- import { resolve as resolve16 } from "path";
11752
+ import { resolve as resolve17 } from "path";
11609
11753
  import { existsSync as existsSync17 } from "fs";
11610
11754
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
11611
11755
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
@@ -11618,7 +11762,7 @@ app23.post("/", requireAdminSession, async (c) => {
11618
11762
  if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
11619
11763
  return c.json({ error: "id and content required" }, 400);
11620
11764
  }
11621
- const accountDir = resolve16(ACCOUNTS_DIR, accountId);
11765
+ const accountDir = resolve17(ACCOUNTS_DIR, accountId);
11622
11766
  const resolved = await resolveSavePath(body.id, accountId, accountDir);
11623
11767
  if (resolved.kind === "heal-race") {
11624
11768
  c.header("Retry-After", "2");
@@ -11663,17 +11807,17 @@ async function resolveSavePath(id, accountId, accountDir) {
11663
11807
  if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
11664
11808
  return { kind: "reject", status: 400, reason: "invalid-id" };
11665
11809
  }
11666
- const parent = resolve16(accountDir, "agents", "admin");
11810
+ const parent = resolve17(accountDir, "agents", "admin");
11667
11811
  await mkdir4(parent, { recursive: true });
11668
11812
  try {
11669
11813
  validateFilePathInAccount(parent, accountDir);
11670
11814
  } catch {
11671
11815
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11672
11816
  }
11673
- return { kind: "admin-template", path: resolve16(parent, filename) };
11817
+ return { kind: "admin-template", path: resolve17(parent, filename) };
11674
11818
  }
11675
11819
  if (UUID_RE4.test(id)) {
11676
- const dir = resolve16(ATTACHMENTS_ROOT, accountId, id);
11820
+ const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
11677
11821
  if (!existsSync17(dir)) {
11678
11822
  const attShort = id.slice(0, 8);
11679
11823
  if (isHealPending(accountId, id)) {
@@ -11706,7 +11850,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11706
11850
  }
11707
11851
  }
11708
11852
  try {
11709
- validateFilePathInAccount(dir, resolve16(ATTACHMENTS_ROOT, accountId));
11853
+ validateFilePathInAccount(dir, resolve17(ATTACHMENTS_ROOT, accountId));
11710
11854
  } catch {
11711
11855
  return { kind: "reject", status: 400, reason: "containment-rejected" };
11712
11856
  }
@@ -11715,7 +11859,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11715
11859
  if (!dataFile) {
11716
11860
  return { kind: "reject", status: 400, reason: "not-found" };
11717
11861
  }
11718
- return { kind: "knowledge-doc", path: resolve16(dir, dataFile) };
11862
+ return { kind: "knowledge-doc", path: resolve17(dir, dataFile) };
11719
11863
  }
11720
11864
  return { kind: "reject", status: 400, reason: "invalid-id" };
11721
11865
  }
@@ -11727,7 +11871,7 @@ var sidebar_artefact_save_default = app23;
11727
11871
  // server/routes/admin/sidebar-artefact-content.ts
11728
11872
  import { readFile as readFile6, readdir as readdir6 } from "fs/promises";
11729
11873
  import { existsSync as existsSync18 } from "fs";
11730
- import { resolve as resolve17 } from "path";
11874
+ import { resolve as resolve18 } from "path";
11731
11875
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11732
11876
  var app24 = new Hono();
11733
11877
  app24.get("/", requireAdminSession, async (c) => {
@@ -11739,14 +11883,14 @@ app24.get("/", requireAdminSession, async (c) => {
11739
11883
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11740
11884
  return new Response("Not found", { status: 404 });
11741
11885
  }
11742
- const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
11886
+ const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11743
11887
  if (!existsSync18(dir)) {
11744
11888
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11745
11889
  return new Response("Not found", { status: 404 });
11746
11890
  }
11747
11891
  let meta;
11748
11892
  try {
11749
- meta = JSON.parse(await readFile6(resolve17(dir, `${id}.meta.json`), "utf-8"));
11893
+ meta = JSON.parse(await readFile6(resolve18(dir, `${id}.meta.json`), "utf-8"));
11750
11894
  } catch {
11751
11895
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11752
11896
  return new Response("Not found", { status: 404 });
@@ -11758,7 +11902,7 @@ app24.get("/", requireAdminSession, async (c) => {
11758
11902
  return new Response("Not found", { status: 404 });
11759
11903
  }
11760
11904
  const start = Date.now();
11761
- const buffer = await readFile6(resolve17(dir, dataFile));
11905
+ const buffer = await readFile6(resolve18(dir, dataFile));
11762
11906
  const ms = Date.now() - start;
11763
11907
  console.log(
11764
11908
  `[admin/sidebar-artefact-content] account=${accountId} id=${id.slice(0, 8)} mime=${meta.mimeType} bytes=${buffer.length} ms=${ms}`
@@ -11896,8 +12040,8 @@ var system_stats_default = app25;
11896
12040
 
11897
12041
  // server/routes/admin/health.ts
11898
12042
  import { existsSync as existsSync19, readFileSync as readFileSync14 } from "fs";
11899
- import { resolve as resolve18, join as join13 } from "path";
11900
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
12043
+ import { resolve as resolve19, join as join13 } from "path";
12044
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
11901
12045
  var brandHostname = "maxy";
11902
12046
  var brandJsonPath = join13(PLATFORM_ROOT6, "config", "brand.json");
11903
12047
  if (existsSync19(brandJsonPath)) {
@@ -11907,7 +12051,7 @@ if (existsSync19(brandJsonPath)) {
11907
12051
  } catch {
11908
12052
  }
11909
12053
  }
11910
- var VERSION_FILE = resolve18(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
12054
+ var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
11911
12055
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11912
12056
  var PROBE_TIMEOUT_MS = 1e3;
11913
12057
  function readVersion() {
@@ -12422,13 +12566,13 @@ var admin_default = app32;
12422
12566
  // app/lib/access-gate.ts
12423
12567
  import neo4j5 from "neo4j-driver";
12424
12568
  import { readFileSync as readFileSync15 } from "fs";
12425
- import { resolve as resolve19 } from "path";
12569
+ import { resolve as resolve20 } from "path";
12426
12570
  import { randomUUID as randomUUID8 } from "crypto";
12427
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
12571
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
12428
12572
  var driver = null;
12429
12573
  function readPassword() {
12430
12574
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
12431
- const passwordFile = resolve19(PLATFORM_ROOT7, "config/.neo4j-password");
12575
+ const passwordFile = resolve20(PLATFORM_ROOT7, "config/.neo4j-password");
12432
12576
  try {
12433
12577
  return readFileSync15(passwordFile, "utf-8").trim();
12434
12578
  } catch {
@@ -12718,9 +12862,9 @@ var verify_token_default = app33;
12718
12862
 
12719
12863
  // app/lib/access-email.ts
12720
12864
  import { spawn as spawn2 } from "child_process";
12721
- import { resolve as resolve20 } from "path";
12722
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
12723
- var SEND_SCRIPT = resolve20(
12865
+ import { resolve as resolve21 } from "path";
12866
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
12867
+ var SEND_SCRIPT = resolve21(
12724
12868
  PLATFORM_ROOT8,
12725
12869
  "plugins",
12726
12870
  "email",
@@ -12862,8 +13006,8 @@ app35.route("/request-magic-link", request_magic_link_default);
12862
13006
  var access_default = app35;
12863
13007
 
12864
13008
  // server/routes/sites.ts
12865
- import { existsSync as existsSync20, readFileSync as readFileSync16, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
12866
- import { resolve as resolve21 } from "path";
13009
+ import { existsSync as existsSync20, readFileSync as readFileSync16, realpathSync as realpathSync6, statSync as statSync8 } from "fs";
13010
+ import { resolve as resolve22 } from "path";
12867
13011
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12868
13012
  var MIME = {
12869
13013
  ".html": "text/html; charset=utf-8",
@@ -12920,15 +13064,15 @@ app36.get("/:rel{.*}", (c) => {
12920
13064
  }
12921
13065
  segments.push(seg);
12922
13066
  }
12923
- const rootDir = resolve21(account.accountDir, "sites");
12924
- let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
13067
+ const rootDir = resolve22(account.accountDir, "sites");
13068
+ let filePath = segments.length === 0 ? rootDir : resolve22(rootDir, ...segments);
12925
13069
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
12926
13070
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
12927
13071
  return c.text("Forbidden", 403);
12928
13072
  }
12929
13073
  let stat7;
12930
13074
  try {
12931
- stat7 = existsSync20(filePath) ? statSync7(filePath) : null;
13075
+ stat7 = existsSync20(filePath) ? statSync8(filePath) : null;
12932
13076
  } catch {
12933
13077
  stat7 = null;
12934
13078
  }
@@ -12941,7 +13085,7 @@ app36.get("/:rel{.*}", (c) => {
12941
13085
  return c.redirect(target, 301);
12942
13086
  }
12943
13087
  if (stat7?.isDirectory()) {
12944
- filePath = resolve21(filePath, "index.html");
13088
+ filePath = resolve22(filePath, "index.html");
12945
13089
  }
12946
13090
  if (!filePath.startsWith(rootDir + "/")) {
12947
13091
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -12954,8 +13098,8 @@ app36.get("/:rel{.*}", (c) => {
12954
13098
  let realPath;
12955
13099
  let realRoot;
12956
13100
  try {
12957
- realPath = realpathSync5(filePath);
12958
- realRoot = realpathSync5(rootDir);
13101
+ realPath = realpathSync6(filePath);
13102
+ realRoot = realpathSync6(rootDir);
12959
13103
  } catch {
12960
13104
  console.error(`[sites] not-found path=${reqPath} status=404`);
12961
13105
  return c.text("Not found", 404);
@@ -13224,8 +13368,8 @@ function appendConsentParams(pageUrl, token) {
13224
13368
  const hashIdx = pageUrl.indexOf("#");
13225
13369
  const hash = hashIdx >= 0 ? pageUrl.slice(hashIdx) : "";
13226
13370
  const base = hashIdx >= 0 ? pageUrl.slice(0, hashIdx) : pageUrl;
13227
- const sep6 = base.indexOf("?") >= 0 ? "&" : "?";
13228
- return base + sep6 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
13371
+ const sep7 = base.indexOf("?") >= 0 ? "&" : "?";
13372
+ return base + sep7 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
13229
13373
  }
13230
13374
  }
13231
13375
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
@@ -13719,8 +13863,8 @@ function broadcastAdminShutdown(reason) {
13719
13863
 
13720
13864
  // ../lib/entitlement/src/index.ts
13721
13865
  import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
13722
- import { existsSync as existsSync22, readFileSync as readFileSync19, statSync as statSync8 } from "fs";
13723
- import { resolve as resolve22 } from "path";
13866
+ import { existsSync as existsSync22, readFileSync as readFileSync19, statSync as statSync9 } from "fs";
13867
+ import { resolve as resolve23 } from "path";
13724
13868
 
13725
13869
  // ../lib/entitlement/src/canonicalize.ts
13726
13870
  function canonicalize(value) {
@@ -13755,7 +13899,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
13755
13899
  var GRACE_DAYS = 7;
13756
13900
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
13757
13901
  function pubkeyPath(brand) {
13758
- return resolve22(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
13902
+ return resolve23(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
13759
13903
  }
13760
13904
  var memo = null;
13761
13905
  function memoKey(mtimeMs, account) {
@@ -13767,11 +13911,11 @@ function resolveEntitlement(brand, account) {
13767
13911
  if (brand.commercialMode !== true) {
13768
13912
  return logResolved(implicitTrust(account), null);
13769
13913
  }
13770
- const entitlementPath = resolve22(brand.configDir, "entitlement.json");
13914
+ const entitlementPath = resolve23(brand.configDir, "entitlement.json");
13771
13915
  if (!existsSync22(entitlementPath)) {
13772
13916
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
13773
13917
  }
13774
- const stat7 = statSync8(entitlementPath);
13918
+ const stat7 = statSync9(entitlementPath);
13775
13919
  const key = memoKey(stat7.mtimeMs, account);
13776
13920
  if (memo && memo.key === key) {
13777
13921
  return memo.result;
@@ -14352,8 +14496,8 @@ app40.get("/agent-assets/:slug/:filename", (c) => {
14352
14496
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
14353
14497
  return c.text("Not found", 404);
14354
14498
  }
14355
- const filePath = resolve23(account.accountDir, "agents", slug, "assets", filename);
14356
- const expectedDir = resolve23(account.accountDir, "agents", slug, "assets");
14499
+ const filePath = resolve24(account.accountDir, "agents", slug, "assets", filename);
14500
+ const expectedDir = resolve24(account.accountDir, "agents", slug, "assets");
14357
14501
  if (!filePath.startsWith(expectedDir + "/")) {
14358
14502
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
14359
14503
  return c.text("Forbidden", 403);
@@ -14382,8 +14526,8 @@ app40.get("/generated/:filename", (c) => {
14382
14526
  console.error(`[generated] serve file=${filename} status=404`);
14383
14527
  return c.text("Not found", 404);
14384
14528
  }
14385
- const filePath = resolve23(account.accountDir, "generated", filename);
14386
- const expectedDir = resolve23(account.accountDir, "generated");
14529
+ const filePath = resolve24(account.accountDir, "generated", filename);
14530
+ const expectedDir = resolve24(account.accountDir, "generated");
14387
14531
  if (!filePath.startsWith(expectedDir + "/")) {
14388
14532
  console.error(`[generated] serve file=${filename} status=403`);
14389
14533
  return c.text("Forbidden", 403);
@@ -14470,7 +14614,7 @@ var clientErrorReporterScript = `<script>
14470
14614
  function cachedHtml(file) {
14471
14615
  let html = htmlCache.get(file);
14472
14616
  if (!html) {
14473
- html = readFileSync20(resolve23(process.cwd(), "public", file), "utf-8");
14617
+ html = readFileSync20(resolve24(process.cwd(), "public", file), "utf-8");
14474
14618
  const productNameEsc = escapeHtml(BRAND.productName);
14475
14619
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
14476
14620
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -14578,7 +14722,7 @@ app40.use("/vnc-popout.html", logViewerFetch);
14578
14722
  app40.get("/vnc-popout.html", (c) => {
14579
14723
  let html = htmlCache.get("vnc-popout.html");
14580
14724
  if (!html) {
14581
- html = readFileSync20(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14725
+ html = readFileSync20(resolve24(process.cwd(), "public", "vnc-popout.html"), "utf-8");
14582
14726
  const name = escapeHtml(BRAND.productName);
14583
14727
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
14584
14728
  html = html.replace("</head>", ` ${brandScript}
@@ -14796,7 +14940,7 @@ if (bootAccountConfig?.whatsapp) {
14796
14940
  }
14797
14941
  init({
14798
14942
  configDir: configDirForWhatsApp,
14799
- platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join15(__dirname, "..")),
14943
+ platformRoot: resolve24(process.env.MAXY_PLATFORM_ROOT ?? join15(__dirname, "..")),
14800
14944
  accountConfig: bootAccountConfig,
14801
14945
  onMessage: async (msg) => {
14802
14946
  if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {