@rubytech/create-maxy-code 0.1.330 → 0.1.331

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 (118) hide show
  1. package/dist/index.js +19 -2
  2. package/package.json +1 -1
  3. package/payload/platform/config/brand.json +1 -0
  4. package/payload/platform/lib/account-enumeration/dist/index.d.ts +33 -0
  5. package/payload/platform/lib/account-enumeration/dist/index.d.ts.map +1 -1
  6. package/payload/platform/lib/account-enumeration/dist/index.js +76 -0
  7. package/payload/platform/lib/account-enumeration/dist/index.js.map +1 -1
  8. package/payload/platform/lib/account-enumeration/src/index.ts +78 -0
  9. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  10. package/payload/platform/plugins/admin/PLUGIN.md +13 -1
  11. package/payload/platform/plugins/admin/mcp/dist/index.js +102 -0
  12. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  13. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts +2 -0
  14. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts.map +1 -0
  15. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js +57 -0
  16. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js.map +1 -0
  17. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +34 -0
  18. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +78 -0
  20. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -0
  21. package/payload/platform/plugins/admin/skills/plainly/SKILL.md +7 -0
  22. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
  23. package/payload/platform/plugins/contacts/mcp/dist/index.js +1 -1
  24. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
  25. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts +2 -0
  26. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts.map +1 -0
  27. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js +71 -0
  28. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js.map +1 -0
  29. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +1 -0
  30. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
  31. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +10 -3
  32. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
  33. package/payload/platform/plugins/contacts/mcp/package.json +4 -2
  34. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  35. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  36. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/index.js +3 -1
  38. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  39. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js +39 -0
  40. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js.map +1 -1
  41. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js +13 -1
  43. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js.map +1 -1
  44. package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +40 -0
  45. package/payload/platform/scripts/__tests__/sweep-durability.test.sh +103 -0
  46. package/payload/platform/scripts/lib/provision-account-dir.sh +319 -0
  47. package/payload/platform/scripts/lib/resolve-account-dir.sh +79 -132
  48. package/payload/platform/scripts/setup-account.sh +28 -361
  49. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  50. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +4 -0
  51. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/config.d.ts +18 -0
  53. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  54. package/payload/platform/services/claude-session-manager/dist/config.js +63 -7
  55. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  56. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  57. package/payload/platform/services/claude-session-manager/dist/http-server.js +30 -2
  58. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  59. package/payload/platform/services/claude-session-manager/dist/index.js +16 -1
  60. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  61. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  62. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +7 -0
  63. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  64. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +5 -0
  65. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  66. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +8 -0
  67. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  68. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +6 -0
  69. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
  70. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +17 -5
  71. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
  72. package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
  73. package/payload/platform/services/webchat-channel/dist/instructions.js +25 -1
  74. package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
  75. package/payload/platform/services/webchat-channel/dist/notification.d.ts +17 -0
  76. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  77. package/payload/platform/services/webchat-channel/dist/notification.js +14 -0
  78. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  79. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  80. package/payload/platform/services/webchat-channel/dist/server.js +66 -2
  81. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  82. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts +28 -0
  83. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts.map +1 -0
  84. package/payload/platform/services/webchat-channel/dist/turn-follow.js +188 -0
  85. package/payload/platform/services/webchat-channel/dist/turn-follow.js.map +1 -0
  86. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  87. package/payload/platform/services/whatsapp-channel/dist/notification.js +24 -1
  88. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  89. package/payload/platform/templates/account.json +2 -0
  90. package/payload/server/public/assets/AdminLoginScreens-DexSvtjD.js +1 -0
  91. package/payload/server/public/assets/AdminShell-Bf9tndNg.js +1 -0
  92. package/payload/server/public/assets/{Checkbox-1flpB9H0.js → Checkbox-D58GsKoQ.js} +1 -1
  93. package/payload/server/public/assets/{OperatorConversations-DrPqB9Ym.css → OperatorConversations-CDdp2nVn.css} +1 -1
  94. package/payload/server/public/assets/OperatorConversations-RmqANYz8.js +9 -0
  95. package/payload/server/public/assets/{admin-BWJTvagN.js → admin-CH5Vkkt4.js} +1 -1
  96. package/payload/server/public/assets/{browser-XM5e-fn1.js → browser-BwDtzSlr.js} +1 -1
  97. package/payload/server/public/assets/chat-3GY0LmYH.js +1 -0
  98. package/payload/server/public/assets/data-CttrzhfL.js +1 -0
  99. package/payload/server/public/assets/{graph-CIIz9Dmh.js → graph-CZSdF2jv.js} +3 -3
  100. package/payload/server/public/assets/{graph-labels-BRKvhE0e.js → graph-labels-Bi0fu8Ns.js} +1 -1
  101. package/payload/server/public/assets/operator-BEivxmRy.js +1 -0
  102. package/payload/server/public/assets/page-DUvT07SB.js +30 -0
  103. package/payload/server/public/assets/{public-BPlZnopr.js → public-B3eIlVbd.js} +1 -1
  104. package/payload/server/public/browser.html +4 -4
  105. package/payload/server/public/chat.html +5 -5
  106. package/payload/server/public/data.html +4 -4
  107. package/payload/server/public/graph.html +6 -6
  108. package/payload/server/public/index.html +6 -6
  109. package/payload/server/public/operator.html +7 -7
  110. package/payload/server/public/public.html +5 -5
  111. package/payload/server/server.js +314 -222
  112. package/payload/server/public/assets/AdminLoginScreens-BnuaXvxN.js +0 -1
  113. package/payload/server/public/assets/AdminShell-Br0DJQNu.js +0 -1
  114. package/payload/server/public/assets/OperatorConversations-C8sITz2_.js +0 -9
  115. package/payload/server/public/assets/chat-COFMxaoC.js +0 -1
  116. package/payload/server/public/assets/data-BHtJozT2.js +0 -1
  117. package/payload/server/public/assets/operator-9hbxrXKm.js +0 -1
  118. package/payload/server/public/assets/page-CXkBfOhG.js +0 -30
@@ -1293,8 +1293,8 @@ var serveStatic = (options = { root: "" }) => {
1293
1293
  };
1294
1294
 
1295
1295
  // server/index.ts
1296
- import { readFileSync as readFileSync31, existsSync as existsSync31, watchFile } from "fs";
1297
- import { resolve as resolve33, join as join28, basename as basename10 } from "path";
1296
+ import { readFileSync as readFileSync32, existsSync as existsSync31, watchFile } from "fs";
1297
+ import { resolve as resolve33, join as join29, basename as basename10 } from "path";
1298
1298
  import { homedir as homedir3 } from "os";
1299
1299
  import { monitorEventLoopDelay } from "perf_hooks";
1300
1300
 
@@ -1650,7 +1650,7 @@ async function ensureAuth() {
1650
1650
  }
1651
1651
 
1652
1652
  // server/routes/health.ts
1653
- import { existsSync as existsSync3, readFileSync as readFileSync6 } from "fs";
1653
+ import { existsSync as existsSync3, readFileSync as readFileSync7 } from "fs";
1654
1654
  import { createConnection as createConnection2 } from "net";
1655
1655
 
1656
1656
  // app/lib/network.ts
@@ -3297,6 +3297,23 @@ function enumerateValidAccountIds(accountsDir) {
3297
3297
  cache.set(accountsDir, valid);
3298
3298
  return valid;
3299
3299
  }
