@rubytech/create-realagent 1.0.831 → 1.0.833

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 (87) hide show
  1. package/dist/index.js +131 -9
  2. package/package.json +1 -1
  3. package/payload/platform/lib/admins-write/dist/index.d.ts +87 -0
  4. package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -0
  5. package/payload/platform/lib/admins-write/dist/index.js +248 -0
  6. package/payload/platform/lib/admins-write/dist/index.js.map +1 -0
  7. package/payload/platform/lib/admins-write/src/index.ts +311 -0
  8. package/payload/platform/lib/admins-write/tsconfig.json +8 -0
  9. package/payload/platform/neo4j/migrations/004-project-admin-agent.ts +36 -3
  10. package/payload/platform/neo4j/migrations/009-conversation-archive-title.ts +197 -0
  11. package/payload/platform/neo4j/schema.cypher +1 -1
  12. package/payload/platform/package.json +2 -2
  13. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  14. package/payload/platform/plugins/admin/mcp/dist/index.js +37 -44
  15. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  16. package/payload/platform/plugins/docs/references/internals.md +4 -3
  17. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +455 -140
  18. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +47 -15
  19. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +75 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
  21. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +16 -10
  22. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +155 -100
  24. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts +13 -5
  26. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts.map +1 -1
  27. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +53 -59
  28. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +1 -1
  29. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.d.ts +3 -0
  30. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.d.ts.map +1 -0
  31. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js +12 -0
  32. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js.map +1 -0
  33. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +28 -0
  34. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +35 -9
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  37. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +64 -12
  38. package/payload/platform/scripts/lib/resolve-account-dir.sh +22 -2
  39. package/payload/platform/scripts/migrate-import.sh +3 -1
  40. package/payload/platform/scripts/seed-neo4j.sh +13 -3
  41. package/payload/server/chunk-25QDCOE5.js +1116 -0
  42. package/payload/server/chunk-35YZS3KL.js +328 -0
  43. package/payload/server/chunk-7CBRZKZS.js +654 -0
  44. package/payload/server/chunk-CRAIGEXY.js +654 -0
  45. package/payload/server/chunk-I2NOLBQA.js +2123 -0
  46. package/payload/server/chunk-IVTESKFR.js +9961 -0
  47. package/payload/server/chunk-IXOPV36P.js +2305 -0
  48. package/payload/server/chunk-KD3XP4IK.js +1116 -0
  49. package/payload/server/chunk-OJZPS4BL.js +367 -0
  50. package/payload/server/chunk-ZKGAYLAK.js +10097 -0
  51. package/payload/server/client-pool-J5BCVVI2.js +32 -0
  52. package/payload/server/client-pool-NBVGONQL.js +32 -0
  53. package/payload/server/cloudflare-task-tracker-R4FIORFL.js +19 -0
  54. package/payload/server/cloudflare-task-tracker-XCUO4N74.js +19 -0
  55. package/payload/server/maxy-edge.js +6 -5
  56. package/payload/server/neo4j-migrations-3A6K2EB5.js +552 -0
  57. package/payload/server/neo4j-migrations-5AN2U3YO.js +664 -0
  58. package/payload/server/public/assets/{admin-BNwPsMhJ.js → admin-CgGQafDG.js} +1 -1
  59. package/payload/server/public/assets/{graph-N_Bw-8oT.js → graph-BlrcvwWP.js} +1 -1
  60. package/payload/server/public/assets/{page-BKLGP-th.js → page-ClTUYMK8.js} +1 -1
  61. package/payload/server/public/graph.html +2 -2
  62. package/payload/server/public/index.html +2 -2
  63. package/payload/server/server.js +385 -167
  64. package/payload/platform/plugins/admin/mcp/dist/lib/review-tools.d.ts +0 -31
  65. package/payload/platform/plugins/admin/mcp/dist/lib/review-tools.d.ts.map +0 -1
  66. package/payload/platform/plugins/admin/mcp/dist/lib/review-tools.js +0 -666
  67. package/payload/platform/plugins/admin/mcp/dist/lib/review-tools.js.map +0 -1
  68. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.d.ts +0 -61
  69. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.d.ts.map +0 -1
  70. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.js +0 -266
  71. package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.js.map +0 -1
  72. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts +0 -27
  73. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts.map +0 -1
  74. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js +0 -477
  75. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js.map +0 -1
  76. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.d.ts +0 -27
  77. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.d.ts.map +0 -1
  78. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.js +0 -160
  79. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-write.js.map +0 -1
  80. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts +0 -10
  81. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.d.ts.map +0 -1
  82. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.js +0 -29
  83. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-parse.js.map +0 -1
  84. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts +0 -28
  85. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.d.ts.map +0 -1
  86. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js +0 -34
  87. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-preview.js.map +0 -1
@@ -1,11 +1,5 @@
1
1
  import {
2
- COMMERCIAL_MODE,
3
2
  Hono,
4
- LOG_DIR,
5
- MAXY_DIR,
6
- TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
7
- TELEGRAM_WEBHOOK_SECRET_FILE,
8
- USERS_FILE,
9
3
  autoDeliverPremiumPlugins,
10
4
  buildX11Env,
11
5
  callOauthLlm,
@@ -51,7 +45,7 @@ import {
51
45
  vncLog,
52
46
  waitForExit,
53
47
  writeChromiumWrapper
54
- } from "./chunk-CV3HPX46.js";
48
+ } from "./chunk-IVTESKFR.js";
55
49
  import {
56
50
  agentLogStream,
57
51
  clearSessionHistory,
@@ -79,17 +73,24 @@ import {
79
73
  sigtermFlushStreamLogs,
80
74
  unregisterSession,
81
75
  validateSession
82
- } from "./chunk-J6YWEJBN.js";
76
+ } from "./chunk-KD3XP4IK.js";
83
77
  import {
84
78
  ACCOUNTS_DIR,
79
+ COMMERCIAL_MODE,
80
+ LOG_DIR,
81
+ MAXY_DIR,
85
82
  PLATFORM_ROOT,
83
+ TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
84
+ TELEGRAM_WEBHOOK_SECRET_FILE,
85
+ USERS_FILE,
86
86
  getDefaultAccountId,
87
+ hasStubAccountDir,
87
88
  resolveAccount,
88
89
  resolveAgentConfig,
89
90
  resolveDefaultAgentSlug,
90
91
  resolveUserAccounts,
91
92
  validateAgentSlug
92
- } from "./chunk-5OG7TUQL.js";
93
+ } from "./chunk-OJZPS4BL.js";
93
94
  import {
94
95
  CLOUDFLARE_TASK_DIAGNOSTICS,
95
96
  appendCloudflareSteps,
@@ -97,7 +98,7 @@ import {
97
98
  openCloudflareTask,
98
99
  readTunnelState,
99
100
  resolveUnitGoneVerdict
100
- } from "./chunk-OCPJGZ6S.js";
101
+ } from "./chunk-CRAIGEXY.js";
101
102
  import {
102
103
  GREETING_DIRECTIVE,
103
104
  HAIKU_MODEL,
@@ -129,7 +130,7 @@ import {
129
130
  verifyAndGetConversationUpdatedAt,
130
131
  verifyConversationOwnership,
131
132
  writeAdminUserAndPerson
132
- } from "./chunk-BCFM2UPH.js";
133
+ } from "./chunk-I2NOLBQA.js";
133
134
 
134
135
  // ../lib/graph-trash/dist/index.js
135
136
  var require_dist = __commonJS({
@@ -628,8 +629,8 @@ var serveStatic = (options = { root: "" }) => {
628
629
  };
629
630
 
630
631
  // server/index.ts
631
- import { readFileSync as readFileSync16, existsSync as existsSync22, watchFile } from "fs";
632
- import { resolve as resolve22, join as join10, basename as basename5 } from "path";
632
+ import { readFileSync as readFileSync17, existsSync as existsSync23, watchFile } from "fs";
633
+ import { resolve as resolve22, join as join12, basename as basename5 } from "path";
633
634
  import { homedir as homedir2 } from "os";
634
635
 
635
636
  // app/lib/agent-slug-pattern.ts
@@ -6391,16 +6392,164 @@ var whatsapp_default = app7;
6391
6392
 
6392
6393
  // server/routes/onboarding.ts
6393
6394
  import { spawn, execFileSync } from "child_process";
6394
- import { openSync, closeSync, writeFileSync as writeFileSync4, writeSync, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync8, unlinkSync } from "fs";
6395
- import { resolve as resolve8, dirname as dirname2 } from "path";
6395
+ import { openSync, closeSync, writeFileSync as writeFileSync5, writeSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync9, unlinkSync } from "fs";
6396
+ import { resolve as resolve8, dirname as dirname3 } from "path";
6396
6397
  import { createHash, randomUUID as randomUUID6 } from "crypto";
6398
+
6399
+ // ../lib/admins-write/src/index.ts
6400
+ import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync4, renameSync, mkdirSync as mkdirSync3, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
6401
+ import { dirname as dirname2, join as join6 } from "path";
6402
+ function logLine(input, result) {
6403
+ const userIdShort = input.userId.slice(0, 8);
6404
+ console.error(
6405
+ `[admins-write] caller=${input.caller} userId=${userIdShort} usersJsonResult=${result.usersJsonResult} accountJsonResult=${result.accountJsonResult}` + (result.usersError ? ` usersError=${result.usersError}` : "") + (result.accountError ? ` accountError=${result.accountError}` : "")
6406
+ );
6407
+ }
6408
+ function writeFileAtomic(filePath, contents, mode) {
6409
+ mkdirSync3(dirname2(filePath), { recursive: true });
6410
+ const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
6411
+ writeFileSync4(tempPath, contents, mode !== void 0 ? { mode } : void 0);
6412
+ renameSync(tempPath, filePath);
6413
+ }
6414
+ function writeAdminEntry(input) {
6415
+ const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
6416
+ try {
6417
+ let users = [];
6418
+ if (existsSync8(input.usersFile)) {
6419
+ const raw = readFileSync8(input.usersFile, "utf-8").trim();
6420
+ if (raw) {
6421
+ const parsed = JSON.parse(raw);
6422
+ if (!Array.isArray(parsed)) {
6423
+ throw new Error("users.json is not an array");
6424
+ }
6425
+ users = parsed;
6426
+ }
6427
+ }
6428
+ const existing = users.findIndex((u) => u.userId === input.userId);
6429
+ if (existing === -1) {
6430
+ users.push({ userId: input.userId, pin: input.pin });
6431
+ } else {
6432
+ const merged = { ...users[existing], pin: input.pin };
6433
+ delete merged.name;
6434
+ users[existing] = merged;
6435
+ }
6436
+ writeFileAtomic(input.usersFile, JSON.stringify(users, null, 2) + "\n", 384);
6437
+ result.usersJsonResult = "ok";
6438
+ } catch (err) {
6439
+ result.usersJsonResult = "fail";
6440
+ result.usersError = err instanceof Error ? err.message : String(err);
6441
+ logLine(input, result);
6442
+ return result;
6443
+ }
6444
+ try {
6445
+ const accountJsonPath = join6(input.accountDir, "account.json");
6446
+ if (!existsSync8(accountJsonPath)) {
6447
+ throw new Error(`account.json not found at ${accountJsonPath}`);
6448
+ }
6449
+ const config = JSON.parse(readFileSync8(accountJsonPath, "utf-8"));
6450
+ const admins = config.admins ?? [];
6451
+ if (admins.some((a) => a.userId === input.userId)) {
6452
+ result.accountJsonResult = "noop";
6453
+ } else {
6454
+ admins.push({ userId: input.userId, role: input.role });
6455
+ config.admins = admins;
6456
+ writeFileAtomic(accountJsonPath, JSON.stringify(config, null, 2) + "\n");
6457
+ result.accountJsonResult = "ok";
6458
+ }
6459
+ } catch (err) {
6460
+ result.accountJsonResult = "fail";
6461
+ result.accountError = err instanceof Error ? err.message : String(err);
6462
+ }
6463
+ logLine(input, result);
6464
+ return result;
6465
+ }
6466
+ function checkAdminAuthInvariant(input) {
6467
+ const result = {
6468
+ divergences: 0,
6469
+ accountWithoutUsers: [],
6470
+ usersWithoutAccount: []
6471
+ };
6472
+ const usersUserIds = /* @__PURE__ */ new Set();
6473
+ if (existsSync8(input.usersFile)) {
6474
+ try {
6475
+ const raw = readFileSync8(input.usersFile, "utf-8").trim();
6476
+ if (raw) {
6477
+ const users = JSON.parse(raw);
6478
+ for (const u of users) {
6479
+ if (typeof u.userId === "string") usersUserIds.add(u.userId);
6480
+ }
6481
+ }
6482
+ } catch (err) {
6483
+ const msg = err instanceof Error ? err.message : String(err);
6484
+ console.error(`[${input.tag}] users.json unreadable usersFile=${input.usersFile} error=${msg}`);
6485
+ }
6486
+ }
6487
+ const accountUserIds = /* @__PURE__ */ new Set();
6488
+ if (existsSync8(input.accountsDir)) {
6489
+ let entries;
6490
+ try {
6491
+ entries = readdirSync3(input.accountsDir);
6492
+ } catch (err) {
6493
+ const msg = err instanceof Error ? err.message : String(err);
6494
+ console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
6495
+ console.error(`[${input.tag}] check complete divergences=0 (accounts-dir unreadable)`);
6496
+ return result;
6497
+ }
6498
+ for (const entry of entries) {
6499
+ if (entry.startsWith(".")) continue;
6500
+ const accountDir = join6(input.accountsDir, entry);
6501
+ try {
6502
+ if (!statSync2(accountDir).isDirectory()) continue;
6503
+ } catch {
6504
+ continue;
6505
+ }
6506
+ const accountJsonPath = join6(accountDir, "account.json");
6507
+ if (!existsSync8(accountJsonPath)) continue;
6508
+ let admins = [];
6509
+ try {
6510
+ const config = JSON.parse(readFileSync8(accountJsonPath, "utf-8"));
6511
+ admins = config.admins ?? [];
6512
+ } catch (err) {
6513
+ const msg = err instanceof Error ? err.message : String(err);
6514
+ console.error(`[${input.tag}] account.json unreadable source=${accountJsonPath} error=${msg}`);
6515
+ continue;
6516
+ }
6517
+ for (const a of admins) {
6518
+ if (typeof a.userId !== "string") continue;
6519
+ accountUserIds.add(a.userId);
6520
+ if (!usersUserIds.has(a.userId)) {
6521
+ const userIdShort = a.userId.slice(0, 8);
6522
+ console.error(
6523
+ `[${input.tag}] direction=account-without-users userId=${userIdShort} source=${accountJsonPath}`
6524
+ );
6525
+ result.accountWithoutUsers.push({ userId: a.userId, source: accountJsonPath });
6526
+ result.divergences += 1;
6527
+ }
6528
+ }
6529
+ }
6530
+ }
6531
+ for (const uid of usersUserIds) {
6532
+ if (!accountUserIds.has(uid)) {
6533
+ const userIdShort = uid.slice(0, 8);
6534
+ console.error(
6535
+ `[${input.tag}] direction=users-without-account userId=${userIdShort} source=${input.usersFile}`
6536
+ );
6537
+ result.usersWithoutAccount.push({ userId: uid });
6538
+ result.divergences += 1;
6539
+ }
6540
+ }
6541
+ console.error(`[${input.tag}] check complete divergences=${result.divergences}`);
6542
+ return result;
6543
+ }
6544
+
6545
+ // server/routes/onboarding.ts
6397
6546
  var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT || "";
6398
6547
  function hashPin(pin) {
6399
6548
  return createHash("sha256").update(pin).digest("hex");
6400
6549
  }
6401
6550
  function readUsersFile() {
6402
- if (!existsSync8(USERS_FILE)) return null;
6403
- const raw = readFileSync8(USERS_FILE, "utf-8").trim();
6551
+ if (!existsSync9(USERS_FILE)) return null;
6552
+ const raw = readFileSync9(USERS_FILE, "utf-8").trim();
6404
6553
  if (!raw) return [];
6405
6554
  return JSON.parse(raw);
6406
6555
  }
@@ -6466,7 +6615,7 @@ app8.post("/claude-auth", async (c) => {
6466
6615
  if (!vncReady) return c.json({ error: "VNC display failed to start" }, 500);
6467
6616
  }
6468
6617
  await ensureCdp(transport);
6469
- writeFileSync4(logPath("claude-auth"), "");
6618
+ writeFileSync5(logPath("claude-auth"), "");
6470
6619
  const chromiumWrapper = writeChromiumWrapper();
6471
6620
  const x11Env = buildX11Env(chromiumWrapper, transport);
6472
6621
  vncLog("claude-auth", { action: "start", transport });
@@ -6494,6 +6643,17 @@ app8.post("/set-pin", async (c) => {
6494
6643
  if (existingUsers !== null && existingUsers.length > 0) {
6495
6644
  return c.json({ error: "PIN is already configured." }, 409);
6496
6645
  }
6646
+ const stubCheck = hasStubAccountDir();
6647
+ if (stubCheck.stub) {
6648
+ console.error(
6649
+ `[onboarding] set-pin REFUSED reason=stub-account-dirs dirs=${stubCheck.dirs.join(",")}`
6650
+ );
6651
+ return c.json({
6652
+ error: `Onboarding refused: data/accounts/ contains ${stubCheck.dirs.length} directory/ies without account.json (${stubCheck.dirs.join(", ")}). Resolve the stub before setting up.`,
6653
+ code: "STUB_ACCOUNT_DIR",
6654
+ dirs: stubCheck.dirs
6655
+ }, 409);
6656
+ }
6497
6657
  let body;
6498
6658
  try {
6499
6659
  body = await c.req.json();
@@ -6516,36 +6676,41 @@ app8.post("/set-pin", async (c) => {
6516
6676
  } else {
6517
6677
  console.log(`[set-pin] minted new userId=${userId.slice(0, 8)}\u2026 (first-time install)`);
6518
6678
  }
6519
- mkdirSync3(dirname2(USERS_FILE), { recursive: true });
6520
- writeFileSync4(USERS_FILE, JSON.stringify([{ userId, pin: hash }]), { mode: 384 });
6521
- console.log(`[set-pin] wrote users.json: userId=${userId.slice(0, 8)}\u2026 hash=${hash.slice(0, 8)}\u2026`);
6522
- if (account) {
6523
- try {
6524
- const config = JSON.parse(readFileSync8(`${account.accountDir}/account.json`, "utf-8"));
6525
- if (!config.admins) config.admins = [];
6526
- if (!config.admins.some((a) => a.userId === userId)) {
6527
- config.admins.push({ userId, role: "owner" });
6528
- writeFileSync4(`${account.accountDir}/account.json`, JSON.stringify(config, null, 2) + "\n");
6529
- console.log(`[set-pin] added userId=${userId.slice(0, 8)}\u2026 to account.json admins`);
6530
- }
6531
- } catch (err) {
6532
- console.error(`[set-pin] failed to update account.json admins: ${err instanceof Error ? err.message : String(err)}`);
6533
- }
6534
- try {
6535
- const result = await writeAdminUserAndPerson({
6536
- userId,
6537
- fullName,
6538
- accountId: account.accountId
6539
- });
6540
- console.log(
6541
- `[admin-identity] adminuser-bound userId=${userId.slice(0, 8)} givenName=${result.givenName} familyName=${result.familyName ?? "null"} personReused=${result.personReused}`
6542
- );
6543
- } catch (err) {
6544
- console.error(
6545
- `[admin-identity] adminuser-bind-failed userId=${userId.slice(0, 8)} accountId=${account.accountId.slice(0, 8)} error=${err instanceof Error ? err.message : String(err)}`
6546
- );
6547
- return c.json({ error: "Failed to write admin identity to graph. Check Neo4j connectivity and retry." }, 500);
6548
- }
6679
+ if (!account) {
6680
+ console.error(`[set-pin] no account resolvable at set-pin time \u2014 refusing to write users.json without account binding`);
6681
+ return c.json({ error: "No account is configured on this device. Re-run the installer." }, 503);
6682
+ }
6683
+ const result = writeAdminEntry({
6684
+ userId,
6685
+ pin: hash,
6686
+ role: "owner",
6687
+ usersFile: USERS_FILE,
6688
+ accountDir: account.accountDir,
6689
+ caller: "set-pin"
6690
+ });
6691
+ if (result.usersJsonResult !== "ok") {
6692
+ console.error(`[set-pin] users.json write failed: ${result.usersError ?? "unknown"}`);
6693
+ return c.json({ error: "Failed to write user configuration. See server log." }, 500);
6694
+ }
6695
+ if (result.accountJsonResult === "fail") {
6696
+ console.error(`[set-pin] account.json write failed after users.json succeeded: ${result.accountError ?? "unknown"}`);
6697
+ return c.json({ error: "PIN saved but admin role could not be recorded. See server log." }, 500);
6698
+ }
6699
+ console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
6700
+ try {
6701
+ const adminBind = await writeAdminUserAndPerson({
6702
+ userId,
6703
+ fullName,
6704
+ accountId: account.accountId
6705
+ });
6706
+ console.log(
6707
+ `[admin-identity] adminuser-bound userId=${userId.slice(0, 8)} givenName=${adminBind.givenName} familyName=${adminBind.familyName ?? "null"} personReused=${adminBind.personReused}`
6708
+ );
6709
+ } catch (err) {
6710
+ console.error(
6711
+ `[admin-identity] adminuser-bind-failed userId=${userId.slice(0, 8)} accountId=${account.accountId.slice(0, 8)} error=${err instanceof Error ? err.message : String(err)}`
6712
+ );
6713
+ return c.json({ error: "Failed to write admin identity to graph. Check Neo4j connectivity and retry." }, 500);
6549
6714
  }
6550
6715
  return c.json({ ok: true });
6551
6716
  });
@@ -6578,7 +6743,7 @@ app8.delete("/set-pin", async (c) => {
6578
6743
  unlinkSync(USERS_FILE);
6579
6744
  console.log(`[set-pin] cleared users.json (last entry removed): userId=${matchedUser.userId.slice(0, 8)}\u2026`);
6580
6745
  } else {
6581
- writeFileSync4(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
6746
+ writeFileSync5(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
6582
6747
  console.log(`[set-pin] removed entry from users.json: userId=${matchedUser.userId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
6583
6748
  }
6584
6749
  return c.json({ ok: true });
@@ -6598,9 +6763,9 @@ app8.post("/skip", async (c) => {
6598
6763
  const { accountId, accountDir } = account;
6599
6764
  let agentName = "Maxy";
6600
6765
  const brandPath = PLATFORM_ROOT5 ? resolve8(PLATFORM_ROOT5, "config", "brand.json") : "";
6601
- if (brandPath && existsSync8(brandPath)) {
6766
+ if (brandPath && existsSync9(brandPath)) {
6602
6767
  try {
6603
- const brand = JSON.parse(readFileSync8(brandPath, "utf-8"));
6768
+ const brand = JSON.parse(readFileSync9(brandPath, "utf-8"));
6604
6769
  if (brand.productName) agentName = brand.productName;
6605
6770
  } catch (err) {
6606
6771
  console.error(`[onboarding-skip] brand.json read failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -6608,8 +6773,8 @@ app8.post("/skip", async (c) => {
6608
6773
  }
6609
6774
  const soulPath = resolve8(accountDir, "agents", "admin", "SOUL.md");
6610
6775
  try {
6611
- mkdirSync3(dirname2(soulPath), { recursive: true });
6612
- writeFileSync4(soulPath, `You are ${agentName}, an AI operations manager.
6776
+ mkdirSync4(dirname3(soulPath), { recursive: true });
6777
+ writeFileSync5(soulPath, `You are ${agentName}, an AI operations manager.
6613
6778
  `);
6614
6779
  console.log(`[onboarding-skip] wrote SOUL.md: ${soulPath}`);
6615
6780
  } catch (err) {
@@ -6653,9 +6818,9 @@ app8.post("/skip", async (c) => {
6653
6818
  var onboarding_default = app8;
6654
6819
 
6655
6820
  // server/routes/client-error.ts
6656
- import { appendFileSync, existsSync as existsSync9, renameSync, statSync as statSync2 } from "fs";
6657
- import { join as join6 } from "path";
6658
- var CLIENT_ERRORS_LOG = join6(LOG_DIR, "client-errors.log");
6821
+ import { appendFileSync, existsSync as existsSync10, renameSync as renameSync2, statSync as statSync3 } from "fs";
6822
+ import { join as join7 } from "path";
6823
+ var CLIENT_ERRORS_LOG = join7(LOG_DIR, "client-errors.log");
6659
6824
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
6660
6825
  var MAX_BODY_SIZE = 8 * 1024;
6661
6826
  var MAX_STACK_LEN = 2e3;
@@ -6698,10 +6863,10 @@ function stackHead(stack) {
6698
6863
  }
6699
6864
  function rotateIfNeeded() {
6700
6865
  try {
6701
- if (!existsSync9(CLIENT_ERRORS_LOG)) return;
6702
- const stats = statSync2(CLIENT_ERRORS_LOG);
6866
+ if (!existsSync10(CLIENT_ERRORS_LOG)) return;
6867
+ const stats = statSync3(CLIENT_ERRORS_LOG);
6703
6868
  if (stats.size < MAX_LOG_SIZE) return;
6704
- renameSync(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
6869
+ renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
6705
6870
  } catch (err) {
6706
6871
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
6707
6872
  }
@@ -6812,18 +6977,53 @@ app9.post("/", async (c) => {
6812
6977
  var client_error_default = app9;
6813
6978
 
6814
6979
  // server/routes/admin/session.ts
6815
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs";
6980
+ import { readFileSync as readFileSync10, readdirSync as readdirSync4, statSync as statSync4, writeFileSync as writeFileSync6, existsSync as existsSync11 } from "fs";
6981
+ import { join as join8 } from "path";
6816
6982
  import { createHash as createHash2 } from "crypto";
6817
6983
  var deprecationLogged = /* @__PURE__ */ new Set();
6818
6984
  function hashPin2(pin) {
6819
6985
  return createHash2("sha256").update(pin).digest("hex");
6820
6986
  }
6821
6987
  function readUsersFile2() {
6822
- if (!existsSync10(USERS_FILE)) return null;
6823
- const raw = readFileSync9(USERS_FILE, "utf-8").trim();
6988
+ if (!existsSync11(USERS_FILE)) return null;
6989
+ const raw = readFileSync10(USERS_FILE, "utf-8").trim();
6824
6990
  if (!raw) return [];
6825
6991
  return JSON.parse(raw);
6826
6992
  }
6993
+ function scanForOrphanedAccountAdmins(users) {
6994
+ const usersUserIds = new Set(users.map((u) => u.userId));
6995
+ const orphans = [];
6996
+ if (!existsSync11(ACCOUNTS_DIR)) return orphans;
6997
+ let entries;
6998
+ try {
6999
+ entries = readdirSync4(ACCOUNTS_DIR);
7000
+ } catch {
7001
+ return orphans;
7002
+ }
7003
+ for (const entry of entries) {
7004
+ if (entry.startsWith(".")) continue;
7005
+ const accountDir = join8(ACCOUNTS_DIR, entry);
7006
+ try {
7007
+ if (!statSync4(accountDir).isDirectory()) continue;
7008
+ } catch {
7009
+ continue;
7010
+ }
7011
+ const accountJsonPath = join8(accountDir, "account.json");
7012
+ if (!existsSync11(accountJsonPath)) continue;
7013
+ try {
7014
+ const config = JSON.parse(readFileSync10(accountJsonPath, "utf-8"));
7015
+ const admins = config.admins ?? [];
7016
+ for (const a of admins) {
7017
+ if (typeof a.userId === "string" && !usersUserIds.has(a.userId)) {
7018
+ orphans.push(a.userId);
7019
+ }
7020
+ }
7021
+ } catch {
7022
+ continue;
7023
+ }
7024
+ }
7025
+ return orphans;
7026
+ }
6827
7027
  function stripLegacyNameField(users) {
6828
7028
  const dirty = users.some((u) => "name" in u && u.name !== void 0);
6829
7029
  if (!dirty) return;
@@ -6837,7 +7037,7 @@ function stripLegacyNameField(users) {
6837
7037
  }
6838
7038
  }
6839
7039
  try {
6840
- writeFileSync5(USERS_FILE, JSON.stringify(users), { mode: 384 });
7040
+ writeFileSync6(USERS_FILE, JSON.stringify(users), { mode: 384 });
6841
7041
  } catch (err) {
6842
7042
  console.error(`[admin-identity] users-json strip failed: ${err instanceof Error ? err.message : String(err)}`);
6843
7043
  }
@@ -6957,7 +7157,15 @@ app10.post("/", async (c) => {
6957
7157
  }
6958
7158
  const matchedUser = users.find((u) => u.pin === inputHash);
6959
7159
  if (!matchedUser) {
6960
- console.log(`[session] PIN auth failed: no matching user`);
7160
+ const orphanUserIds = scanForOrphanedAccountAdmins(users);
7161
+ if (orphanUserIds.length > 0) {
7162
+ const prefix = orphanUserIds[0].slice(0, 8);
7163
+ console.log(
7164
+ `[session] PIN auth failed: no matching user; account.json admins[] contains userId=${prefix} with no users.json row \u2014 three-store divergence`
7165
+ );
7166
+ } else {
7167
+ console.log(`[session] PIN auth failed: no matching user`);
7168
+ }
6961
7169
  return c.json({ error: "Invalid PIN" }, 401);
6962
7170
  }
6963
7171
  stripLegacyNameField(users);
@@ -6999,8 +7207,8 @@ import { appendFileSync as appendFileSync3 } from "fs";
6999
7207
 
7000
7208
  // app/lib/script-stream-tailer.ts
7001
7209
  import * as childProcess from "child_process";
7002
- import { appendFileSync as appendFileSync2, createReadStream as createReadStream2, mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
7003
- import { dirname as dirname3 } from "path";
7210
+ import { appendFileSync as appendFileSync2, createReadStream as createReadStream2, mkdirSync as mkdirSync5, statSync as statSync5 } from "fs";
7211
+ import { dirname as dirname4 } from "path";
7004
7212
  import { StringDecoder } from "string_decoder";
7005
7213
  var SCRIPT_STREAM_RE = /^\[([^\]]+)\] \[script:([a-z][a-z0-9-]*)((?::[a-z0-9:_-]+)?)\] (.*)$/;
7006
7214
  function parseLine(line) {
@@ -7018,7 +7226,7 @@ function startScriptStreamTailer(opts) {
7018
7226
  const { path: path2, onEvent, onError } = opts;
7019
7227
  let offset;
7020
7228
  try {
7021
- offset = statSync3(path2).size;
7229
+ offset = statSync5(path2).size;
7022
7230
  } catch {
7023
7231
  offset = 0;
7024
7232
  }
@@ -7037,7 +7245,7 @@ function startScriptStreamTailer(opts) {
7037
7245
  try {
7038
7246
  let size;
7039
7247
  try {
7040
- size = statSync3(path2).size;
7248
+ size = statSync5(path2).size;
7041
7249
  } catch {
7042
7250
  return;
7043
7251
  }
@@ -7109,7 +7317,7 @@ function writeRouteMilestone(streamLogPath, scope, line) {
7109
7317
  }
7110
7318
  const ts = (/* @__PURE__ */ new Date()).toISOString();
7111
7319
  try {
7112
- mkdirSync4(dirname3(streamLogPath), { recursive: true });
7320
+ mkdirSync5(dirname4(streamLogPath), { recursive: true });
7113
7321
  appendFileSync2(streamLogPath, `[${ts}] [script:${scope}] ${line}
7114
7322
  `);
7115
7323
  } catch (err) {
@@ -7285,7 +7493,7 @@ var app11 = new Hono();
7285
7493
  app11.post("/cancel", requireAdminSession, async (c) => {
7286
7494
  const session_key = c.var.sessionKey;
7287
7495
  try {
7288
- const { interruptClient: interruptClient2 } = await import("./client-pool-ZNGN66GN.js");
7496
+ const { interruptClient: interruptClient2 } = await import("./client-pool-J5BCVVI2.js");
7289
7497
  await interruptClient2(session_key);
7290
7498
  return c.json({ ok: true });
7291
7499
  } catch (err) {
@@ -7680,22 +7888,22 @@ app12.post("/", requireAdminSession, async (c) => {
7680
7888
  var compact_default = app12;
7681
7889
 
7682
7890
  // server/routes/admin/logs.ts
7683
- import { existsSync as existsSync12, readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
7891
+ import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync6 } from "fs";
7684
7892
  import { resolve as resolve10, basename as basename3 } from "path";
7685
7893
 
7686
7894
  // app/lib/logs-read-resolve.ts
7687
- import { existsSync as existsSync11 } from "fs";
7688
- import { join as join7 } from "path";
7895
+ import { existsSync as existsSync12 } from "fs";
7896
+ import { join as join9 } from "path";
7689
7897
  function resolveConversationLogPaths(fullFilename, preflushFilename, logDirs) {
7690
7898
  const tried = [fullFilename, preflushFilename];
7691
7899
  const hits = [];
7692
7900
  const stalePreflushPaths = [];
7693
7901
  for (const dir of logDirs) {
7694
- const fullPath = join7(dir, fullFilename);
7695
- if (existsSync11(fullPath)) {
7902
+ const fullPath = join9(dir, fullFilename);
7903
+ if (existsSync12(fullPath)) {
7696
7904
  hits.push({ path: fullPath, shape: "full", dir });
7697
- const preflushSibling = join7(dir, preflushFilename);
7698
- if (existsSync11(preflushSibling)) {
7905
+ const preflushSibling = join9(dir, preflushFilename);
7906
+ if (existsSync12(preflushSibling)) {
7699
7907
  stalePreflushPaths.push(preflushSibling);
7700
7908
  }
7701
7909
  }
@@ -7704,8 +7912,8 @@ function resolveConversationLogPaths(fullFilename, preflushFilename, logDirs) {
7704
7912
  return { hits, stalePreflushPaths, tried };
7705
7913
  }
7706
7914
  for (const dir of logDirs) {
7707
- const preflushPath = join7(dir, preflushFilename);
7708
- if (existsSync11(preflushPath)) {
7915
+ const preflushPath = join9(dir, preflushFilename);
7916
+ if (existsSync12(preflushPath)) {
7709
7917
  hits.push({ path: preflushPath, shape: "preflush", dir });
7710
7918
  }
7711
7919
  }
@@ -7736,8 +7944,8 @@ app13.get("/", async (c) => {
7736
7944
  const filePath = resolve10(dir, safe);
7737
7945
  searched.push(filePath);
7738
7946
  try {
7739
- const buffer = readFileSync10(filePath);
7740
- const onDiskBytes = statSync4(filePath).size;
7947
+ const buffer = readFileSync11(filePath);
7948
+ const onDiskBytes = statSync6(filePath).size;
7741
7949
  const headers = {
7742
7950
  "Content-Type": "text/plain; charset=utf-8",
7743
7951
  "Content-Length": String(buffer.byteLength)
@@ -7822,7 +8030,7 @@ app13.get("/", async (c) => {
7822
8030
  try {
7823
8031
  const filename = basename3(hit.path);
7824
8032
  if (stalePreflushCount > 0 && !download) {
7825
- const content = readFileSync10(hit.path, "utf-8");
8033
+ const content = readFileSync11(hit.path, "utf-8");
7826
8034
  return c.json({
7827
8035
  log: content,
7828
8036
  filename,
@@ -7830,8 +8038,8 @@ app13.get("/", async (c) => {
7830
8038
  warnings: stalePreflushPaths.map((path2) => ({ kind: "stale-preflush", path: path2 }))
7831
8039
  });
7832
8040
  }
7833
- const buffer = readFileSync10(hit.path);
7834
- const onDiskBytes = statSync4(hit.path).size;
8041
+ const buffer = readFileSync11(hit.path);
8042
+ const onDiskBytes = statSync6(hit.path).size;
7835
8043
  const headers = {
7836
8044
  "Content-Type": "text/plain; charset=utf-8",
7837
8045
  "Content-Length": String(buffer.byteLength)
@@ -7864,19 +8072,19 @@ app13.get("/", async (c) => {
7864
8072
  const seen = /* @__PURE__ */ new Set();
7865
8073
  const logs = {};
7866
8074
  for (const dir of logDirs) {
7867
- if (!existsSync12(dir)) continue;
8075
+ if (!existsSync13(dir)) continue;
7868
8076
  let files;
7869
8077
  try {
7870
- files = readdirSync3(dir).filter((f) => f.endsWith(".log"));
8078
+ files = readdirSync5(dir).filter((f) => f.endsWith(".log"));
7871
8079
  } catch (err) {
7872
8080
  const reason = err instanceof Error ? err.message : String(err);
7873
8081
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
7874
8082
  continue;
7875
8083
  }
7876
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync4(resolve10(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
8084
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync6(resolve10(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
7877
8085
  seen.add(name);
7878
8086
  try {
7879
- const content = readFileSync10(resolve10(dir, name));
8087
+ const content = readFileSync11(resolve10(dir, name));
7880
8088
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
7881
8089
  logs[name] = tail.trim() || "(empty)";
7882
8090
  } catch (err) {
@@ -7915,7 +8123,7 @@ var claude_info_default = app14;
7915
8123
 
7916
8124
  // server/routes/admin/attachment.ts
7917
8125
  import { readFile as readFile3, readdir } from "fs/promises";
7918
- import { existsSync as existsSync13 } from "fs";
8126
+ import { existsSync as existsSync14 } from "fs";
7919
8127
  import { resolve as resolve11 } from "path";
7920
8128
  var app15 = new Hono();
7921
8129
  app15.get("/:attachmentId", requireAdminSession, async (c) => {
@@ -7929,11 +8137,11 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
7929
8137
  return new Response("Not found", { status: 404 });
7930
8138
  }
7931
8139
  const dir = resolve11(ATTACHMENTS_ROOT, accountId, attachmentId);
7932
- if (!existsSync13(dir)) {
8140
+ if (!existsSync14(dir)) {
7933
8141
  return new Response("Not found", { status: 404 });
7934
8142
  }
7935
8143
  const metaPath = resolve11(dir, `${attachmentId}.meta.json`);
7936
- if (!existsSync13(metaPath)) {
8144
+ if (!existsSync14(metaPath)) {
7937
8145
  return new Response("Not found", { status: 404 });
7938
8146
  }
7939
8147
  let meta;
@@ -7961,23 +8169,23 @@ var attachment_default = app15;
7961
8169
 
7962
8170
  // server/routes/admin/agents.ts
7963
8171
  import { resolve as resolve12 } from "path";
7964
- import { readdirSync as readdirSync4, readFileSync as readFileSync11, existsSync as existsSync14, rmSync } from "fs";
8172
+ import { readdirSync as readdirSync6, readFileSync as readFileSync12, existsSync as existsSync15, rmSync } from "fs";
7965
8173
  var app16 = new Hono();
7966
8174
  app16.get("/", (c) => {
7967
8175
  const account = resolveAccount();
7968
8176
  if (!account) return c.json({ agents: [] });
7969
8177
  const agentsDir = resolve12(account.accountDir, "agents");
7970
- if (!existsSync14(agentsDir)) return c.json({ agents: [] });
8178
+ if (!existsSync15(agentsDir)) return c.json({ agents: [] });
7971
8179
  const agents = [];
7972
8180
  try {
7973
- const entries = readdirSync4(agentsDir, { withFileTypes: true });
8181
+ const entries = readdirSync6(agentsDir, { withFileTypes: true });
7974
8182
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
7975
8183
  if (!entry.isDirectory()) continue;
7976
8184
  if (entry.name === "admin") continue;
7977
8185
  const configPath2 = resolve12(agentsDir, entry.name, "config.json");
7978
- if (!existsSync14(configPath2)) continue;
8186
+ if (!existsSync15(configPath2)) continue;
7979
8187
  try {
7980
- const config = JSON.parse(readFileSync11(configPath2, "utf-8"));
8188
+ const config = JSON.parse(readFileSync12(configPath2, "utf-8"));
7981
8189
  agents.push({
7982
8190
  slug: entry.name,
7983
8191
  displayName: config.displayName ?? entry.name,
@@ -8004,7 +8212,7 @@ app16.delete("/:slug", async (c) => {
8004
8212
  return c.json({ error: "Invalid agent slug" }, 400);
8005
8213
  }
8006
8214
  const agentDir = resolve12(account.accountDir, "agents", slug);
8007
- if (!existsSync14(agentDir)) {
8215
+ if (!existsSync15(agentDir)) {
8008
8216
  return c.json({ error: "Agent not found" }, 404);
8009
8217
  }
8010
8218
  try {
@@ -8034,7 +8242,7 @@ app16.post("/:slug/project", async (c) => {
8034
8242
  return c.json({ error: "Invalid agent slug" }, 400);
8035
8243
  }
8036
8244
  const agentDir = resolve12(account.accountDir, "agents", slug);
8037
- if (!existsSync14(agentDir)) {
8245
+ if (!existsSync15(agentDir)) {
8038
8246
  return c.json({ error: "Agent not found on disk" }, 404);
8039
8247
  }
8040
8248
  try {
@@ -8050,7 +8258,7 @@ var agents_default = app16;
8050
8258
  // server/routes/admin/sessions.ts
8051
8259
  import crypto2 from "crypto";
8052
8260
  import { resolve as resolvePath } from "path";
8053
- import { appendFileSync as appendFileSync4, existsSync as existsSync15 } from "fs";
8261
+ import { appendFileSync as appendFileSync4, existsSync as existsSync16 } from "fs";
8054
8262
 
8055
8263
  // app/lib/synthetic-marker.ts
8056
8264
  var CLOUDFLARE_MARKER_PREFIX = "Cloudflare setup completed (actionId: ";
@@ -8070,7 +8278,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, conversationId
8070
8278
  let reason = null;
8071
8279
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
8072
8280
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
8073
- else if (!existsSync15(a.storagePath)) reason = "missing-file";
8281
+ else if (!existsSync16(a.storagePath)) reason = "missing-file";
8074
8282
  if (reason) {
8075
8283
  invalid++;
8076
8284
  try {
@@ -8641,7 +8849,7 @@ var events_default = app20;
8641
8849
  // server/routes/admin/cloudflare.ts
8642
8850
  import { homedir } from "os";
8643
8851
  import { resolve as resolve14 } from "path";
8644
- import { readFileSync as readFileSync13 } from "fs";
8852
+ import { readFileSync as readFileSync14 } from "fs";
8645
8853
 
8646
8854
  // app/lib/dns-label.ts
8647
8855
  var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
@@ -8657,14 +8865,14 @@ function isValidDomain(value) {
8657
8865
  }
8658
8866
 
8659
8867
  // app/lib/alias-domains.ts
8660
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "fs";
8661
- import { dirname as dirname4 } from "path";
8868
+ import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "fs";
8869
+ import { dirname as dirname5 } from "path";
8662
8870
  import { resolve as resolve13 } from "path";
8663
8871
  var ALIAS_DOMAINS_PATH = resolve13(MAXY_DIR, "alias-domains.json");
8664
8872
  function readExisting() {
8665
- if (!existsSync16(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
8873
+ if (!existsSync17(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
8666
8874
  try {
8667
- const parsed = JSON.parse(readFileSync12(ALIAS_DOMAINS_PATH, "utf-8"));
8875
+ const parsed = JSON.parse(readFileSync13(ALIAS_DOMAINS_PATH, "utf-8"));
8668
8876
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
8669
8877
  return new Set(parsed.filter((h) => typeof h === "string"));
8670
8878
  } catch {
@@ -8675,8 +8883,8 @@ function addAliasDomain(hostname2) {
8675
8883
  const existing = readExisting();
8676
8884
  if (existing.has(hostname2)) return;
8677
8885
  existing.add(hostname2);
8678
- mkdirSync5(dirname4(ALIAS_DOMAINS_PATH), { recursive: true });
8679
- writeFileSync6(ALIAS_DOMAINS_PATH, JSON.stringify([...existing], null, 2) + "\n", "utf-8");
8886
+ mkdirSync6(dirname5(ALIAS_DOMAINS_PATH), { recursive: true });
8887
+ writeFileSync7(ALIAS_DOMAINS_PATH, JSON.stringify([...existing], null, 2) + "\n", "utf-8");
8680
8888
  }
8681
8889
 
8682
8890
  // app/lib/cloudflare-setup-types.ts
@@ -8691,7 +8899,7 @@ function loadBrandInfo() {
8691
8899
  const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
8692
8900
  const brandPath = resolve14(platformRoot2, "config", "brand.json");
8693
8901
  try {
8694
- const parsed = JSON.parse(readFileSync13(brandPath, "utf-8"));
8902
+ const parsed = JSON.parse(readFileSync14(brandPath, "utf-8"));
8695
8903
  const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
8696
8904
  const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
8697
8905
  return { hostname: hostname2, configDir: configDir2 };
@@ -8905,8 +9113,8 @@ app21.get("/tunnels", requireAdminSession, async (c) => {
8905
9113
  if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
8906
9114
  streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
8907
9115
  const certPath = resolve14(homedir(), brand.configDir, "cloudflared", "cert.pem");
8908
- const { existsSync: existsSync23 } = await import("fs");
8909
- if (!existsSync23(certPath)) {
9116
+ const { existsSync: existsSync24 } = await import("fs");
9117
+ if (!existsSync24(certPath)) {
8910
9118
  return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
8911
9119
  }
8912
9120
  const result = await runFormSpawn({
@@ -9196,7 +9404,7 @@ var cloudflare_default = app21;
9196
9404
  import { createReadStream as createReadStream3 } from "fs";
9197
9405
  import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
9198
9406
  import { realpathSync as realpathSync4 } from "fs";
9199
- import { basename as basename4, dirname as dirname5, join as join8, resolve as resolve16, sep as sep2 } from "path";
9407
+ import { basename as basename4, dirname as dirname6, join as join10, resolve as resolve16, sep as sep2 } from "path";
9200
9408
  import { Readable as Readable2 } from "stream";
9201
9409
 
9202
9410
  // app/lib/data-path.ts
@@ -9554,7 +9762,7 @@ async function cascadeDeleteDocument(params) {
9554
9762
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9555
9763
  async function readMeta(absDir, baseName) {
9556
9764
  try {
9557
- const raw = await readFile4(join8(absDir, `${baseName}.meta.json`), "utf8");
9765
+ const raw = await readFile4(join10(absDir, `${baseName}.meta.json`), "utf8");
9558
9766
  const parsed = JSON.parse(raw);
9559
9767
  if (typeof parsed?.filename === "string") {
9560
9768
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -9592,7 +9800,7 @@ async function readAccountNames() {
9592
9800
  }
9593
9801
  async function enrich(absolute, entry, accountNames) {
9594
9802
  if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
9595
- const meta = await readMeta(join8(absolute, entry.name), entry.name);
9803
+ const meta = await readMeta(join10(absolute, entry.name), entry.name);
9596
9804
  if (meta?.filename) {
9597
9805
  entry.displayName = meta.filename;
9598
9806
  entry.mimeType = meta.mimeType;
@@ -9651,7 +9859,7 @@ app22.get("/", requireAdminSession, async (c) => {
9651
9859
  continue;
9652
9860
  }
9653
9861
  try {
9654
- const entryPath = join8(absolute, name);
9862
+ const entryPath = join10(absolute, name);
9655
9863
  const s = await stat4(entryPath);
9656
9864
  entries.push({
9657
9865
  name,
@@ -9824,7 +10032,7 @@ app22.delete("/", requireAdminSession, async (c) => {
9824
10032
  }
9825
10033
  const dot = base.lastIndexOf(".");
9826
10034
  const stem = dot === -1 ? base : base.slice(0, dot);
9827
- const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join8(dirname5(absolute), `${stem}.meta.json`) : null;
10035
+ const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join10(dirname6(absolute), `${stem}.meta.json`) : null;
9828
10036
  await unlink2(absolute);
9829
10037
  if (sidecarPath) {
9830
10038
  try {
@@ -11446,7 +11654,7 @@ var adherence_default = app30;
11446
11654
  import neo4j3 from "neo4j-driver";
11447
11655
  import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
11448
11656
  import { resolve as resolve17, relative as relative2, isAbsolute } from "path";
11449
- import { existsSync as existsSync17 } from "fs";
11657
+ import { existsSync as existsSync18 } from "fs";
11450
11658
  var LIMIT = 50;
11451
11659
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
11452
11660
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -11594,7 +11802,7 @@ async function fetchAgentTemplateRows(accountDir) {
11594
11802
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
11595
11803
  const names = /* @__PURE__ */ new Set();
11596
11804
  for (const dir of [overrideDir, bundledDir]) {
11597
- if (!existsSync17(dir)) continue;
11805
+ if (!existsSync18(dir)) continue;
11598
11806
  try {
11599
11807
  const entries = await readdir3(dir);
11600
11808
  for (const entry of entries) {
@@ -11609,7 +11817,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
11609
11817
  }
11610
11818
  async function readAgentTemplateRow(inp) {
11611
11819
  let chosenPath = null;
11612
- if (existsSync17(inp.overridePath)) {
11820
+ if (existsSync18(inp.overridePath)) {
11613
11821
  try {
11614
11822
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
11615
11823
  chosenPath = inp.overridePath;
@@ -11620,7 +11828,7 @@ async function readAgentTemplateRow(inp) {
11620
11828
  );
11621
11829
  return null;
11622
11830
  }
11623
- } else if (existsSync17(inp.bundledPath)) {
11831
+ } else if (existsSync18(inp.bundledPath)) {
11624
11832
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
11625
11833
  console.error(
11626
11834
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -11662,7 +11870,7 @@ var sidebar_artefacts_default = app31;
11662
11870
  // server/routes/admin/sidebar-artefact-save.ts
11663
11871
  import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
11664
11872
  import { resolve as resolve18 } from "path";
11665
- import { existsSync as existsSync18 } from "fs";
11873
+ import { existsSync as existsSync19 } from "fs";
11666
11874
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
11667
11875
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11668
11876
  var app32 = new Hono();
@@ -11726,7 +11934,7 @@ async function resolveSavePath(id, accountId, accountDir) {
11726
11934
  }
11727
11935
  if (UUID_RE5.test(id)) {
11728
11936
  const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
11729
- if (!existsSync18(dir)) {
11937
+ if (!existsSync19(dir)) {
11730
11938
  return { kind: "reject", status: 400, reason: "not-found" };
11731
11939
  }
11732
11940
  try {
@@ -11750,7 +11958,7 @@ var sidebar_artefact_save_default = app32;
11750
11958
 
11751
11959
  // server/routes/admin/sidebar-artefact-content.ts
11752
11960
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
11753
- import { existsSync as existsSync19 } from "fs";
11961
+ import { existsSync as existsSync20 } from "fs";
11754
11962
  import { resolve as resolve19 } from "path";
11755
11963
  var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
11756
11964
  var app33 = new Hono();
@@ -11764,7 +11972,7 @@ app33.get("/", requireAdminSession, async (c) => {
11764
11972
  return new Response("Not found", { status: 404 });
11765
11973
  }
11766
11974
  const dir = resolve19(ATTACHMENTS_ROOT, accountId, id);
11767
- if (!existsSync19(dir)) {
11975
+ if (!existsSync20(dir)) {
11768
11976
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
11769
11977
  return new Response("Not found", { status: 404 });
11770
11978
  }
@@ -11798,14 +12006,14 @@ app33.get("/", requireAdminSession, async (c) => {
11798
12006
  var sidebar_artefact_content_default = app33;
11799
12007
 
11800
12008
  // server/routes/admin/health.ts
11801
- import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
11802
- import { resolve as resolve20, join as join9 } from "path";
12009
+ import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
12010
+ import { resolve as resolve20, join as join11 } from "path";
11803
12011
  var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
11804
12012
  var brandHostname = "maxy";
11805
- var brandJsonPath = join9(PLATFORM_ROOT7, "config", "brand.json");
11806
- if (existsSync20(brandJsonPath)) {
12013
+ var brandJsonPath = join11(PLATFORM_ROOT7, "config", "brand.json");
12014
+ if (existsSync21(brandJsonPath)) {
11807
12015
  try {
11808
- const brand = JSON.parse(readFileSync14(brandJsonPath, "utf-8"));
12016
+ const brand = JSON.parse(readFileSync15(brandJsonPath, "utf-8"));
11809
12017
  if (brand.hostname) brandHostname = brand.hostname;
11810
12018
  } catch {
11811
12019
  }
@@ -11814,8 +12022,8 @@ var VERSION_FILE = resolve20(PLATFORM_ROOT7, `config/.${brandHostname}-version`)
11814
12022
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
11815
12023
  var PROBE_TIMEOUT_MS = 1e3;
11816
12024
  function readVersion() {
11817
- if (!existsSync20(VERSION_FILE)) return "unknown";
11818
- return readFileSync14(VERSION_FILE, "utf-8").trim() || "unknown";
12025
+ if (!existsSync21(VERSION_FILE)) return "unknown";
12026
+ return readFileSync15(VERSION_FILE, "utf-8").trim() || "unknown";
11819
12027
  }
11820
12028
  async function probeConversationDb() {
11821
12029
  let session;
@@ -11895,7 +12103,7 @@ app35.route("/health-brand", health_default2);
11895
12103
  var admin_default = app35;
11896
12104
 
11897
12105
  // server/routes/sites.ts
11898
- import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
12106
+ import { existsSync as existsSync22, readFileSync as readFileSync16, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
11899
12107
  import { resolve as resolve21 } from "path";
11900
12108
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
11901
12109
  var MIME = {
@@ -11962,7 +12170,7 @@ app36.get("/:rel{.*}", (c) => {
11962
12170
  }
11963
12171
  let stat7;
11964
12172
  try {
11965
- stat7 = existsSync21(filePath) ? statSync5(filePath) : null;
12173
+ stat7 = existsSync22(filePath) ? statSync7(filePath) : null;
11966
12174
  } catch {
11967
12175
  stat7 = null;
11968
12176
  }
@@ -11975,7 +12183,7 @@ app36.get("/:rel{.*}", (c) => {
11975
12183
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
11976
12184
  return c.text("Forbidden", 403);
11977
12185
  }
11978
- if (!existsSync21(filePath)) {
12186
+ if (!existsSync22(filePath)) {
11979
12187
  console.error(`[sites] not-found path=${reqPath} status=404`);
11980
12188
  return c.text("Not found", 404);
11981
12189
  }
@@ -11994,7 +12202,7 @@ app36.get("/:rel{.*}", (c) => {
11994
12202
  }
11995
12203
  let body;
11996
12204
  try {
11997
- body = readFileSync15(realPath);
12205
+ body = readFileSync16(realPath);
11998
12206
  } catch (err) {
11999
12207
  const code = err?.code;
12000
12208
  if (code === "EISDIR") {
@@ -12126,14 +12334,14 @@ function clientFrom(c) {
12126
12334
  );
12127
12335
  }
12128
12336
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
12129
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join10(PLATFORM_ROOT8, "config", "brand.json") : "";
12337
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join12(PLATFORM_ROOT8, "config", "brand.json") : "";
12130
12338
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
12131
- if (BRAND_JSON_PATH && !existsSync22(BRAND_JSON_PATH)) {
12339
+ if (BRAND_JSON_PATH && !existsSync23(BRAND_JSON_PATH)) {
12132
12340
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
12133
12341
  }
12134
- if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12342
+ if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
12135
12343
  try {
12136
- const parsed = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
12344
+ const parsed = JSON.parse(readFileSync17(BRAND_JSON_PATH, "utf-8"));
12137
12345
  BRAND = { ...BRAND, ...parsed };
12138
12346
  } catch (err) {
12139
12347
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -12152,11 +12360,11 @@ var brandLoginOpts = {
12152
12360
  bodyFont: BRAND.defaultFonts?.body,
12153
12361
  logoContainsName: !!BRAND.logoContainsName
12154
12362
  };
12155
- var ALIAS_DOMAINS_PATH2 = join10(homedir2(), BRAND.configDir, "alias-domains.json");
12363
+ var ALIAS_DOMAINS_PATH2 = join12(homedir2(), BRAND.configDir, "alias-domains.json");
12156
12364
  function loadAliasDomains() {
12157
12365
  try {
12158
- if (!existsSync22(ALIAS_DOMAINS_PATH2)) return null;
12159
- const parsed = JSON.parse(readFileSync16(ALIAS_DOMAINS_PATH2, "utf-8"));
12366
+ if (!existsSync23(ALIAS_DOMAINS_PATH2)) return null;
12367
+ const parsed = JSON.parse(readFileSync17(ALIAS_DOMAINS_PATH2, "utf-8"));
12160
12368
  if (!Array.isArray(parsed)) {
12161
12369
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
12162
12370
  return null;
@@ -12502,14 +12710,14 @@ app37.get("/agent-assets/:slug/:filename", (c) => {
12502
12710
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
12503
12711
  return c.text("Forbidden", 403);
12504
12712
  }
12505
- if (!existsSync22(filePath)) {
12713
+ if (!existsSync23(filePath)) {
12506
12714
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
12507
12715
  return c.text("Not found", 404);
12508
12716
  }
12509
12717
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12510
12718
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12511
12719
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
12512
- const body = readFileSync16(filePath);
12720
+ const body = readFileSync17(filePath);
12513
12721
  return c.body(body, 200, {
12514
12722
  "Content-Type": contentType,
12515
12723
  "Cache-Control": "public, max-age=3600"
@@ -12532,14 +12740,14 @@ app37.get("/generated/:filename", (c) => {
12532
12740
  console.error(`[generated] serve file=${filename} status=403`);
12533
12741
  return c.text("Forbidden", 403);
12534
12742
  }
12535
- if (!existsSync22(filePath)) {
12743
+ if (!existsSync23(filePath)) {
12536
12744
  console.error(`[generated] serve file=${filename} status=404`);
12537
12745
  return c.text("Not found", 404);
12538
12746
  }
12539
12747
  const ext = "." + filename.split(".").pop()?.toLowerCase();
12540
12748
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
12541
12749
  console.log(`[generated] serve file=${filename} status=200`);
12542
- const body = readFileSync16(filePath);
12750
+ const body = readFileSync17(filePath);
12543
12751
  return c.body(body, 200, {
12544
12752
  "Content-Type": contentType,
12545
12753
  "Cache-Control": "public, max-age=86400"
@@ -12549,9 +12757,9 @@ app37.route("/sites", sites_default);
12549
12757
  var htmlCache = /* @__PURE__ */ new Map();
12550
12758
  var brandLogoPath = "/brand/maxy-monochrome.png";
12551
12759
  var brandIconPath = "/brand/maxy-monochrome.png";
12552
- if (BRAND_JSON_PATH && existsSync22(BRAND_JSON_PATH)) {
12760
+ if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
12553
12761
  try {
12554
- const fullBrand = JSON.parse(readFileSync16(BRAND_JSON_PATH, "utf-8"));
12762
+ const fullBrand = JSON.parse(readFileSync17(BRAND_JSON_PATH, "utf-8"));
12555
12763
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
12556
12764
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
12557
12765
  } catch {
@@ -12568,9 +12776,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
12568
12776
  function readInstalledVersion() {
12569
12777
  try {
12570
12778
  if (!PLATFORM_ROOT8) return "unknown";
12571
- const versionFile = join10(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
12572
- if (!existsSync22(versionFile)) return "unknown";
12573
- const content = readFileSync16(versionFile, "utf-8").trim();
12779
+ const versionFile = join12(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
12780
+ if (!existsSync23(versionFile)) return "unknown";
12781
+ const content = readFileSync17(versionFile, "utf-8").trim();
12574
12782
  return content || "unknown";
12575
12783
  } catch {
12576
12784
  return "unknown";
@@ -12611,7 +12819,7 @@ var clientErrorReporterScript = `<script>
12611
12819
  function cachedHtml(file) {
12612
12820
  let html = htmlCache.get(file);
12613
12821
  if (!html) {
12614
- html = readFileSync16(resolve22(process.cwd(), "public", file), "utf-8");
12822
+ html = readFileSync17(resolve22(process.cwd(), "public", file), "utf-8");
12615
12823
  const productNameEsc = escapeHtml(BRAND.productName);
12616
12824
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
12617
12825
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -12627,26 +12835,26 @@ ${clientErrorReporterScript}
12627
12835
  }
12628
12836
  var brandedHtmlCache = /* @__PURE__ */ new Map();
12629
12837
  function loadBrandingCache(agentSlug) {
12630
- const configDir2 = join10(homedir2(), BRAND.configDir);
12838
+ const configDir2 = join12(homedir2(), BRAND.configDir);
12631
12839
  try {
12632
- const accountJsonPath = join10(configDir2, "account.json");
12633
- if (!existsSync22(accountJsonPath)) return null;
12634
- const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
12840
+ const accountJsonPath = join12(configDir2, "account.json");
12841
+ if (!existsSync23(accountJsonPath)) return null;
12842
+ const account = JSON.parse(readFileSync17(accountJsonPath, "utf-8"));
12635
12843
  const accountId = account.accountId;
12636
12844
  if (!accountId) return null;
12637
- const cachePath = join10(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
12638
- if (!existsSync22(cachePath)) return null;
12639
- return JSON.parse(readFileSync16(cachePath, "utf-8"));
12845
+ const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
12846
+ if (!existsSync23(cachePath)) return null;
12847
+ return JSON.parse(readFileSync17(cachePath, "utf-8"));
12640
12848
  } catch {
12641
12849
  return null;
12642
12850
  }
12643
12851
  }
12644
12852
  function resolveDefaultSlug() {
12645
12853
  try {
12646
- const configDir2 = join10(homedir2(), BRAND.configDir);
12647
- const accountJsonPath = join10(configDir2, "account.json");
12648
- if (!existsSync22(accountJsonPath)) return null;
12649
- const account = JSON.parse(readFileSync16(accountJsonPath, "utf-8"));
12854
+ const configDir2 = join12(homedir2(), BRAND.configDir);
12855
+ const accountJsonPath = join12(configDir2, "account.json");
12856
+ if (!existsSync23(accountJsonPath)) return null;
12857
+ const account = JSON.parse(readFileSync17(accountJsonPath, "utf-8"));
12650
12858
  return account.defaultAgent || null;
12651
12859
  } catch {
12652
12860
  return null;
@@ -12719,7 +12927,7 @@ app37.use("/vnc-popout.html", logViewerFetch);
12719
12927
  app37.get("/vnc-popout.html", (c) => {
12720
12928
  let html = htmlCache.get("vnc-popout.html");
12721
12929
  if (!html) {
12722
- html = readFileSync16(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12930
+ html = readFileSync17(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
12723
12931
  const name = escapeHtml(BRAND.productName);
12724
12932
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
12725
12933
  html = html.replace("</head>", ` ${brandScript}
@@ -12777,6 +12985,7 @@ var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19
12777
12985
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
12778
12986
  var httpServer = serve({ fetch: app37.fetch, port, hostname });
12779
12987
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
12988
+ console.log("[boot] auth-mode summary: oauth=8 api-key=1 (api-key consumer: invokePublicAgent only)");
12780
12989
  var SUBAPP_MANIFEST = [
12781
12990
  { prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
12782
12991
  { prefix: "/api/session", file: "server/routes/session.ts", subapp: session_default },
@@ -12806,11 +13015,20 @@ try {
12806
13015
  } catch (err) {
12807
13016
  console.error(`[route-shadow] introspection unavailable: ${err instanceof Error ? err.message : String(err)}`);
12808
13017
  }
13018
+ try {
13019
+ checkAdminAuthInvariant({
13020
+ usersFile: USERS_FILE,
13021
+ accountsDir: ACCOUNTS_DIR,
13022
+ tag: "admin-invariant"
13023
+ });
13024
+ } catch (err) {
13025
+ console.error(`[admin-invariant] check threw \u2014 proceeding with boot: ${err instanceof Error ? err.message : String(err)}`);
13026
+ }
12809
13027
  (async () => {
12810
13028
  try {
12811
13029
  let userId = "";
12812
- if (existsSync22(USERS_FILE)) {
12813
- const users = JSON.parse(readFileSync16(USERS_FILE, "utf-8").trim() || "[]");
13030
+ if (existsSync23(USERS_FILE)) {
13031
+ const users = JSON.parse(readFileSync17(USERS_FILE, "utf-8").trim() || "[]");
12814
13032
  userId = users[0]?.userId ?? "";
12815
13033
  }
12816
13034
  await backfillNullUserIdConversations(userId);
@@ -12843,7 +13061,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
12843
13061
  (async () => {
12844
13062
  if (!bootAccount) return;
12845
13063
  try {
12846
- const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-MHALDN54.js");
13064
+ const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-XCUO4N74.js");
12847
13065
  const result = await recoverRunningCloudflareTasks(
12848
13066
  bootAccount.accountId,
12849
13067
  configDirForWhatsApp,
@@ -12893,7 +13111,7 @@ if (bootAccountConfig?.whatsapp) {
12893
13111
  }
12894
13112
  init({
12895
13113
  configDir: configDirForWhatsApp,
12896
- platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join10(__dirname, "..")),
13114
+ platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
12897
13115
  accountConfig: bootAccountConfig,
12898
13116
  onMessage: async (msg) => {
12899
13117
  try {