3300
+ function resolveHouseOrSoleAccountId(accountsDir) {
3301
+ const valid = enumerateValidAccountIds(accountsDir);
3302
+ const houses = [];
3303
+ for (const id of valid) {
3304
+ const configPath2 = resolve3(accountsDir, id, "account.json");
3305
+ try {
3306
+ const cfg = JSON.parse(readFileSync4(configPath2, "utf-8"));
3307
+ if (cfg.role === "house") houses.push(id);
3308
+ } catch {
3309
+ }
3310
+ }
3311
+ if (houses.length === 1) return houses[0];
3312
+ if (houses.length === 0 && valid.length === 1) return valid[0];
3313
+ throw new Error(
3314
+ `[account-registry] resolveHouseOrSoleAccountId: houses=${houses.length} total=${valid.length} under ${accountsDir} \u2014 expected exactly one role:"house" (or a single unlabelled account). Loud-fail rather than picking one silently.`
3315
+ );
3316
+ }
3300
3317
  function getAccountsDirFromEnv() {
3301
3318
  const root = process.env.MAXY_PLATFORM_ROOT;
3302
3319
  if (!root) {
@@ -3324,26 +3341,39 @@ var cached = null;
3324
3341
  var cachedAccountsDir = null;
3325
3342
  function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
3326
3343
  if (cached !== null && cachedAccountsDir === accountsDir) return cached;
3327
- const valid = enumerateValidAccountIds(accountsDir);
3328
- if (valid.length === 0) {
3329
- throw new Error(
3330
- `[whatsapp-persist] resolvePlatformAccountId: no platform account found under ${accountsDir} \u2014 corrupt install? Cannot stamp n.accountId without a valid UUID.`
3331
- );
3344
+ const resolved = resolveHouseOrSoleAccountId(accountsDir);
3345
+ cached = resolved;
3346
+ cachedAccountsDir = accountsDir;
3347
+ return cached;
3348
+ }
3349
+
3350
+ // app/lib/managed-service.ts
3351
+ import { join as join3 } from "path";
3352
+ import { readFileSync as readFileSync5 } from "fs";
3353
+ function isHouseManagedService(accountsDir = ACCOUNTS_DIR) {
3354
+ let houseId;
3355
+ try {
3356
+ houseId = resolvePlatformAccountId(accountsDir);
3357
+ } catch {
3358
+ return false;
3332
3359
  }
3333
- if (valid.length > 1) {
3334
- throw new Error(
3335
- `[whatsapp-persist] resolvePlatformAccountId: multiple platform accounts found under ${accountsDir} (${valid.join(", ")}) \u2014 Phase 0 invariant requires exactly one. Loud-fail rather than picking one silently.`
3360
+ try {
3361
+ const cfg = JSON.parse(
3362
+ readFileSync5(join3(accountsDir, houseId, "account.json"), "utf-8")
3336
3363
  );
3364
+ return cfg.managedService === true;
3365
+ } catch {
3366
+ return false;
3337
3367
  }
3338
- cached = valid[0];
3339
- cachedAccountsDir = accountsDir;
3340
- return cached;
3368
+ }
3369
+ function isCustomerTurnSuppressed(role, managedService) {
3370
+ return managedService === true && role !== "admin";
3341
3371
  }
3342
3372
 
3343
3373
  // app/lib/whatsapp/inbound/media.ts
3344
3374
  import { randomUUID as randomUUID3 } from "crypto";
3345
3375
  import { writeFile, mkdir } from "fs/promises";
3346
- import { join as join3 } from "path";
3376
+ import { join as join4 } from "path";
3347
3377
  import {
3348
3378
  downloadMediaMessage,
3349
3379
  downloadContentFromMessage,
@@ -3429,7 +3459,7 @@ async function downloadInboundMedia(msg, sock, opts) {
3429
3459
  await mkdir(MEDIA_DIR, { recursive: true });
3430
3460
  const ext = mimeToExt(mimetype ?? "application/octet-stream");
3431
3461
  const filename = `${randomUUID3()}.${ext}`;
3432
- const filePath = join3(MEDIA_DIR, filename);
3462
+ const filePath = join4(MEDIA_DIR, filename);
3433
3463
  await writeFile(filePath, buffer);
3434
3464
  const sizeKB = (buffer.length / 1024).toFixed(0);
3435
3465
  console.error(`${TAG9} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
@@ -4471,6 +4501,12 @@ async function handleInboundMessage(conn, msg) {
4471
4501
  `${TAG13} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (mediaResult ? ` mediaPath=${mediaResult.path}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
4472
4502
  );
4473
4503
  if (!accessResult.allowed) return;
4504
+ if (isCustomerTurnSuppressed(accessResult.agentType, isHouseManagedService())) {
4505
+ console.error(
4506
+ `[channel-house] op=inbound from=${senderPhone} accountId=${conn.platformAccountId} autoReply=suppressed`
4507
+ );
4508
+ return;
4509
+ }
4474
4510
  const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
4475
4511
  if (sendReceipts && msg.key.id) {
4476
4512
  sendReadReceipt(conn.sock, remoteJid, [msg.key.id], isGroup ? senderJid : void 0);
@@ -4541,7 +4577,7 @@ async function handleInboundMessage(conn, msg) {
4541
4577
  // app/lib/vnc.ts
4542
4578
  import { spawnSync, execFileSync } from "child_process";
4543
4579
  import { createConnection } from "net";
4544
- import { mkdirSync, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
4580
+ import { mkdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
4545
4581
  import { resolve as resolve4 } from "path";
4546
4582
  var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve4(process.cwd(), "..");
4547
4583
  var VNC_SCRIPT = resolve4(PLATFORM_ROOT3, "scripts/vnc.sh");
@@ -4599,7 +4635,7 @@ function discoverNativeDisplay() {
4599
4635
  const leaderPid = leaderResult.stdout?.trim();
4600
4636
  if (leaderPid) {
4601
4637
  try {
4602
- const environ = readFileSync5(`/proc/${leaderPid}/environ`, "utf8");
4638
+ const environ = readFileSync6(`/proc/${leaderPid}/environ`, "utf8");
4603
4639
  const match = environ.split("\0").find((e) => e.startsWith("WAYLAND_DISPLAY="));
4604
4640
  if (match) waylandDisplay = match.split("=")[1];
4605
4641
  } catch {
@@ -4859,7 +4895,7 @@ app.get("/", async (c) => {
4859
4895
  let pinConfigured = false;
4860
4896
  try {
4861
4897
  if (existsSync3(USERS_FILE)) {
4862
- const raw = readFileSync6(USERS_FILE, "utf-8").trim();
4898
+ const raw = readFileSync7(USERS_FILE, "utf-8").trim();
4863
4899
  if (raw) {
4864
4900
  const users = JSON.parse(raw);
4865
4901
  pinConfigured = Array.isArray(users) && users.length > 0;
@@ -5117,7 +5153,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
5117
5153
  // app/lib/stt/voice-note.ts
5118
5154
  import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
5119
5155
  import { tmpdir } from "os";
5120
- import { join as join4 } from "path";
5156
+ import { join as join5 } from "path";
5121
5157
  var TAG14 = "[voice]";
5122
5158
  var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
5123
5159
  "audio/ogg",
@@ -5161,9 +5197,9 @@ async function transcribeVoiceNote(file, source) {
5161
5197
  let tempDir;
5162
5198
  let tempPath;
5163
5199
  try {
5164
- tempDir = await mkdtemp(join4(tmpdir(), "voice-"));
5200
+ tempDir = await mkdtemp(join5(tmpdir(), "voice-"));
5165
5201
  const ext = audioExtension(mimeType);
5166
- tempPath = join4(tempDir, `recording${ext}`);
5202
+ tempPath = join5(tempDir, `recording${ext}`);
5167
5203
  const buffer = Buffer.from(await file.arrayBuffer());
5168
5204
  await writeFile3(tempPath, buffer);
5169
5205
  } catch (err) {
@@ -5483,15 +5519,15 @@ ${result.result.text}` : result.result.text;
5483
5519
  }
5484
5520
 
5485
5521
  // server/routes/whatsapp.ts
5486
- import { join as join7, resolve as resolve9 } from "path";
5487
- import { readdirSync as readdirSync3, readFileSync as readFileSync8, existsSync as existsSync5 } from "fs";
5522
+ import { join as join8, resolve as resolve9 } from "path";
5523
+ import { readdirSync as readdirSync3, readFileSync as readFileSync9, existsSync as existsSync5 } from "fs";
5488
5524
 
5489
5525
  // app/lib/whatsapp/login.ts
5490
5526
  import { randomUUID as randomUUID6 } from "crypto";
5491
5527
 
5492
5528
  // app/lib/whatsapp/config-persist.ts
5493
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
5494
- import { resolve as resolve7, join as join5 } from "path";
5529
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
5530
+ import { resolve as resolve7, join as join6 } from "path";
5495
5531
  var TAG15 = "[whatsapp:config]";
5496
5532
  function configPath(accountDir) {
5497
5533
  return resolve7(accountDir, "account.json");
@@ -5499,7 +5535,7 @@ function configPath(accountDir) {
5499
5535
  function readConfig(accountDir) {
5500
5536
  const path2 = configPath(accountDir);
5501
5537
  if (!existsSync4(path2)) throw new Error(`account.json not found at ${path2}`);
5502
- return JSON.parse(readFileSync7(path2, "utf-8"));
5538
+ return JSON.parse(readFileSync8(path2, "utf-8"));
5503
5539
  }
5504
5540
  function writeConfig(accountDir, config) {
5505
5541
  const path2 = configPath(accountDir);
@@ -5643,7 +5679,7 @@ function setPublicAgent(accountDir, slug) {
5643
5679
  if (!trimmed) {
5644
5680
  return { ok: false, error: "Agent slug cannot be empty." };
5645
5681
  }
5646
- const agentConfigPath = join5(accountDir, "agents", trimmed, "config.json");
5682
+ const agentConfigPath = join6(accountDir, "agents", trimmed, "config.json");
5647
5683
  if (!existsSync4(agentConfigPath)) {
5648
5684
  return { ok: false, error: `Agent "${trimmed}" not found \u2014 no config.json at ${agentConfigPath}. Check the agent slug and try again.` };
5649
5685
  }
@@ -6217,11 +6253,11 @@ function serializeWhatsAppSchema() {
6217
6253
 
6218
6254
  // app/lib/whatsapp/status-reconcile.ts
6219
6255
  import { readdirSync as readdirSync2 } from "fs";
6220
- import { join as join6 } from "path";
6256
+ import { join as join7 } from "path";
6221
6257
  var TAG18 = "[whatsapp:reconcile]";
6222
6258
  function listCredsAccountIds(credsRoot) {
6223
6259
  try {
6224
- return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join6(credsRoot, e.name))).map((e) => e.name);
6260
+ return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join7(credsRoot, e.name))).map((e) => e.name);
6225
6261
  } catch {
6226
6262
  return [];
6227
6263
  }
@@ -6236,7 +6272,7 @@ function reconcileCredsOnDisk(opts) {
6236
6272
  const entries = [];
6237
6273
  for (const accountId of listCredsAccountIds(credsRoot)) {
6238
6274
  if (liveAccountIds.has(accountId)) continue;
6239
- const authDir = join6(credsRoot, accountId);
6275
+ const authDir = join7(credsRoot, accountId);
6240
6276
  const selfPhone = readSelfId(authDir).e164 ?? void 0;
6241
6277
  const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
6242
6278
  console.error(
@@ -6263,7 +6299,7 @@ app2.get("/status", (c) => {
6263
6299
  try {
6264
6300
  const live = getStatus();
6265
6301
  const liveIds = new Set(live.map((a) => a.accountId));
6266
- const credsRoot = join7(MAXY_DIR, "credentials", "whatsapp");
6302
+ const credsRoot = join8(MAXY_DIR, "credentials", "whatsapp");
6267
6303
  const accountDir = resolveAccount()?.accountDir ?? null;
6268
6304
  const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
6269
6305
  const accounts = [...live, ...reconciled];
@@ -6284,7 +6320,7 @@ app2.post("/login/start", async (c) => {
6284
6320
  if (!phone) {
6285
6321
  return c.json({ error: 'Missing required field "phone" (E.164, e.g. +441234567890).' }, 400);
6286
6322
  }
6287
- const authDir = join7(MAXY_DIR, "credentials", "whatsapp", accountId);
6323
+ const authDir = join8(MAXY_DIR, "credentials", "whatsapp", accountId);
6288
6324
  const accountDir = resolveAccount()?.accountDir ?? null;
6289
6325
  const result = await startLogin({ accountId, authDir, phone, accountDir, force });
6290
6326
  console.error(`${TAG19} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
@@ -6392,7 +6428,7 @@ app2.post("/config", async (c) => {
6392
6428
  const configPath2 = resolve9(agentsDir, entry.name, "config.json");
6393
6429
  if (!existsSync5(configPath2)) continue;
6394
6430
  try {
6395
- const config = JSON.parse(readFileSync8(configPath2, "utf-8"));
6431
+ const config = JSON.parse(readFileSync9(configPath2, "utf-8"));
6396
6432
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
6397
6433
  } catch {
6398
6434
  console.error(`${TAG19} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
@@ -6661,12 +6697,12 @@ app2.get("/group-info", async (c) => {
6661
6697
  var whatsapp_default = app2;
6662
6698
 
6663
6699
  // server/routes/whatsapp-reader.ts
6664
- import { readFileSync as readFileSync12, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync7 } from "fs";
6665
- import { basename as basename2, dirname, isAbsolute, join as join11, relative as relative2, resolve as resolve11, sep as sep3 } from "path";
6700
+ import { readFileSync as readFileSync13, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync7 } from "fs";
6701
+ import { basename as basename2, dirname, isAbsolute, join as join12, relative as relative2, resolve as resolve11, sep as sep3 } from "path";
6666
6702
 
6667
6703
  // server/routes/admin/sidebar-sessions.ts
6668
- import { readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
6669
- import { join as join8, resolve as resolve10 } from "path";
6704
+ import { readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync2 } from "fs";
6705
+ import { join as join9, resolve as resolve10 } from "path";
6670
6706
 
6671
6707
  // app/lib/whatsapp-reader/select-sessions.ts
6672
6708
  function isReaderChannelSession(role, channel) {
@@ -6725,7 +6761,7 @@ function enumerateJsonls(projectsRoot) {
6725
6761
  throw err;
6726
6762
  }
6727
6763
  for (const slug of slugs) {
6728
- const slugDir = join8(projectsRoot, slug);
6764
+ const slugDir = join9(projectsRoot, slug);
6729
6765
  let entries;
6730
6766
  try {
6731
6767
  entries = readdirSync4(slugDir, { withFileTypes: true });
@@ -6736,9 +6772,9 @@ function enumerateJsonls(projectsRoot) {
6736
6772
  }
6737
6773
  for (const entry of entries) {
6738
6774
  if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
6739
- out.push({ path: join8(slugDir, entry.name), isSubagent: false, archived: false });
6775
+ out.push({ path: join9(slugDir, entry.name), isSubagent: false, archived: false });
6740
6776
  } else if (entry.isDirectory() && entry.name === "subagents") {
6741
- const subDir = join8(slugDir, entry.name);
6777
+ const subDir = join9(slugDir, entry.name);
6742
6778
  let subEntries;
6743
6779
  try {
6744
6780
  subEntries = readdirSync4(subDir, { withFileTypes: true });
@@ -6749,11 +6785,11 @@ function enumerateJsonls(projectsRoot) {
6749
6785
  }
6750
6786
  for (const sub of subEntries) {
6751
6787
  if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
6752
- out.push({ path: join8(subDir, sub.name), isSubagent: true, archived: false });
6788
+ out.push({ path: join9(subDir, sub.name), isSubagent: true, archived: false });
6753
6789
  }
6754
6790
  }
6755
6791
  } else if (entry.isDirectory() && entry.name === "archive") {
6756
- const archiveDir = join8(slugDir, entry.name);
6792
+ const archiveDir = join9(slugDir, entry.name);
6757
6793
  let archiveEntries;
6758
6794
  try {
6759
6795
  archiveEntries = readdirSync4(archiveDir, { withFileTypes: true });
@@ -6764,7 +6800,7 @@ function enumerateJsonls(projectsRoot) {
6764
6800
  }
6765
6801
  for (const arc of archiveEntries) {
6766
6802
  if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
6767
- out.push({ path: join8(archiveDir, arc.name), isSubagent: false, archived: true });
6803
+ out.push({ path: join9(archiveDir, arc.name), isSubagent: false, archived: true });
6768
6804
  }
6769
6805
  }
6770
6806
  }
@@ -6797,10 +6833,10 @@ async function fetchLiveSessions() {
6797
6833
  function loadUserTitles(accountDir) {
6798
6834
  const out = /* @__PURE__ */ new Map();
6799
6835
  if (!accountDir) return out;
6800
- const path2 = join8(accountDir, "session-titles.json");
6836
+ const path2 = join9(accountDir, "session-titles.json");
6801
6837
  let raw;
6802
6838
  try {
6803
- raw = readFileSync9(path2, "utf8");
6839
+ raw = readFileSync10(path2, "utf8");
6804
6840
  } catch {
6805
6841
  return out;
6806
6842
  }
@@ -6823,10 +6859,10 @@ function loadUserTitles(accountDir) {
6823
6859
  return out;
6824
6860
  }
6825
6861
  function readSidecarMeta(metaPath) {
6826
- const empty = { bridgeIds: [], role: null, channel: null, senderId: null, startedAt: null, personId: null, adminUserId: null, visitorId: null, agentSlug: null };
6862
+ const empty = { bridgeIds: [], role: null, channel: null, senderId: null, startedAt: null, personId: null, adminUserId: null, visitorId: null, agentSlug: null, accountId: null };
6827
6863
  let raw;
6828
6864
  try {
6829
- raw = readFileSync9(metaPath, "utf8");
6865
+ raw = readFileSync10(metaPath, "utf8");
6830
6866
  } catch {
6831
6867
  return empty;
6832
6868
  }
@@ -6848,7 +6884,8 @@ function readSidecarMeta(metaPath) {
6848
6884
  personId: typeof r.personId === "string" ? r.personId : null,
6849
6885
  adminUserId: typeof r.adminUserId === "string" ? r.adminUserId : null,
6850
6886
  visitorId: typeof r.visitorId === "string" ? r.visitorId : null,
6851
- agentSlug: typeof r.agentSlug === "string" ? r.agentSlug : null
6887
+ agentSlug: typeof r.agentSlug === "string" ? r.agentSlug : null,
6888
+ accountId: typeof r.accountId === "string" ? r.accountId : null
6852
6889
  };
6853
6890
  }
6854
6891
  function startsWithCliMarker(s) {
@@ -6915,12 +6952,33 @@ function resolveTitle(body, sessionId, userTitles) {
6915
6952
  }
6916
6953
  app3.get("/", requireAdminSession, async (c) => {
6917
6954
  const accountId = process.env.ACCOUNT_ID ?? null;
6955
+ const switcherUserId = (() => {
6956
+ const cacheKey = c.get("cacheKey");
6957
+ return cacheKey ? getUserIdForSession(cacheKey) : void 0;
6958
+ })();
6959
+ const accounts = [];
6960
+ if (switcherUserId) {
6961
+ for (const a of resolveUserAccounts(switcherUserId)) {
6962
+ let businessName = null;
6963
+ try {
6964
+ const branding = await fetchBranding(a.accountId);
6965
+ businessName = branding?.name || null;
6966
+ } catch {
6967
+ }
6968
+ accounts.push({
6969
+ accountId: a.accountId,
6970
+ role: a.config.role ?? "",
6971
+ businessName,
6972
+ isHouse: a.config.role === "house"
6973
+ });
6974
+ }
6975
+ }
6918
6976
  const configDir2 = claudeConfigDir();
6919
6977
  if (!configDir2) {
6920
6978
  console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
6921
- return c.json({ sessions: [], accountId });
6979
+ return c.json({ sessions: [], accountId, accounts });
6922
6980
  }
6923
- const projectsRoot = join8(configDir2, "projects");
6981
+ const projectsRoot = join9(configDir2, "projects");
6924
6982
  const jsonls = enumerateJsonls(projectsRoot);
6925
6983
  const liveSessions = await fetchLiveSessions();
6926
6984
  const accountDir = accountId ? resolve10(ACCOUNTS_DIR, accountId) : null;
@@ -6947,7 +7005,7 @@ app3.get("/", requireAdminSession, async (c) => {
6947
7005
  let body;
6948
7006
  let mtimeMs;
6949
7007
  try {
6950
- body = readFileSync9(path2, "utf8");
7008
+ body = readFileSync10(path2, "utf8");
6951
7009
  mtimeMs = statSync2(path2).mtimeMs;
6952
7010
  } catch {
6953
7011
  continue;
@@ -6956,8 +7014,8 @@ app3.get("/", requireAdminSession, async (c) => {
6956
7014
  const pid = live ? liveSessions.get(sessionId) ?? null : null;
6957
7015
  const resolved = resolveTitle(body, sessionId, userTitles);
6958
7016
  titleSourceCounts[resolved.source] += 1;
6959
- const metaPath = join8(projectDir, `${sessionId}.meta.json`);
6960
- const { bridgeIds, role, channel: sidecarChannel, personId, adminUserId } = readSidecarMeta(metaPath);
7017
+ const metaPath = join9(projectDir, `${sessionId}.meta.json`);
7018
+ const { bridgeIds, role, channel: sidecarChannel, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
6961
7019
  if (isReaderChannelSession(role, sidecarChannel)) {
6962
7020
  excludedChannelCount += 1;
6963
7021
  continue;
@@ -6979,7 +7037,8 @@ app3.get("/", requireAdminSession, async (c) => {
6979
7037
  archived,
6980
7038
  channel: resolved.channel,
6981
7039
  personName: null,
6982
- model: lastAssistantModel(body)
7040
+ model: lastAssistantModel(body),
7041
+ accountId: rowAccountId
6983
7042
  });
6984
7043
  if (live) liveCount += 1;
6985
7044
  if (isSubagent) subagentCount += 1;
@@ -7015,20 +7074,20 @@ app3.get("/", requireAdminSession, async (c) => {
7015
7074
  console.log(
7016
7075
  `[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} excludedChannel=${excludedChannelCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
7017
7076
  );
7018
- return c.json({ sessions: rows, accountId });
7077
+ return c.json({ sessions: rows, accountId, accounts });
7019
7078
  });
7020
7079
  var sidebar_sessions_default = app3;
7021
7080
 
7022
7081
  // app/lib/admin-identity/pin-validator.ts
7023
7082
  import { createHash } from "crypto";
7024
- import { existsSync as existsSync6, readFileSync as readFileSync10, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
7025
- import { join as join9 } from "path";
7083
+ import { existsSync as existsSync6, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
7084
+ import { join as join10 } from "path";
7026
7085
  function hashPin(pin) {
7027
7086
  return createHash("sha256").update(pin).digest("hex");
7028
7087
  }
7029
7088
  function readUsersFile(usersFilePath) {
7030
7089
  if (!existsSync6(usersFilePath)) return null;
7031
- const raw = readFileSync10(usersFilePath, "utf-8").trim();
7090
+ const raw = readFileSync11(usersFilePath, "utf-8").trim();
7032
7091
  if (!raw) return [];
7033
7092
  return JSON.parse(raw);
7034
7093
  }
@@ -7056,16 +7115,16 @@ function scanForOrphanedAccountAdmins(users, accountsDir) {
7056
7115
  }
7057
7116
  for (const entry of entries) {
7058
7117
  if (entry.startsWith(".")) continue;
7059
- const accountDir = join9(accountsDir, entry);
7118
+ const accountDir = join10(accountsDir, entry);
7060
7119
  try {
7061
7120
  if (!statSync3(accountDir).isDirectory()) continue;
7062
7121
  } catch {
7063
7122
  continue;
7064
7123
  }
7065
- const accountJsonPath = join9(accountDir, "account.json");
7124
+ const accountJsonPath = join10(accountDir, "account.json");
7066
7125
  if (!existsSync6(accountJsonPath)) continue;
7067
7126
  try {
7068
- const config = JSON.parse(readFileSync10(accountJsonPath, "utf-8"));
7127
+ const config = JSON.parse(readFileSync11(accountJsonPath, "utf-8"));
7069
7128
  const admins = config.admins ?? [];
7070
7129
  for (const a of admins) {
7071
7130
  if (typeof a.userId === "string" && !known.has(a.userId)) orphans.push(a.userId);
@@ -7321,8 +7380,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
7321
7380
  }
7322
7381
 
7323
7382
  // app/lib/whatsapp-reader/enrich-attachments.ts
7324
- import { readFileSync as readFileSync11, readdirSync as readdirSync6 } from "fs";
7325
- import { join as join10 } from "path";
7383
+ import { readFileSync as readFileSync12, readdirSync as readdirSync6 } from "fs";
7384
+ import { join as join11 } from "path";
7326
7385
  var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
7327
7386
  function adminAttachmentIds(text) {
7328
7387
  const ids = [];
@@ -7335,7 +7394,7 @@ function adminAttachmentIds(text) {
7335
7394
  function adminAttachmentsFromText(text, uploadsBase) {
7336
7395
  const out = [];
7337
7396
  for (const id of adminAttachmentIds(text)) {
7338
- const meta = readAttachmentMeta(join10(uploadsBase, id));
7397
+ const meta = readAttachmentMeta(join11(uploadsBase, id));
7339
7398
  if (meta) out.push(meta);
7340
7399
  }
7341
7400
  return out;
@@ -7343,7 +7402,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
7343
7402
  function readSidecar(dir, attachmentId) {
7344
7403
  let parsed;
7345
7404
  try {
7346
- parsed = JSON.parse(readFileSync11(join10(dir, `${attachmentId}.meta.json`), "utf8"));
7405
+ parsed = JSON.parse(readFileSync12(join11(dir, `${attachmentId}.meta.json`), "utf8"));
7347
7406
  } catch {
7348
7407
  return null;
7349
7408
  }
@@ -7372,7 +7431,7 @@ function listSessionAttachmentsInDir(dir) {
7372
7431
  }
7373
7432
  const sidecars = [];
7374
7433
  for (const name of entries) {
7375
- const sidecar = readSidecar(join10(dir, name), name);
7434
+ const sidecar = readSidecar(join11(dir, name), name);
7376
7435
  if (sidecar) sidecars.push(sidecar);
7377
7436
  }
7378
7437
  sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
@@ -7407,17 +7466,17 @@ var app4 = new Hono();
7407
7466
  app4.get("/conversations", requireAdminSession, async (c) => {
7408
7467
  const cfg = claudeConfigDir();
7409
7468
  if (!cfg) return c.json({ conversations: [] });
7410
- const projectsRoot = join11(cfg, "projects");
7469
+ const projectsRoot = join12(cfg, "projects");
7411
7470
  const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
7412
7471
  const rows = [];
7413
7472
  for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
7414
7473
  const sessionId = basename2(path2).replace(/\.jsonl$/, "");
7415
7474
  const projectDir = dirname(path2);
7416
- const meta = readSidecarMeta(join11(projectDir, `${sessionId}.meta.json`));
7475
+ const meta = readSidecarMeta(join12(projectDir, `${sessionId}.meta.json`));
7417
7476
  if (!isReaderChannelSession(meta.role, meta.channel)) continue;
7418
7477
  let body = "";
7419
7478
  try {
7420
- body = readFileSync12(path2, "utf8");
7479
+ body = readFileSync13(path2, "utf8");
7421
7480
  } catch {
7422
7481
  }
7423
7482
  const { title } = resolveTitle(body, sessionId, userTitles);
@@ -7521,11 +7580,11 @@ app4.get("/stream", requireAdminSession, (c) => {
7521
7580
  const sessionId = c.req.query("sessionId") ?? "";
7522
7581
  const projectDir = c.req.query("projectDir") ?? "";
7523
7582
  const cfg = claudeConfigDir();
7524
- const projectsRoot = cfg ? resolve11(join11(cfg, "projects")) : null;
7583
+ const projectsRoot = cfg ? resolve11(join12(cfg, "projects")) : null;
7525
7584
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
7526
7585
  return c.json({ error: "bad session reference" }, 400);
7527
7586
  }
7528
- const jsonlPath = resolve11(join11(projectDir, `${sessionId}.jsonl`));
7587
+ const jsonlPath = resolve11(join12(projectDir, `${sessionId}.jsonl`));
7529
7588
  if (!jsonlPath.startsWith(projectsRoot + sep3)) {
7530
7589
  return c.json({ error: "bad session reference" }, 400);
7531
7590
  }
@@ -7638,7 +7697,7 @@ app4.get("/directives", requireAdminSession, (c) => {
7638
7697
  const pid = Number(pidPart);
7639
7698
  let len = 0;
7640
7699
  try {
7641
- len = statSync4(join11(dir, name)).size;
7700
+ len = statSync4(join12(dir, name)).size;
7642
7701
  } catch {
7643
7702
  }
7644
7703
  return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
@@ -7653,11 +7712,11 @@ app4.get("/directive", requireAdminSession, (c) => {
7653
7712
  }
7654
7713
  const dir = directiveStoreDir(sessionId);
7655
7714
  if (!dir) return c.json({ error: "no account" }, 404);
7656
- const path2 = resolve11(join11(dir, name));
7715
+ const path2 = resolve11(join12(dir, name));
7657
7716
  if (!path2.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
7658
7717
  let body;
7659
7718
  try {
7660
- body = readFileSync12(path2, "utf8");
7719
+ body = readFileSync13(path2, "utf8");
7661
7720
  } catch {
7662
7721
  return c.json({ error: "not found" }, 404);
7663
7722
  }
@@ -7666,8 +7725,8 @@ app4.get("/directive", requireAdminSession, (c) => {
7666
7725
  var whatsapp_reader_default = app4;
7667
7726
 
7668
7727
  // server/routes/public-reader.ts
7669
- import { statSync as statSync5, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync13, readdirSync as readdirSync8 } from "fs";
7670
- import { basename as basename3, dirname as dirname2, join as join12, resolve as resolve12, sep as sep4 } from "path";
7728
+ import { statSync as statSync5, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "fs";
7729
+ import { basename as basename3, dirname as dirname2, join as join13, resolve as resolve12, sep as sep4 } from "path";
7671
7730
 
7672
7731
  // app/lib/whatsapp-reader/delivered-kinds.ts
7673
7732
  var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
@@ -7741,10 +7800,10 @@ function enumeratePublicRows() {
7741
7800
  const cfg = claudeConfigDir();
7742
7801
  if (!cfg) return [];
7743
7802
  const rows = [];
7744
- for (const { path: path2 } of enumerateJsonls(join12(cfg, "projects"))) {
7803
+ for (const { path: path2 } of enumerateJsonls(join13(cfg, "projects"))) {
7745
7804
  const sessionId = basename3(path2).replace(/\.jsonl$/, "");
7746
7805
  const projectDir = dirname2(path2);
7747
- const meta = readSidecarMeta(join12(projectDir, `${sessionId}.meta.json`));
7806
+ const meta = readSidecarMeta(join13(projectDir, `${sessionId}.meta.json`));
7748
7807
  rows.push({
7749
7808
  sessionId,
7750
7809
  projectDir,
@@ -7820,15 +7879,15 @@ app5.get("/stream", (c) => {
7820
7879
  const sessionId = c.req.query("sessionId") ?? "";
7821
7880
  const projectDir = c.req.query("projectDir") ?? "";
7822
7881
  const cfg = claudeConfigDir();
7823
- const projectsRoot = cfg ? resolve12(join12(cfg, "projects")) : null;
7882
+ const projectsRoot = cfg ? resolve12(join13(cfg, "projects")) : null;
7824
7883
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
7825
7884
  return c.json({ error: "bad session reference" }, 400);
7826
7885
  }
7827
- const jsonlPath = resolve12(join12(projectDir, `${sessionId}.jsonl`));
7886
+ const jsonlPath = resolve12(join13(projectDir, `${sessionId}.jsonl`));
7828
7887
  if (!jsonlPath.startsWith(projectsRoot + sep4)) {
7829
7888
  return c.json({ error: "bad session reference" }, 400);
7830
7889
  }
7831
- const meta = readSidecarMeta(join12(projectDir, `${sessionId}.meta.json`));
7890
+ const meta = readSidecarMeta(join13(projectDir, `${sessionId}.meta.json`));
7832
7891
  const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
7833
7892
  const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
7834
7893
  if (!(isPublicWebchat && owns)) {
@@ -7943,7 +8002,7 @@ app5.get("/attachment/:attachmentId", (c) => {
7943
8002
  try {
7944
8003
  dataFile = readdirSync8(dir).find((f) => !f.endsWith(".meta.json"));
7945
8004
  if (!dataFile) throw new Error("no data file");
7946
- buffer = readFileSync13(resolve12(dir, dataFile));
8005
+ buffer = readFileSync14(resolve12(dir, dataFile));
7947
8006
  } catch {
7948
8007
  console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
7949
8008
  return new Response("Not found", { status: 404 });
@@ -7962,20 +8021,20 @@ var public_reader_default = app5;
7962
8021
 
7963
8022
  // server/routes/webchat.ts
7964
8023
  import { basename as basename4, dirname as dirname3 } from "path";
7965
- import { join as join15 } from "path";
7966
- import { existsSync as existsSync9, readdirSync as readdirSync10, readFileSync as readFileSync16, renameSync as renameSync3, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
8024
+ import { join as join16 } from "path";
8025
+ import { existsSync as existsSync9, readdirSync as readdirSync10, readFileSync as readFileSync17, renameSync as renameSync3, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
7967
8026
 
7968
8027
  // server/canonical-webchat-override.ts
7969
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync5, renameSync } from "fs";
7970
- import { join as join13 } from "path";
8028
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync5, renameSync } from "fs";
8029
+ import { join as join14 } from "path";
7971
8030
  var FILE = "canonical-webchat-session.json";
7972
8031
  var UUID = /^[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}$/;
7973
8032
  function canonicalOverridePath(accountDir) {
7974
- return join13(accountDir, FILE);
8033
+ return join14(accountDir, FILE);
7975
8034
  }
7976
8035
  function readRaw(accountDir) {
7977
8036
  try {
7978
- return JSON.parse(readFileSync14(canonicalOverridePath(accountDir), "utf8"));
8037
+ return JSON.parse(readFileSync15(canonicalOverridePath(accountDir), "utf8"));
7979
8038
  } catch {
7980
8039
  return null;
7981
8040
  }
@@ -8062,8 +8121,8 @@ function isNewSessionEffortLevel(value) {
8062
8121
  }
8063
8122
 
8064
8123
  // ../services/claude-session-manager/src/sidecar-store.ts
8065
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync as readdirSync9, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
8066
- import { join as join14 } from "path";
8124
+ import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync as readdirSync9, readFileSync as readFileSync16, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
8125
+ import { join as join15 } from "path";
8067
8126
  function escapeRegExp(s) {
8068
8127
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8069
8128
  }
@@ -8071,7 +8130,7 @@ function createSidecarStore(config) {
8071
8130
  const { suffix, validate: validate2 } = config;
8072
8131
  const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
8073
8132
  function pathFor(sessionsDir, id) {
8074
- return join14(sessionsDir, `${id}${suffix}`);
8133
+ return join15(sessionsDir, `${id}${suffix}`);
8075
8134
  }
8076
8135
  function write(sessionsDir, id, record) {
8077
8136
  mkdirSync2(sessionsDir, { recursive: true });
@@ -8092,7 +8151,7 @@ function createSidecarStore(config) {
8092
8151
  function readFileAt(path2) {
8093
8152
  let raw;
8094
8153
  try {
8095
- raw = readFileSync15(path2, "utf8");
8154
+ raw = readFileSync16(path2, "utf8");
8096
8155
  } catch {
8097
8156
  return null;
8098
8157
  }
@@ -8115,10 +8174,10 @@ function createSidecarStore(config) {
8115
8174
  const out = [];
8116
8175
  for (const name of names) {
8117
8176
  if (!suffixRe.test(name)) continue;
8118
- const path2 = join14(sessionsDir, name);
8177
+ const path2 = join15(sessionsDir, name);
8119
8178
  let raw;
8120
8179
  try {
8121
- raw = readFileSync15(path2, "utf8");
8180
+ raw = readFileSync16(path2, "utf8");
8122
8181
  } catch {
8123
8182
  onSkip?.(name, "unreadable");
8124
8183
  continue;
@@ -8192,10 +8251,10 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
8192
8251
  function locateSession(sessionId) {
8193
8252
  const cfg = claudeConfigDir();
8194
8253
  if (!cfg) return { projectDir: null, channel: null };
8195
- for (const { path: path2 } of enumerateJsonls(join15(cfg, "projects"))) {
8254
+ for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
8196
8255
  if (basename4(path2) === `${sessionId}.jsonl`) {
8197
8256
  const dir = dirname3(path2);
8198
- const meta = readSidecarMeta(join15(dir, `${sessionId}.meta.json`));
8257
+ const meta = readSidecarMeta(join16(dir, `${sessionId}.meta.json`));
8199
8258
  return { projectDir: dir, channel: meta.channel };
8200
8259
  }
8201
8260
  }
@@ -8204,7 +8263,7 @@ function locateSession(sessionId) {
8204
8263
  function locateSidecar(sessionId) {
8205
8264
  const cfg = claudeConfigDir();
8206
8265
  if (!cfg) return null;
8207
- const projectsRoot = join15(cfg, "projects");
8266
+ const projectsRoot = join16(cfg, "projects");
8208
8267
  let slugs;
8209
8268
  try {
8210
8269
  slugs = readdirSync10(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
@@ -8212,7 +8271,7 @@ function locateSidecar(sessionId) {
8212
8271
  return null;
8213
8272
  }
8214
8273
  for (const slug of slugs) {
8215
- const metaPath = join15(projectsRoot, slug, `${sessionId}.meta.json`);
8274
+ const metaPath = join16(projectsRoot, slug, `${sessionId}.meta.json`);
8216
8275
  if (existsSync9(metaPath)) {
8217
8276
  const meta = readSidecarMeta(metaPath);
8218
8277
  return { channel: meta.channel, adminUserId: meta.adminUserId };
@@ -8225,7 +8284,7 @@ function readTargetOwner(sessionId) {
8225
8284
  if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
8226
8285
  const { projectDir } = locateSession(sessionId);
8227
8286
  if (projectDir !== null) {
8228
- return { found: true, owner: readSidecarMeta(join15(projectDir, `${sessionId}.meta.json`)).adminUserId };
8287
+ return { found: true, owner: readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`)).adminUserId };
8229
8288
  }
8230
8289
  return { found: false, owner: null };
8231
8290
  }
@@ -8239,7 +8298,7 @@ function sessionSidecarExists(sessionId) {
8239
8298
  function jsonlSizeBytes(projectDir, sessionId) {
8240
8299
  if (projectDir === null) return null;
8241
8300
  try {
8242
- return statSync6(join15(projectDir, `${sessionId}.jsonl`)).size;
8301
+ return statSync6(join16(projectDir, `${sessionId}.jsonl`)).size;
8243
8302
  } catch {
8244
8303
  return null;
8245
8304
  }
@@ -8327,10 +8386,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId) {
8327
8386
  const cfg = claudeConfigDir();
8328
8387
  if (!cfg) return null;
8329
8388
  let best = null;
8330
- for (const { path: path2, isSubagent, archived } of enumerateJsonls(join15(cfg, "projects"))) {
8389
+ for (const { path: path2, isSubagent, archived } of enumerateJsonls(join16(cfg, "projects"))) {
8331
8390
  if (isSubagent || archived) continue;
8332
8391
  const id = basename4(path2).slice(0, -".jsonl".length);
8333
- const meta = readSidecarMeta(join15(dirname3(path2), `${id}.meta.json`));
8392
+ const meta = readSidecarMeta(join16(dirname3(path2), `${id}.meta.json`));
8334
8393
  if (meta.role !== "admin" || meta.channel !== "webchat") continue;
8335
8394
  let mtimeMs;
8336
8395
  try {
@@ -8581,9 +8640,9 @@ ${note}` : note;
8581
8640
  console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
8582
8641
  return c.json({ error: "account unresolved" }, 503);
8583
8642
  }
8584
- const accountJsonPath = join15(account.accountDir, "account.json");
8643
+ const accountJsonPath = join16(account.accountDir, "account.json");
8585
8644
  try {
8586
- const parsed = JSON.parse(readFileSync16(accountJsonPath, "utf8"));
8645
+ const parsed = JSON.parse(readFileSync17(accountJsonPath, "utf8"));
8587
8646
  if (op === "model") parsed.adminModel = value;
8588
8647
  else if (op === "effort") parsed.effort = value;
8589
8648
  else parsed.adminPermissionMode = value;
@@ -8628,7 +8687,7 @@ ${note}` : note;
8628
8687
  const cfg2 = claudeConfigDir();
8629
8688
  if (cfg2) {
8630
8689
  const source2 = resolveBridgeSource(
8631
- join15(cfg2, "sessions"),
8690
+ join16(cfg2, "sessions"),
8632
8691
  target,
8633
8692
  (id) => locateSession(id).projectDir !== null
8634
8693
  );
@@ -8660,7 +8719,7 @@ ${note}` : note;
8660
8719
  const cfg = claudeConfigDir();
8661
8720
  let projectDir = null;
8662
8721
  if (cfg) {
8663
- for (const { path: path2 } of enumerateJsonls(join15(cfg, "projects"))) {
8722
+ for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
8664
8723
  if (basename4(path2) === `${sessionId}.jsonl`) {
8665
8724
  projectDir = dirname3(path2);
8666
8725
  break;
@@ -8668,7 +8727,7 @@ ${note}` : note;
8668
8727
  }
8669
8728
  }
8670
8729
  if (source === "latest" && requesterUserId !== null) {
8671
- const owner = readSidecarMeta(join15(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
8730
+ const owner = readSidecarMeta(join16(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
8672
8731
  if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
8673
8732
  console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
8674
8733
  }
@@ -8700,8 +8759,8 @@ ${note}` : note;
8700
8759
  import { resolve as resolve13 } from "path";
8701
8760
 
8702
8761
  // app/lib/claude-agent/specialist-roster.ts
8703
- import { existsSync as existsSync10, readFileSync as readFileSync17, readdirSync as readdirSync11 } from "fs";
8704
- import { join as join16 } from "path";
8762
+ import { existsSync as existsSync10, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "fs";
8763
+ import { join as join17 } from "path";
8705
8764
  function field(fm, name) {
8706
8765
  const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
8707
8766
  if (!m) return null;
@@ -8720,7 +8779,7 @@ function readSpecialistRoster(specialistsDir) {
8720
8779
  if (!file.endsWith(".md")) continue;
8721
8780
  let raw;
8722
8781
  try {
8723
- raw = readFileSync17(join16(specialistsDir, file), "utf-8");
8782
+ raw = readFileSync18(join17(specialistsDir, file), "utf-8");
8724
8783
  } catch (err) {
8725
8784
  skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
8726
8785
  continue;
@@ -8837,8 +8896,8 @@ var webchat_greeting_default = app6;
8837
8896
 
8838
8897
  // server/routes/telegram.ts
8839
8898
  import { homedir } from "os";
8840
- import { resolve as resolve17, join as join17 } from "path";
8841
- import { existsSync as existsSync11, readFileSync as readFileSync18 } from "fs";
8899
+ import { resolve as resolve17, join as join18 } from "path";
8900
+ import { existsSync as existsSync11, readFileSync as readFileSync19 } from "fs";
8842
8901
 
8843
8902
  // app/lib/channel-pty-bridge/bridge.ts
8844
8903
  import { resolve as resolve16 } from "path";
@@ -9959,10 +10018,10 @@ var TAG26 = "[telegram-inbound]";
9959
10018
  var DISPATCH_TIMEOUT_MS = 12e4;
9960
10019
  function configDirName() {
9961
10020
  const platformRoot4 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
9962
- const brandPath = join17(platformRoot4, "config", "brand.json");
10021
+ const brandPath = join18(platformRoot4, "config", "brand.json");
9963
10022
  if (existsSync11(brandPath)) {
9964
10023
  try {
9965
- return JSON.parse(readFileSync18(brandPath, "utf-8")).configDir ?? ".maxy";
10024
+ return JSON.parse(readFileSync19(brandPath, "utf-8")).configDir ?? ".maxy";
9966
10025
  } catch {
9967
10026
  }
9968
10027
  }
@@ -9998,7 +10057,7 @@ app7.post("/", async (c) => {
9998
10057
  console.error(`${TAG26} op=reject reason=no-secret-file botType=${botType}`);
9999
10058
  return c.json({ ok: false }, 401);
10000
10059
  }
10001
- const expected = readFileSync18(sp, "utf-8").trim();
10060
+ const expected = readFileSync19(sp, "utf-8").trim();
10002
10061
  const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
10003
10062
  if (got !== expected) {
10004
10063
  console.error(`${TAG26} op=reject reason=bad-secret botType=${botType}`);
@@ -10063,16 +10122,16 @@ app7.post("/", async (c) => {
10063
10122
  var telegram_default = app7;
10064
10123
 
10065
10124
  // server/routes/quickbooks.ts
10066
- import { join as join18 } from "path";
10067
- import { existsSync as existsSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, rmSync, renameSync as renameSync4 } from "fs";
10125
+ import { join as join19 } from "path";
10126
+ import { existsSync as existsSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, rmSync, renameSync as renameSync4 } from "fs";
10068
10127
  var TAG27 = "[quickbooks]";
10069
10128
  var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
10070
10129
  var STATE_RE = /^[A-Za-z0-9_-]+$/;
10071
10130
  function pendingPath(accountDir, state) {
10072
- return join18(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
10131
+ return join19(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
10073
10132
  }
10074
10133
  function storePath(accountDir) {
10075
- return join18(accountDir, "secrets", "quickbooks.json");
10134
+ return join19(accountDir, "secrets", "quickbooks.json");
10076
10135
  }
10077
10136
  async function completeConsent(args) {
10078
10137
  const { accountDir, code, realmId } = args;
@@ -10091,7 +10150,7 @@ async function completeConsent(args) {
10091
10150
  try {
10092
10151
  let pending;
10093
10152
  try {
10094
- pending = JSON.parse(readFileSync19(claimFile, "utf-8"));
10153
+ pending = JSON.parse(readFileSync20(claimFile, "utf-8"));
10095
10154
  } catch {
10096
10155
  console.error(`${TAG27} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
10097
10156
  return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
@@ -10107,7 +10166,7 @@ async function completeConsent(args) {
10107
10166
  if (!existsSync12(storePath(accountDir))) {
10108
10167
  return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
10109
10168
  }
10110
- const store2 = JSON.parse(readFileSync19(storePath(accountDir), "utf-8"));
10169
+ const store2 = JSON.parse(readFileSync20(storePath(accountDir), "utf-8"));
10111
10170
  const form = new URLSearchParams({
10112
10171
  grant_type: "authorization_code",
10113
10172
  code,
@@ -10139,9 +10198,9 @@ async function completeConsent(args) {
10139
10198
  refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
10140
10199
  lastRefresh: now
10141
10200
  };
10142
- mkdirSync3(join18(accountDir, "secrets"), { recursive: true });
10201
+ mkdirSync3(join19(accountDir, "secrets"), { recursive: true });
10143
10202
  writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
10144
- const persisted = JSON.parse(readFileSync19(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
10203
+ const persisted = JSON.parse(readFileSync20(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
10145
10204
  console.error(`${TAG27} op=token-exchange realmId=${realmId} persisted=${persisted}`);
10146
10205
  return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
10147
10206
  } finally {
@@ -10172,12 +10231,12 @@ var quickbooks_default = app8;
10172
10231
 
10173
10232
  // server/routes/onboarding.ts
10174
10233
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
10175
- import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync14, readFileSync as readFileSync21, unlinkSync as unlinkSync2 } from "fs";
10234
+ import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync2 } from "fs";
10176
10235
  import { createHash as createHash3, randomUUID as randomUUID8 } from "crypto";
10177
10236
 
10178
10237
  // ../lib/admins-write/src/index.ts
10179
- import { existsSync as existsSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync9, renameSync as renameSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync12, statSync as statSync7 } from "fs";
10180
- import { dirname as dirname4, join as join19 } from "path";
10238
+ import { existsSync as existsSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync9, renameSync as renameSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync12, statSync as statSync7 } from "fs";
10239
+ import { dirname as dirname4, join as join20 } from "path";
10181
10240
  function logLine(input, result) {
10182
10241
  const userIdShort = input.userId.slice(0, 8);
10183
10242
  console.error(
@@ -10195,7 +10254,7 @@ function writeAdminEntry(input) {
10195
10254
  try {
10196
10255
  let users = [];
10197
10256
  if (existsSync13(input.usersFile)) {
10198
- const raw = readFileSync20(input.usersFile, "utf-8").trim();
10257
+ const raw = readFileSync21(input.usersFile, "utf-8").trim();
10199
10258
  if (raw) {
10200
10259
  const parsed = JSON.parse(raw);
10201
10260
  if (!Array.isArray(parsed)) {
@@ -10219,11 +10278,11 @@ function writeAdminEntry(input) {
10219
10278
  return result;
10220
10279
  }
10221
10280
  try {
10222
- const accountJsonPath = join19(input.accountDir, "account.json");
10281
+ const accountJsonPath = join20(input.accountDir, "account.json");
10223
10282
  if (!existsSync13(accountJsonPath)) {
10224
10283
  throw new Error(`account.json not found at ${accountJsonPath}`);
10225
10284
  }
10226
- const config = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
10285
+ const config = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
10227
10286
  const admins = config.admins ?? [];
10228
10287
  if (admins.some((a) => a.userId === input.userId)) {
10229
10288
  result.accountJsonResult = "noop";
@@ -10249,7 +10308,7 @@ function checkAdminAuthInvariant(input) {
10249
10308
  const usersUserIds = /* @__PURE__ */ new Set();
10250
10309
  if (existsSync13(input.usersFile)) {
10251
10310
  try {
10252
- const raw = readFileSync20(input.usersFile, "utf-8").trim();
10311
+ const raw = readFileSync21(input.usersFile, "utf-8").trim();
10253
10312
  if (raw) {
10254
10313
  const users = JSON.parse(raw);
10255
10314
  for (const u of users) {
@@ -10274,17 +10333,17 @@ function checkAdminAuthInvariant(input) {
10274
10333
  }
10275
10334
  for (const entry of entries) {
10276
10335
  if (entry.startsWith(".")) continue;
10277
- const accountDir = join19(input.accountsDir, entry);
10336
+ const accountDir = join20(input.accountsDir, entry);
10278
10337
  try {
10279
10338
  if (!statSync7(accountDir).isDirectory()) continue;
10280
10339
  } catch {
10281
10340
  continue;
10282
10341
  }
10283
- const accountJsonPath = join19(accountDir, "account.json");
10342
+ const accountJsonPath = join20(accountDir, "account.json");
10284
10343
  if (!existsSync13(accountJsonPath)) continue;
10285
10344
  let admins = [];
10286
10345
  try {
10287
- const config = JSON.parse(readFileSync20(accountJsonPath, "utf-8"));
10346
+ const config = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
10288
10347
  admins = config.admins ?? [];
10289
10348
  } catch (err) {
10290
10349
  const msg = err instanceof Error ? err.message : String(err);
@@ -10325,7 +10384,7 @@ function hashPin2(pin) {
10325
10384
  }
10326
10385
  function readUsersFile2() {
10327
10386
  if (!existsSync14(USERS_FILE)) return null;
10328
- const raw = readFileSync21(USERS_FILE, "utf-8").trim();
10387
+ const raw = readFileSync22(USERS_FILE, "utf-8").trim();
10329
10388
  if (!raw) return [];
10330
10389
  return JSON.parse(raw);
10331
10390
  }
@@ -10487,7 +10546,7 @@ app9.post("/set-pin", async (c) => {
10487
10546
  let installOwner = null;
10488
10547
  if (existsSync14(INSTALL_OWNER_FILE)) {
10489
10548
  try {
10490
- const raw = readFileSync21(INSTALL_OWNER_FILE, "utf-8").trim();
10549
+ const raw = readFileSync22(INSTALL_OWNER_FILE, "utf-8").trim();
10491
10550
  if (raw.length > 0) installOwner = raw;
10492
10551
  } catch (err) {
10493
10552
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -10569,8 +10628,8 @@ var onboarding_default = app9;
10569
10628
 
10570
10629
  // server/routes/client-error.ts
10571
10630
  import { appendFileSync, existsSync as existsSync15, renameSync as renameSync6, statSync as statSync8 } from "fs";
10572
- import { join as join20 } from "path";
10573
- var CLIENT_ERRORS_LOG = join20(LOG_DIR, "client-errors.log");
10631
+ import { join as join21 } from "path";
10632
+ var CLIENT_ERRORS_LOG = join21(LOG_DIR, "client-errors.log");
10574
10633
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
10575
10634
  var MAX_BODY_SIZE = 8 * 1024;
10576
10635
  var MAX_STACK_LEN = 2e3;
@@ -10895,17 +10954,17 @@ app11.post("/", async (c) => {
10895
10954
  var session_default = app11;
10896
10955
 
10897
10956
  // server/routes/admin/logs.ts
10898
- import { existsSync as existsSync17, readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync9 } from "fs";
10957
+ import { existsSync as existsSync17, readdirSync as readdirSync13, readFileSync as readFileSync23, statSync as statSync9 } from "fs";
10899
10958
  import { resolve as resolve18, basename as basename6 } from "path";
10900
10959
 
10901
10960
  // app/lib/logs-read-resolve.ts
10902
10961
  import { existsSync as existsSync16 } from "fs";
10903
- import { join as join21 } from "path";
10962
+ import { join as join22 } from "path";
10904
10963
  function resolveSessionLogPaths(filename, logDirs) {
10905
10964
  const tried = [filename];
10906
10965
  const hits = [];
10907
10966
  for (const dir of logDirs) {
10908
- const fullPath = join21(dir, filename);
10967
+ const fullPath = join22(dir, filename);
10909
10968
  if (existsSync16(fullPath)) {
10910
10969
  hits.push({ path: fullPath, dir });
10911
10970
  }
@@ -10934,7 +10993,7 @@ app12.get("/", async (c) => {
10934
10993
  const filePath = resolve18(dir, safe);
10935
10994
  searched.push(filePath);
10936
10995
  try {
10937
- const buffer = readFileSync22(filePath);
10996
+ const buffer = readFileSync23(filePath);
10938
10997
  const onDiskBytes = statSync9(filePath).size;
10939
10998
  const headers = {
10940
10999
  "Content-Type": "text/plain; charset=utf-8",
@@ -10999,7 +11058,7 @@ app12.get("/", async (c) => {
10999
11058
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
11000
11059
  try {
11001
11060
  const filename = basename6(hit.path);
11002
- const buffer = readFileSync22(hit.path);
11061
+ const buffer = readFileSync23(hit.path);
11003
11062
  const onDiskBytes = statSync9(hit.path).size;
11004
11063
  const headers = {
11005
11064
  "Content-Type": "text/plain; charset=utf-8",
@@ -11046,7 +11105,7 @@ app12.get("/", async (c) => {
11046
11105
  files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync9(resolve18(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
11047
11106
  seen.add(name);
11048
11107
  try {
11049
- const content = readFileSync22(resolve18(dir, name));
11108
+ const content = readFileSync23(resolve18(dir, name));
11050
11109
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
11051
11110
  logs[name] = tail.trim() || "(empty)";
11052
11111
  } catch (err) {
@@ -11131,7 +11190,7 @@ var attachment_default = app14;
11131
11190
 
11132
11191
  // server/routes/admin/agents.ts
11133
11192
  import { resolve as resolve20 } from "path";
11134
- import { readdirSync as readdirSync14, readFileSync as readFileSync23, existsSync as existsSync19, rmSync as rmSync2 } from "fs";
11193
+ import { readdirSync as readdirSync14, readFileSync as readFileSync24, existsSync as existsSync19, rmSync as rmSync2 } from "fs";
11135
11194
  var app15 = new Hono();
11136
11195
  app15.get("/", (c) => {
11137
11196
  const account = resolveAccount();
@@ -11147,7 +11206,7 @@ app15.get("/", (c) => {
11147
11206
  const configPath2 = resolve20(agentsDir, entry.name, "config.json");
11148
11207
  if (!existsSync19(configPath2)) continue;
11149
11208
  try {
11150
- const config = JSON.parse(readFileSync23(configPath2, "utf-8"));
11209
+ const config = JSON.parse(readFileSync24(configPath2, "utf-8"));
11151
11210
  agents.push({
11152
11211
  slug: entry.name,
11153
11212
  displayName: config.displayName ?? entry.name,
@@ -11906,8 +11965,8 @@ app16.put("/:id/label", requireAdminSession, async (c) => {
11906
11965
  var sessions_default = app16;
11907
11966
 
11908
11967
  // app/lib/claude-agent/spawn-context.ts
11909
- import { existsSync as existsSync21, readFileSync as readFileSync24, readdirSync as readdirSync15, statSync as statSync10 } from "fs";
11910
- import { dirname as dirname5, resolve as resolve21, join as join22 } from "path";
11968
+ import { existsSync as existsSync21, readFileSync as readFileSync25, readdirSync as readdirSync15, statSync as statSync10 } from "fs";
11969
+ import { dirname as dirname5, resolve as resolve21, join as join23 } from "path";
11911
11970
  async function resolveOwnerProfileBlock(accountId, userId) {
11912
11971
  if (!userId) return { ok: false, reason: "missing-user-id" };
11913
11972
  try {
@@ -11948,14 +12007,14 @@ function frontmatterField(manifest, field2) {
11948
12007
  function extractPluginToolDescriptions(pluginDir) {
11949
12008
  const out = /* @__PURE__ */ new Map();
11950
12009
  const candidates = [
11951
- join22(pluginDir, "mcp/dist/index.js"),
11952
- join22(pluginDir, "mcp/src/index.ts")
12010
+ join23(pluginDir, "mcp/dist/index.js"),
12011
+ join23(pluginDir, "mcp/src/index.ts")
11953
12012
  ];
11954
12013
  let raw = null;
11955
12014
  for (const path2 of candidates) {
11956
12015
  if (!existsSync21(path2)) continue;
11957
12016
  try {
11958
- raw = readFileSync24(path2, "utf-8");
12017
+ raw = readFileSync25(path2, "utf-8");
11959
12018
  break;
11960
12019
  } catch {
11961
12020
  }
@@ -12007,7 +12066,7 @@ function listPluginDirs() {
12007
12066
  const platformPlugins = resolve21(PLATFORM_ROOT, "plugins");
12008
12067
  if (existsSync21(platformPlugins)) {
12009
12068
  for (const name of readdirSync15(platformPlugins)) {
12010
- const dir = join22(platformPlugins, name);
12069
+ const dir = join23(platformPlugins, name);
12011
12070
  try {
12012
12071
  if (statSync10(dir).isDirectory()) out.set(name, dir);
12013
12072
  } catch {
@@ -12017,11 +12076,11 @@ function listPluginDirs() {
12017
12076
  const premiumRoot = resolve21(dirname5(PLATFORM_ROOT), "premium-plugins");
12018
12077
  if (existsSync21(premiumRoot)) {
12019
12078
  for (const bundle of readdirSync15(premiumRoot)) {
12020
- const bundlePlugins = join22(premiumRoot, bundle, "plugins");
12079
+ const bundlePlugins = join23(premiumRoot, bundle, "plugins");
12021
12080
  if (!existsSync21(bundlePlugins)) continue;
12022
12081
  try {
12023
12082
  for (const name of readdirSync15(bundlePlugins)) {
12024
- const dir = join22(bundlePlugins, name);
12083
+ const dir = join23(bundlePlugins, name);
12025
12084
  try {
12026
12085
  if (statSync10(dir).isDirectory()) out.set(name, dir);
12027
12086
  } catch {
@@ -12037,7 +12096,7 @@ function readEnabledPlugins(accountId) {
12037
12096
  const accountFile = resolve21(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12038
12097
  if (!existsSync21(accountFile)) return /* @__PURE__ */ new Set();
12039
12098
  try {
12040
- const parsed = JSON.parse(readFileSync24(accountFile, "utf-8"));
12099
+ const parsed = JSON.parse(readFileSync25(accountFile, "utf-8"));
12041
12100
  return new Set(
12042
12101
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
12043
12102
  );
@@ -12049,7 +12108,7 @@ function readFrontmatter(path2) {
12049
12108
  if (!existsSync21(path2)) return null;
12050
12109
  let raw;
12051
12110
  try {
12052
- raw = readFileSync24(path2, "utf-8");
12111
+ raw = readFileSync25(path2, "utf-8");
12053
12112
  } catch {
12054
12113
  return null;
12055
12114
  }
@@ -12064,7 +12123,7 @@ function computeActivePlugins(accountId) {
12064
12123
  for (const name of Array.from(enabled).sort()) {
12065
12124
  const dir = pluginDirs.get(name);
12066
12125
  if (!dir) continue;
12067
- const fm = readFrontmatter(join22(dir, "PLUGIN.md"));
12126
+ const fm = readFrontmatter(join23(dir, "PLUGIN.md"));
12068
12127
  if (!fm) continue;
12069
12128
  const description = frontmatterField(`---
12070
12129
  ${fm}
@@ -12081,7 +12140,7 @@ ${fm}
12081
12140
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
12082
12141
  );
12083
12142
  if (toolNames.length > 0 && descMap.size === 0) {
12084
- const hasSource = existsSync21(join22(dir, "mcp/dist/index.js")) || existsSync21(join22(dir, "mcp/src/index.ts"));
12143
+ const hasSource = existsSync21(join23(dir, "mcp/dist/index.js")) || existsSync21(join23(dir, "mcp/src/index.ts"));
12085
12144
  if (hasSource) {
12086
12145
  console.warn(
12087
12146
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -12091,7 +12150,7 @@ ${fm}
12091
12150
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
12092
12151
  const skills = [];
12093
12152
  for (const relPath of skillPaths) {
12094
- const skillPath = join22(dir, relPath);
12153
+ const skillPath = join23(dir, relPath);
12095
12154
  const skillFm = readFrontmatter(skillPath);
12096
12155
  if (!skillFm) continue;
12097
12156
  const skillName = frontmatterField(`---
@@ -12135,7 +12194,7 @@ function computeSpecialistDomains(accountId) {
12135
12194
  const out = [];
12136
12195
  for (const file of entries.sort()) {
12137
12196
  if (!file.endsWith(".md")) continue;
12138
- const fm = readFrontmatter(join22(specialistsDir, file));
12197
+ const fm = readFrontmatter(join23(specialistsDir, file));
12139
12198
  if (!fm) continue;
12140
12199
  const wrapped = `---
12141
12200
  ${fm}
@@ -12157,7 +12216,7 @@ function computeDormantPlugins(accountId) {
12157
12216
  if (!existsSync21(accountFile)) return [];
12158
12217
  let enabled;
12159
12218
  try {
12160
- const raw = readFileSync24(accountFile, "utf-8");
12219
+ const raw = readFileSync25(accountFile, "utf-8");
12161
12220
  const parsed = JSON.parse(raw);
12162
12221
  enabled = new Set(
12163
12222
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
@@ -12183,7 +12242,7 @@ function computeDormantPlugins(accountId) {
12183
12242
  if (!existsSync21(manifestPath)) continue;
12184
12243
  let manifest;
12185
12244
  try {
12186
- manifest = readFileSync24(manifestPath, "utf-8");
12245
+ manifest = readFileSync25(manifestPath, "utf-8");
12187
12246
  } catch {
12188
12247
  continue;
12189
12248
  }
@@ -12197,13 +12256,13 @@ function computeDormantPlugins(accountId) {
12197
12256
  }
12198
12257
 
12199
12258
  // server/routes/admin/claude-sessions.ts
12200
- import { existsSync as existsSync22, readFileSync as readFileSync25 } from "fs";
12259
+ import { existsSync as existsSync22, readFileSync as readFileSync26 } from "fs";
12201
12260
  import { resolve as resolve22 } from "path";
12202
12261
  function readTunnelState(brandConfigDir) {
12203
12262
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
12204
12263
  if (!existsSync22(statePath)) return null;
12205
12264
  try {
12206
- const parsed = JSON.parse(readFileSync25(statePath, "utf-8"));
12265
+ const parsed = JSON.parse(readFileSync26(statePath, "utf-8"));
12207
12266
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
12208
12267
  const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
12209
12268
  const domain = typeof parsed.domain === "string" ? parsed.domain : null;
@@ -12217,7 +12276,7 @@ function resolveTunnelUrl() {
12217
12276
  const platformRoot4 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
12218
12277
  let brand;
12219
12278
  try {
12220
- brand = JSON.parse(readFileSync25(resolve22(platformRoot4, "config", "brand.json"), "utf-8"));
12279
+ brand = JSON.parse(readFileSync26(resolve22(platformRoot4, "config", "brand.json"), "utf-8"));
12221
12280
  } catch {
12222
12281
  return null;
12223
12282
  }
@@ -12463,7 +12522,7 @@ import { createReadStream as createReadStream2, createWriteStream as createWrite
12463
12522
  import { readdir as readdir3, readFile as readFile5, stat as stat5, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
12464
12523
  import { realpathSync as realpathSync6 } from "fs";
12465
12524
  import { randomUUID as randomUUID10 } from "crypto";
12466
- import { basename as basename8, dirname as dirname6, join as join24, resolve as resolve24, sep as sep6 } from "path";
12525
+ import { basename as basename8, dirname as dirname6, join as join25, resolve as resolve24, sep as sep6 } from "path";
12467
12526
  import { Readable as Readable2 } from "stream";
12468
12527
 
12469
12528
  // ../lib/graph-trash/src/index.ts
@@ -12781,7 +12840,7 @@ async function cascadeDeleteDocument(params) {
12781
12840
 
12782
12841
  // app/lib/file-index.ts
12783
12842
  import * as fsp from "fs/promises";
12784
- import { resolve as resolve23, relative as relative3, join as join23, basename as basename7, extname as extname2, sep as sep5 } from "path";
12843
+ import { resolve as resolve23, relative as relative3, join as join24, basename as basename7, extname as extname2, sep as sep5 } from "path";
12785
12844
  import { tmpdir as tmpdir2 } from "os";
12786
12845
  import { execFile as execFile2 } from "child_process";
12787
12846
  import { promisify as promisify2 } from "util";
@@ -12863,7 +12922,7 @@ async function extractPdf(absolute) {
12863
12922
  return stdout.trim();
12864
12923
  }
12865
12924
  async function ocrPdf(absolute) {
12866
- const outPdf = join23(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
12925
+ const outPdf = join24(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
12867
12926
  try {
12868
12927
  await execFileAsync2(
12869
12928
  "ocrmypdf",
@@ -12925,7 +12984,7 @@ async function readDisplayName(absolute) {
12925
12984
  const stem = dot === -1 ? base : base.slice(0, dot);
12926
12985
  if (base === `${stem}.meta.json`) return null;
12927
12986
  try {
12928
- const raw = await fsp.readFile(join23(dir, `${stem}.meta.json`), "utf-8");
12987
+ const raw = await fsp.readFile(join24(dir, `${stem}.meta.json`), "utf-8");
12929
12988
  const meta = JSON.parse(raw);
12930
12989
  const dn = meta.displayName ?? meta.filename;
12931
12990
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -12946,7 +13005,7 @@ async function walkSubtree(root, dataRoot, out) {
12946
13005
  for (const entry of entries) {
12947
13006
  if (entry.isSymbolicLink()) continue;
12948
13007
  if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
12949
- const abs = join23(root, entry.name);
13008
+ const abs = join24(root, entry.name);
12950
13009
  if (entry.isDirectory()) {
12951
13010
  const sub = await walkSubtree(abs, dataRoot, out);
12952
13011
  if (!sub.clean) clean = false;
@@ -13219,7 +13278,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
13219
13278
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13220
13279
  async function readMeta(absDir, baseName) {
13221
13280
  try {
13222
- const raw = await readFile5(join24(absDir, `${baseName}.meta.json`), "utf8");
13281
+ const raw = await readFile5(join25(absDir, `${baseName}.meta.json`), "utf8");
13223
13282
  const parsed = JSON.parse(raw);
13224
13283
  if (typeof parsed?.filename === "string") {
13225
13284
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -13257,7 +13316,7 @@ async function readAccountNames() {
13257
13316
  }
13258
13317
  async function enrich(absolute, entry, accountNames) {
13259
13318
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
13260
- const meta = await readMeta(join24(absolute, entry.name), entry.name);
13319
+ const meta = await readMeta(join25(absolute, entry.name), entry.name);
13261
13320
  if (meta?.filename) {
13262
13321
  entry.displayName = meta.filename;
13263
13322
  entry.mimeType = meta.mimeType;
@@ -13421,7 +13480,7 @@ app20.get("/", requireAdminSession, async (c) => {
13421
13480
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
13422
13481
  const protectedEntry = isProtectedFromDeletion(childRel).protected;
13423
13482
  try {
13424
- const entryPath = join24(absolute, name);
13483
+ const entryPath = join25(absolute, name);
13425
13484
  const s = await stat5(entryPath);
13426
13485
  entries.push({
13427
13486
  name,
@@ -13562,7 +13621,7 @@ app20.post("/upload", requireAdminSession, async (c) => {
13562
13621
  const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
13563
13622
  if (!base.ok) return c.json({ error: base.error }, base.status);
13564
13623
  const relDir = relpath ? dirname6(relpath) : ".";
13565
- const destRel = relDir === "." ? base.relative : join24(base.relative, relDir);
13624
+ const destRel = relDir === "." ? base.relative : join25(base.relative, relDir);
13566
13625
  if (crossesForeignAccountPartition(destRel, accountId)) {
13567
13626
  console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
13568
13627
  return c.json({ error: "Not found" }, 404);
@@ -13739,7 +13798,7 @@ app20.delete("/", requireAdminSession, async (c) => {
13739
13798
  }
13740
13799
  const dot = base.lastIndexOf(".");
13741
13800
  const stem = dot === -1 ? base : base.slice(0, dot);
13742
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join24(dirname6(absolute), `${stem}.meta.json`) : null;
13801
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join25(dirname6(absolute), `${stem}.meta.json`) : null;
13743
13802
  await unlink2(absolute);
13744
13803
  if (sidecarPath) {
13745
13804
  try {
@@ -16215,6 +16274,7 @@ var session_rename_default = app31;
16215
16274
 
16216
16275
  // server/routes/admin/session-rc-spawn.ts
16217
16276
  import { randomUUID as randomUUID11 } from "crypto";
16277
+ 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}$/;
16218
16278
  function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID11, adminUserId, authenticatedName) {
16219
16279
  const operator = isOperatorHost(host, operatorDomains);
16220
16280
  const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
@@ -16225,6 +16285,7 @@ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID11, ad
16225
16285
  const pickedModel = kind === "new" && typeof body.model === "string" && isSelectableModel(body.model) ? body.model : null;
16226
16286
  const pickedEffort = kind === "new" && typeof body.effort === "string" && isNewSessionEffortLevel(body.effort) ? body.effort : null;
16227
16287
  const paramsSource = pickedModel !== null && pickedEffort !== null ? "picker" : "default";
16288
+ const targetAccountId = typeof body.targetAccountId === "string" && ACCOUNT_UUID_RE2.test(body.targetAccountId) ? body.targetAccountId : void 0;
16228
16289
  const payload = {};
16229
16290
  let sessionId;
16230
16291
  if (webchatBind) {
@@ -16239,6 +16300,7 @@ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID11, ad
16239
16300
  if (pickedModel) payload.model = pickedModel;
16240
16301
  if (pickedEffort) payload.effort = pickedEffort;
16241
16302
  if (adminUserId) payload.adminUserId = adminUserId;
16303
+ if (targetAccountId) payload.targetAccountId = targetAccountId;
16242
16304
  if (authenticatedName) payload.authenticatedName = authenticatedName;
16243
16305
  } else {
16244
16306
  sessionId = resumeId;
@@ -16549,14 +16611,14 @@ app34.get("/", async (c) => {
16549
16611
  var system_stats_default = app34;
16550
16612
 
16551
16613
  // server/routes/admin/health.ts
16552
- import { existsSync as existsSync25, readFileSync as readFileSync26 } from "fs";
16553
- import { resolve as resolve26, join as join25 } from "path";
16614
+ import { existsSync as existsSync25, readFileSync as readFileSync27 } from "fs";
16615
+ import { resolve as resolve26, join as join26 } from "path";
16554
16616
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
16555
16617
  var brandHostname = "maxy";
16556
- var brandJsonPath = join25(PLATFORM_ROOT6, "config", "brand.json");
16618
+ var brandJsonPath = join26(PLATFORM_ROOT6, "config", "brand.json");
16557
16619
  if (existsSync25(brandJsonPath)) {
16558
16620
  try {
16559
- const brand = JSON.parse(readFileSync26(brandJsonPath, "utf-8"));
16621
+ const brand = JSON.parse(readFileSync27(brandJsonPath, "utf-8"));
16560
16622
  if (brand.hostname) brandHostname = brand.hostname;
16561
16623
  } catch {
16562
16624
  }
@@ -16566,7 +16628,7 @@ var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
16566
16628
  var PROBE_TIMEOUT_MS = 1e3;
16567
16629
  function readVersion() {
16568
16630
  if (!existsSync25(VERSION_FILE)) return "unknown";
16569
- return readFileSync26(VERSION_FILE, "utf-8").trim() || "unknown";
16631
+ return readFileSync27(VERSION_FILE, "utf-8").trim() || "unknown";
16570
16632
  }
16571
16633
  async function probeConversationDb() {
16572
16634
  let session;
@@ -17465,7 +17527,7 @@ app46.route("/request-magic-link", request_magic_link_default);
17465
17527
  var access_default = app46;
17466
17528
 
17467
17529
  // server/routes/sites.ts
17468
- import { existsSync as existsSync26, readFileSync as readFileSync27, realpathSync as realpathSync7, statSync as statSync11 } from "fs";
17530
+ import { existsSync as existsSync26, readFileSync as readFileSync28, realpathSync as realpathSync7, statSync as statSync11 } from "fs";
17469
17531
  import { resolve as resolve28 } from "path";
17470
17532
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
17471
17533
  var MIME = {
@@ -17569,7 +17631,7 @@ app47.get("/:rel{.*}", (c) => {
17569
17631
  }
17570
17632
  let body;
17571
17633
  try {
17572
- body = readFileSync27(realPath);
17634
+ body = readFileSync28(realPath);
17573
17635
  } catch (err) {
17574
17636
  const code = err?.code;
17575
17637
  if (code === "EISDIR") {
@@ -17605,7 +17667,7 @@ var sites_default = app47;
17605
17667
 
17606
17668
  // app/lib/visitor-token.ts
17607
17669
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
17608
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync28, writeFileSync as writeFileSync11 } from "fs";
17670
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync29, writeFileSync as writeFileSync11 } from "fs";
17609
17671
  import { dirname as dirname7 } from "path";
17610
17672
  var TOKEN_PREFIX = "v1.";
17611
17673
  var SECRET_BYTES = 32;
@@ -17614,7 +17676,7 @@ var cachedSecret = null;
17614
17676
  function getSecret() {
17615
17677
  if (cachedSecret) return cachedSecret;
17616
17678
  try {
17617
- const hex2 = readFileSync28(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
17679
+ const hex2 = readFileSync29(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
17618
17680
  if (hex2.length === SECRET_BYTES * 2) {
17619
17681
  cachedSecret = Buffer.from(hex2, "hex");
17620
17682
  return cachedSecret;
@@ -17628,7 +17690,7 @@ function getSecret() {
17628
17690
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
17629
17691
  } catch {
17630
17692
  }
17631
- const hex = readFileSync28(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
17693
+ const hex = readFileSync29(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
17632
17694
  cachedSecret = Buffer.from(hex, "hex");
17633
17695
  return cachedSecret;
17634
17696
  }
@@ -17681,8 +17743,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
17681
17743
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
17682
17744
 
17683
17745
  // app/lib/brand-config.ts
17684
- import { existsSync as existsSync27, readFileSync as readFileSync29 } from "fs";
17685
- import { join as join26 } from "path";
17746
+ import { existsSync as existsSync27, readFileSync as readFileSync30 } from "fs";
17747
+ import { join as join27 } from "path";
17686
17748
  var cached2 = null;
17687
17749
  var cachedAttempted = false;
17688
17750
  function readBrandConfig() {
@@ -17690,10 +17752,10 @@ function readBrandConfig() {
17690
17752
  cachedAttempted = true;
17691
17753
  const platformRoot4 = process.env.MAXY_PLATFORM_ROOT;
17692
17754
  if (!platformRoot4) return null;
17693
- const brandPath = join26(platformRoot4, "config", "brand.json");
17755
+ const brandPath = join27(platformRoot4, "config", "brand.json");
17694
17756
  if (!existsSync27(brandPath)) return null;
17695
17757
  try {
17696
- cached2 = JSON.parse(readFileSync29(brandPath, "utf-8"));
17758
+ cached2 = JSON.parse(readFileSync30(brandPath, "utf-8"));
17697
17759
  return cached2;
17698
17760
  } catch {
17699
17761
  return null;
@@ -18494,7 +18556,7 @@ function startGraphHealthTimer() {
18494
18556
  // app/lib/file-watcher.ts
18495
18557
  import * as fsp2 from "fs/promises";
18496
18558
  import { resolve as resolve30, sep as sep8 } from "path";
18497
- 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;
18559
+ 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;
18498
18560
  var DEFAULT_COALESCE_MS = 500;
18499
18561
  var ROOTS = ["accounts"];
18500
18562
  function _routeEvent(rootName, filename) {
@@ -18502,7 +18564,7 @@ function _routeEvent(rootName, filename) {
18502
18564
  const segs = filename.split(sep8).filter(Boolean);
18503
18565
  if (segs.length < 2) return null;
18504
18566
  const accountId = segs[0];
18505
- if (!ACCOUNT_UUID_RE2.test(accountId)) return null;
18567
+ if (!ACCOUNT_UUID_RE3.test(accountId)) return null;
18506
18568
  return { accountId, relativePath: `${rootName}/${segs.join("/")}` };
18507
18569
  }
18508
18570
  async function startFileWatcher(opts = {}) {
@@ -18597,7 +18659,7 @@ async function startFileWatcher(opts = {}) {
18597
18659
  // app/lib/migrate-uploads.ts
18598
18660
  import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
18599
18661
  import { dirname as dirname8, relative as relative5, resolve as resolve31 } from "path";
18600
- 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;
18662
+ 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;
18601
18663
  async function walkFiles(dir) {
18602
18664
  const out = [];
18603
18665
  let entries;
@@ -18673,7 +18735,7 @@ async function migrateUploads(opts = {}) {
18673
18735
  try {
18674
18736
  for (const entry of topEntries) {
18675
18737
  const name = entry.name;
18676
- if (ACCOUNT_UUID_RE3.test(name)) {
18738
+ if (ACCOUNT_UUID_RE4.test(name)) {
18677
18739
  moved += await relocateTree(
18678
18740
  resolve31(oldRoot, name),
18679
18741
  resolve31(dataRoot, "accounts", name, "uploads"),
@@ -18720,7 +18782,7 @@ async function migrateUploads(opts = {}) {
18720
18782
  // app/lib/migrate-admin-webchat-sidecars.ts
18721
18783
  import { readdir as readdir6, readFile as readFile7, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
18722
18784
  import { existsSync as existsSync29 } from "fs";
18723
- import { join as join27 } from "path";
18785
+ import { join as join28 } from "path";
18724
18786
  var ADMIN_ROLE2 = "admin";
18725
18787
  var WEBCHAT_CHANNEL2 = "webchat";
18726
18788
  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;
@@ -18765,7 +18827,7 @@ async function collectLiveSidecars(projectsRoot) {
18765
18827
  }
18766
18828
  for (const slug of slugs) {
18767
18829
  if (!slug.isDirectory()) continue;
18768
- const slugDir = join27(projectsRoot, slug.name);
18830
+ const slugDir = join28(projectsRoot, slug.name);
18769
18831
  let entries;
18770
18832
  try {
18771
18833
  entries = await readdir6(slugDir, { withFileTypes: true });
@@ -18774,9 +18836,9 @@ async function collectLiveSidecars(projectsRoot) {
18774
18836
  }
18775
18837
  for (const entry of entries) {
18776
18838
  if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
18777
- out.push(join27(slugDir, entry.name));
18839
+ out.push(join28(slugDir, entry.name));
18778
18840
  } else if (entry.isDirectory() && entry.name === "subagents") {
18779
- const subDir = join27(slugDir, entry.name);
18841
+ const subDir = join28(slugDir, entry.name);
18780
18842
  let subs;
18781
18843
  try {
18782
18844
  subs = await readdir6(subDir, { withFileTypes: true });
@@ -18784,7 +18846,7 @@ async function collectLiveSidecars(projectsRoot) {
18784
18846
  continue;
18785
18847
  }
18786
18848
  for (const s of subs) {
18787
- if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join27(subDir, s.name));
18849
+ if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join28(subDir, s.name));
18788
18850
  }
18789
18851
  }
18790
18852
  }
@@ -18796,7 +18858,7 @@ function shortId(path2) {
18796
18858
  return base.slice(0, 8);
18797
18859
  }
18798
18860
  async function migrateAdminWebchatSidecars(opts = {}) {
18799
- const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join27(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
18861
+ const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join28(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
18800
18862
  const usersFile = opts.usersFile ?? USERS_FILE;
18801
18863
  const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
18802
18864
  const resolveName = opts.resolveName ?? defaultResolveName;
@@ -19622,6 +19684,26 @@ function createWebchatChannelRoutes(deps) {
19622
19684
  deps.onReceived?.(key, messageId);
19623
19685
  return c.json({ ok: true });
19624
19686
  });
19687
+ app53.post("/webchat-channel/turn-end", async (c) => {
19688
+ const body = await c.req.json().catch(() => null);
19689
+ const key = body?.key;
19690
+ const sessionId = body?.sessionId;
19691
+ const replied = body?.replied;
19692
+ if (typeof key !== "string" || typeof sessionId !== "string" || typeof replied !== "boolean") {
19693
+ return c.json({ error: "key, sessionId and replied required" }, 400);
19694
+ }
19695
+ const k = key.slice(0, 8);
19696
+ const sid = sessionId.slice(0, 8);
19697
+ if (replied) {
19698
+ return c.json({ ok: true, delivered: "reply" });
19699
+ }
19700
+ const finalBytes = typeof body?.finalBytes === "number" && Number.isFinite(body.finalBytes) ? body.finalBytes : 0;
19701
+ if (finalBytes <= 0) {
19702
+ return c.json({ ok: true, delivered: "none" });
19703
+ }
19704
+ console.error(`[webchat-native] op=turn-undelivered channel=webchat key=${k} sessionId=${sid} bytes=${finalBytes}`);
19705
+ return c.json({ ok: true, delivered: "undelivered" });
19706
+ });
19625
19707
  return app53;
19626
19708
  }
19627
19709
 
@@ -20114,7 +20196,7 @@ function broadcastAdminShutdown(reason) {
20114
20196
 
20115
20197
  // ../lib/entitlement/src/index.ts
20116
20198
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
20117
- import { existsSync as existsSync30, readFileSync as readFileSync30, statSync as statSync12 } from "fs";
20199
+ import { existsSync as existsSync30, readFileSync as readFileSync31, statSync as statSync12 } from "fs";
20118
20200
  import { resolve as resolve32 } from "path";
20119
20201
 
20120
20202
  // ../lib/entitlement/src/canonicalize.ts
@@ -20178,7 +20260,7 @@ function resolveEntitlement(brand, account) {
20178
20260
  function verifyAndResolve(brand, entitlementPath, account) {
20179
20261
  let pubkeyPem;
20180
20262
  try {
20181
- pubkeyPem = readFileSync30(pubkeyPath(brand), "utf-8");
20263
+ pubkeyPem = readFileSync31(pubkeyPath(brand), "utf-8");
20182
20264
  } catch (err) {
20183
20265
  return logResolved(anonymousFallback("pubkey-missing"), {
20184
20266
  reason: "pubkey-missing"
@@ -20192,7 +20274,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
20192
20274
  }
20193
20275
  let envelope;
20194
20276
  try {
20195
- envelope = JSON.parse(readFileSync30(entitlementPath, "utf-8"));
20277
+ envelope = JSON.parse(readFileSync31(entitlementPath, "utf-8"));
20196
20278
  } catch {
20197
20279
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
20198
20280
  }
@@ -20353,14 +20435,14 @@ function clientFrom(c) {
20353
20435
  );
20354
20436
  }
20355
20437
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
20356
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join28(PLATFORM_ROOT8, "config", "brand.json") : "";
20438
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join29(PLATFORM_ROOT8, "config", "brand.json") : "";
20357
20439
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
20358
20440
  if (BRAND_JSON_PATH && !existsSync31(BRAND_JSON_PATH)) {
20359
20441
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
20360
20442
  }
20361
20443
  if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
20362
20444
  try {
20363
- const parsed = JSON.parse(readFileSync31(BRAND_JSON_PATH, "utf-8"));
20445
+ const parsed = JSON.parse(readFileSync32(BRAND_JSON_PATH, "utf-8"));
20364
20446
  BRAND = { ...BRAND, ...parsed };
20365
20447
  } catch (err) {
20366
20448
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -20379,11 +20461,11 @@ var brandLoginOpts = {
20379
20461
  bodyFont: BRAND.defaultFonts?.body,
20380
20462
  logoContainsName: !!BRAND.logoContainsName
20381
20463
  };
20382
- var ALIAS_DOMAINS_PATH = join28(homedir3(), BRAND.configDir, "alias-domains.json");
20464
+ var ALIAS_DOMAINS_PATH = join29(homedir3(), BRAND.configDir, "alias-domains.json");
20383
20465
  function loadAliasDomains() {
20384
20466
  try {
20385
20467
  if (!existsSync31(ALIAS_DOMAINS_PATH)) return null;
20386
- const parsed = JSON.parse(readFileSync31(ALIAS_DOMAINS_PATH, "utf-8"));
20468
+ const parsed = JSON.parse(readFileSync32(ALIAS_DOMAINS_PATH, "utf-8"));
20387
20469
  if (!Array.isArray(parsed)) {
20388
20470
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
20389
20471
  return null;
@@ -20411,7 +20493,7 @@ var app52 = new Hono();
20411
20493
  var nativeFileFollowers = /* @__PURE__ */ new Map();
20412
20494
  var waGateway = new WaGateway({
20413
20495
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
20414
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join28(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
20496
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join29(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
20415
20497
  // Task 751 — file delivery on the native channel: resolve the platform
20416
20498
  // account + path validation here and funnel through the shared send core.
20417
20499
  sendDocument: async ({ senderId, accountId, filePath, caption }) => {
@@ -20427,7 +20509,7 @@ var waGateway = new WaGateway({
20427
20509
  caption,
20428
20510
  accountId,
20429
20511
  maxyAccountId,
20430
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join28(__dirname, ".."))
20512
+ platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join29(__dirname, ".."))
20431
20513
  });
20432
20514
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
20433
20515
  },
@@ -20902,7 +20984,7 @@ app52.get("/agent-assets/:slug/:filename", (c) => {
20902
20984
  const ext = "." + filename.split(".").pop()?.toLowerCase();
20903
20985
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
20904
20986
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
20905
- const body = readFileSync31(filePath);
20987
+ const body = readFileSync32(filePath);
20906
20988
  return c.body(body, 200, {
20907
20989
  "Content-Type": contentType,
20908
20990
  "Cache-Control": "public, max-age=3600"
@@ -20932,7 +21014,7 @@ app52.get("/generated/:filename", (c) => {
20932
21014
  const ext = "." + filename.split(".").pop()?.toLowerCase();
20933
21015
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
20934
21016
  console.log(`[generated] serve file=${filename} status=200`);
20935
- const body = readFileSync31(filePath);
21017
+ const body = readFileSync32(filePath);
20936
21018
  return c.body(body, 200, {
20937
21019
  "Content-Type": contentType,
20938
21020
  "Cache-Control": "public, max-age=86400"
@@ -20947,19 +21029,29 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
20947
21029
  var brandIconPath = "/brand/maxy-monochrome.png";
20948
21030
  if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
20949
21031
  try {
20950
- const fullBrand = JSON.parse(readFileSync31(BRAND_JSON_PATH, "utf-8"));
21032
+ const fullBrand = JSON.parse(readFileSync32(BRAND_JSON_PATH, "utf-8"));
20951
21033
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
20952
21034
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
20953
21035
  } catch {
20954
21036
  }
20955
21037
  }
21038
+ var DEFAULT_PRIMARY_CONTAINER = { label: "Project", term: "Projects" };
21039
+ var rawPrimaryContainer = BRAND.primaryContainer;
21040
+ var primaryContainerValid = !!rawPrimaryContainer && typeof rawPrimaryContainer.label === "string" && typeof rawPrimaryContainer.term === "string";
21041
+ var brandPrimaryContainer = primaryContainerValid ? rawPrimaryContainer : DEFAULT_PRIMARY_CONTAINER;
21042
+ if (primaryContainerValid) {
21043
+ console.log(`[brand] op=inject primaryContainer=${brandPrimaryContainer.label}/${brandPrimaryContainer.term}`);
21044
+ } else {
21045
+ console.log(`[brand] op=primaryContainer-default reason=${rawPrimaryContainer ? "malformed" : "absent"} brand=${BRAND.hostname}`);
21046
+ }
20956
21047
  var brandScript = `<script>window.__BRAND__=${JSON.stringify({
20957
21048
  productName: BRAND.productName,
20958
21049
  hostname: BRAND.hostname,
20959
21050
  marketingUrl: BRAND.marketingUrl,
20960
21051
  logo: brandLogoPath,
20961
21052
  icon: brandIconPath,
20962
- logoContainsName: !!BRAND.logoContainsName
21053
+ logoContainsName: !!BRAND.logoContainsName,
21054
+ primaryContainer: brandPrimaryContainer
20963
21055
  })}</script>`;
20964
21056
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
20965
21057
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
@@ -20967,7 +21059,7 @@ var brandIconFsPath = resolve33(process.cwd(), "public", brandIconPath.replace(/
20967
21059
  var brandIconExists = existsSync31(brandIconFsPath);
20968
21060
  var SW_SOURCE = (() => {
20969
21061
  try {
20970
- return readFileSync31(resolve33(process.cwd(), "public", "sw.js"), "utf-8");
21062
+ return readFileSync32(resolve33(process.cwd(), "public", "sw.js"), "utf-8");
20971
21063
  } catch {
20972
21064
  return null;
20973
21065
  }
@@ -20975,9 +21067,9 @@ var SW_SOURCE = (() => {
20975
21067
  function readInstalledVersion() {
20976
21068
  try {
20977
21069
  if (!PLATFORM_ROOT8) return "unknown";
20978
- const versionFile = join28(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
21070
+ const versionFile = join29(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
20979
21071
  if (!existsSync31(versionFile)) return "unknown";
20980
- const content = readFileSync31(versionFile, "utf-8").trim();
21072
+ const content = readFileSync32(versionFile, "utf-8").trim();
20981
21073
  return content || "unknown";
20982
21074
  } catch {
20983
21075
  return "unknown";
@@ -21018,7 +21110,7 @@ var clientErrorReporterScript = `<script>
21018
21110
  function cachedHtml(file) {
21019
21111
  let html = htmlCache.get(file);
21020
21112
  if (!html) {
21021
- html = readFileSync31(resolve33(process.cwd(), "public", file), "utf-8");
21113
+ html = readFileSync32(resolve33(process.cwd(), "public", file), "utf-8");
21022
21114
  const productNameEsc = escapeHtml(BRAND.productName);
21023
21115
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
21024
21116
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -21035,13 +21127,13 @@ ${clientErrorReporterScript}
21035
21127
  return html;
21036
21128
  }
21037
21129
  function loadBrandingCache(agentSlug) {
21038
- const configDir2 = join28(homedir3(), BRAND.configDir);
21130
+ const configDir2 = join29(homedir3(), BRAND.configDir);
21039
21131
  try {
21040
21132
  const accountId = getDefaultAccountId();
21041
21133
  if (!accountId) return null;
21042
- const cachePath = join28(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
21134
+ const cachePath = join29(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
21043
21135
  if (!existsSync31(cachePath)) return null;
21044
- return JSON.parse(readFileSync31(cachePath, "utf-8"));
21136
+ return JSON.parse(readFileSync32(cachePath, "utf-8"));
21045
21137
  } catch {
21046
21138
  return null;
21047
21139
  }
@@ -21136,7 +21228,7 @@ app52.use("/vnc-popout.html", logViewerFetch);
21136
21228
  app52.get("/vnc-popout.html", (c) => {
21137
21229
  let html = htmlCache.get("vnc-popout.html");
21138
21230
  if (!html) {
21139
- html = readFileSync31(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
21231
+ html = readFileSync32(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
21140
21232
  const name = escapeHtml(BRAND.productName);
21141
21233
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
21142
21234
  html = html.replace("</head>", ` ${brandScript}
@@ -21347,7 +21439,7 @@ async function runAdminUserReconcileTick() {
21347
21439
  console.error("[adminuser-self-heal] skip reason=no-users-file");
21348
21440
  return;
21349
21441
  }
21350
- const usersRaw = readFileSync31(USERS_FILE, "utf-8").trim();
21442
+ const usersRaw = readFileSync32(USERS_FILE, "utf-8").trim();
21351
21443
  if (!usersRaw) {
21352
21444
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
21353
21445
  return;
@@ -21461,7 +21553,7 @@ if (bootAccountConfig?.whatsapp) {
21461
21553
  }
21462
21554
  init({
21463
21555
  configDir: configDirForWhatsApp,
21464
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join28(__dirname, "..")),
21556
+ platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join29(__dirname, "..")),
21465
21557
  accountConfig: bootAccountConfig,
21466
21558
  onMessage: async (msg) => {
21467
21559
  if (msg.isOwnerMirror) {