@rubytech/create-maxy 1.0.884 → 1.0.886

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.
@@ -42,7 +42,8 @@ import {
42
42
  load,
43
43
  logPath,
44
44
  pickComponentBytes,
45
- preflushSliceOf,
45
+ readBundleSubPlugins,
46
+ reconcileEnabledPlugins,
46
47
  recordFailedAttempt,
47
48
  render,
48
49
  renderLoginPage,
@@ -51,7 +52,6 @@ import {
51
52
  resolveAgentConfig,
52
53
  resolveBrowserTransport,
53
54
  resolveClientIp,
54
- resolveConversationLogPaths,
55
55
  resolveDefaultAgentSlug,
56
56
  resolveEntitlement,
57
57
  resolveUserAccounts,
@@ -76,7 +76,7 @@ import {
76
76
  vncLog,
77
77
  waitForExit,
78
78
  writeChromiumWrapper
79
- } from "./chunk-5PQU2HW2.js";
79
+ } from "./chunk-MOAY7KG2.js";
80
80
  import {
81
81
  CDP_PORT,
82
82
  COMMERCIAL_MODE,
@@ -90,6 +90,8 @@ import {
90
90
  clearSessionHistory,
91
91
  completeGrantSetup,
92
92
  consumeWantsPriorConversation,
93
+ emitMissingOnResolve,
94
+ fingerprintSessionKey,
93
95
  getAccountIdForSession,
94
96
  getActiveClient,
95
97
  getAgentNameForSession,
@@ -97,6 +99,7 @@ import {
97
99
  getGrantForSession,
98
100
  getGroupSlugForSession,
99
101
  getRoleForSession,
102
+ getSessionKeyByConversationId,
100
103
  getSessionMessages,
101
104
  getUserIdForSession,
102
105
  getUserNameForSession,
@@ -104,7 +107,6 @@ import {
104
107
  interruptClient,
105
108
  listAdminSessionsInProgress,
106
109
  mintAdminSessionToken,
107
- preConversationLogStream,
108
110
  registerGrantSession,
109
111
  registerResumedSession,
110
112
  registerSession,
@@ -115,7 +117,7 @@ import {
115
117
  sigtermFlushStreamLogs,
116
118
  unregisterSession,
117
119
  validateSession
118
- } from "./chunk-2INJCOYG.js";
120
+ } from "./chunk-IFMZ5I3E.js";
119
121
  import {
120
122
  CLOUDFLARE_TASK_DIAGNOSTICS,
121
123
  appendCloudflareSteps,
@@ -662,8 +664,8 @@ var serveStatic = (options = { root: "" }) => {
662
664
  };
663
665
 
664
666
  // server/index.ts
665
- import { readFileSync as readFileSync18, existsSync as existsSync23, watchFile } from "fs";
666
- import { resolve as resolve21, join as join11, basename as basename4 } from "path";
667
+ import { readFileSync as readFileSync18, existsSync as existsSync24, watchFile } from "fs";
668
+ import { resolve as resolve21, join as join12, basename as basename4 } from "path";
667
669
  import { homedir as homedir3 } from "os";
668
670
 
669
671
  // app/lib/agent-slug-pattern.ts
@@ -4425,9 +4427,8 @@ app3.post("/", async (c) => {
4425
4427
  if (!account) {
4426
4428
  return c.json({ error: "No account configured" }, 500);
4427
4429
  }
4428
- const publicSseConvId = getConversationIdForSession(session_key);
4429
- const sseLog = publicSseConvId ? agentLogStream("sse-events", account.accountDir, publicSseConvId) : preConversationLogStream("sse-events", account.accountDir);
4430
- const sk = publicSseConvId?.slice(0, 8) ?? session_key.slice(0, 8);
4430
+ const sseLog = agentLogStream("sse-events", account.accountDir, session_key);
4431
+ const sk = session_key.slice(0, 8);
4431
4432
  const agentName = getAgentNameForSession(session_key);
4432
4433
  if (!agentName) {
4433
4434
  console.log(`[chat] no agent for session=${sk} \u2014 session expired or server restarted`);
@@ -7017,7 +7018,8 @@ async function resolveUserIdentity(accountId, userId) {
7017
7018
  async function createAdminSession(accountId, thinkingView, userId, userName, role, avatar) {
7018
7019
  const account = resolveAccount();
7019
7020
  const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
7020
- const cacheKey = userId ? mintAdminSessionToken({ accountId, userId }) : crypto.randomUUID();
7021
+ const signedSessionToken = userId ? mintAdminSessionToken({ accountId, userId }) : crypto.randomUUID();
7022
+ const cacheKey = fingerprintSessionKey(signedSessionToken);
7021
7023
  registerSession(cacheKey, "admin", accountId, void 0, userId, userName, role);
7022
7024
  if (userId) setWantsPriorConversation(cacheKey);
7023
7025
  let onboardingComplete = true;
@@ -7053,7 +7055,7 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
7053
7055
  console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} admin session created: userId=${userId ?? "\u2013"} userName=${userName ?? "\u2013"} accountId=${accountId} conversationId=${initialConversationId ?? "unbound"} cacheKey=${cacheKey.slice(0, 8)}`);
7054
7056
  console.log(`[admin-session] role=${role ?? "null"} cacheKey=${cacheKey.slice(0, 8)} phase=create eager-ensured=${initialConversationId ? "true" : "false"}`);
7055
7057
  return {
7056
- session_key: cacheKey,
7058
+ session_key: signedSessionToken,
7057
7059
  agent_id: "admin",
7058
7060
  userId,
7059
7061
  userName,
@@ -7067,8 +7069,12 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
7067
7069
  }
7068
7070
  var app10 = new Hono();
7069
7071
  app10.get("/", async (c) => {
7070
- const cacheKey = c.req.query("session_key");
7071
- if (!cacheKey || !validateSession(cacheKey, "admin").ok) {
7072
+ const signedSessionToken = c.req.query("session_key");
7073
+ if (!signedSessionToken) {
7074
+ return c.json({ error: "Invalid or expired admin session" }, 401);
7075
+ }
7076
+ const cacheKey = fingerprintSessionKey(signedSessionToken);
7077
+ if (!validateSession(cacheKey, "admin", signedSessionToken).ok) {
7072
7078
  return c.json({ error: "Invalid or expired admin session" }, 401);
7073
7079
  }
7074
7080
  const accountId = getAccountIdForSession(cacheKey);
@@ -7104,7 +7110,7 @@ app10.get("/", async (c) => {
7104
7110
  }
7105
7111
  }
7106
7112
  return c.json({
7107
- session_key: cacheKey,
7113
+ session_key: signedSessionToken,
7108
7114
  agent_id: "admin",
7109
7115
  userId: restoredUserId,
7110
7116
  userName: restoredUserName,
@@ -7474,7 +7480,7 @@ var app11 = new Hono();
7474
7480
  app11.post("/cancel", requireAdminSession, async (c) => {
7475
7481
  const session_key = c.var.cacheKey;
7476
7482
  try {
7477
- const { interruptClient: interruptClient2 } = await import("./client-pool-JAM3QHGW.js");
7483
+ const { interruptClient: interruptClient2 } = await import("./client-pool-M6NS5G2U.js");
7478
7484
  await interruptClient2(session_key);
7479
7485
  return c.json({ ok: true });
7480
7486
  } catch (err) {
@@ -7578,8 +7584,7 @@ app11.post("/", requireAdminSession, async (c) => {
7578
7584
  try {
7579
7585
  const parsed = JSON.parse(message);
7580
7586
  if (parsed._lifecycle) {
7581
- const lifecycleConvId = getConversationIdForSession(session_key);
7582
- const lifecycleLog = lifecycleConvId ? agentLogStream("component-lifecycle", account.accountDir, lifecycleConvId) : preConversationLogStream("component-lifecycle", account.accountDir);
7587
+ const lifecycleLog = agentLogStream("component-lifecycle", account.accountDir, session_key);
7583
7588
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
7584
7589
  const detail = parsed.filePath ? ` filePath=${parsed.filePath}` : "";
7585
7590
  lifecycleLog.write(`[${ts}] [component:${parsed.component ?? "unknown"}] ${parsed.event ?? "unknown"}${detail}
@@ -7603,8 +7608,7 @@ app11.post("/", requireAdminSession, async (c) => {
7603
7608
  try {
7604
7609
  const parsed = JSON.parse(message);
7605
7610
  if (isComponentDone(parsed)) {
7606
- const componentConvId = getConversationIdForSession(session_key);
7607
- const componentLog = componentConvId ? agentLogStream("component-lifecycle", account.accountDir, componentConvId) : preConversationLogStream("component-lifecycle", account.accountDir);
7611
+ const componentLog = agentLogStream("component-lifecycle", account.accountDir, session_key);
7608
7612
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
7609
7613
  message = transformComponentDone(parsed);
7610
7614
  componentLog.write(`[${ts}] [component:${parsed.component}] componentDone \u2192 transformed
@@ -7668,11 +7672,11 @@ app11.post("/", requireAdminSession, async (c) => {
7668
7672
  }
7669
7673
  }
7670
7674
  const encoder = new TextEncoder();
7671
- const sseLogStream = agentLogStream("sse-events", account.accountDir, conversationId);
7675
+ const sseLogStream = agentLogStream("sse-events", account.accountDir, session_key);
7672
7676
  const sk = conversationId.slice(0, 8);
7673
- const teeStreamLogPath = resolve8(account.accountDir, "logs", `claude-agent-stream-${conversationId}.log`);
7677
+ const teeStreamLogPath = resolve8(account.accountDir, "logs", `claude-agent-stream-${session_key}.log`);
7674
7678
  try {
7675
- appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task965-mint-at-entry] cacheKey=${session_key.slice(0, 12)}\u2026 conversationId=${conversationId}
7679
+ appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task1006-sessionkey-on-disk] cacheKey=${session_key.slice(0, 12)}\u2026 conversationId=${conversationId}
7676
7680
  `);
7677
7681
  } catch {
7678
7682
  }
@@ -7760,7 +7764,7 @@ app11.post("/", requireAdminSession, async (c) => {
7760
7764
  const reqSignal = c.req.raw?.signal;
7761
7765
  if (reqSignal) {
7762
7766
  reqSignal.addEventListener("abort", () => {
7763
- const abortStreamLog = agentLogStream("claude-agent-stream", account.accountDir, conversationId);
7767
+ const abortStreamLog = agentLogStream("claude-agent-stream", account.accountDir, session_key);
7764
7768
  const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
7765
7769
  sseLog.write(`[${ts}] [${sk}] admin: ABORT [operator-cancel] interrupting pool client
7766
7770
  `);
@@ -7976,8 +7980,25 @@ app13.post("/", requireAdminSession, async (c) => {
7976
7980
  var compact_default = app13;
7977
7981
 
7978
7982
  // server/routes/admin/logs.ts
7979
- import { existsSync as existsSync12, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync6 } from "fs";
7983
+ import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync6 } from "fs";
7980
7984
  import { resolve as resolve9, basename as basename2 } from "path";
7985
+
7986
+ // app/lib/logs-read-resolve.ts
7987
+ import { existsSync as existsSync12 } from "fs";
7988
+ import { join as join9 } from "path";
7989
+ function resolveSessionLogPaths(filename, logDirs) {
7990
+ const tried = [filename];
7991
+ const hits = [];
7992
+ for (const dir of logDirs) {
7993
+ const fullPath = join9(dir, filename);
7994
+ if (existsSync12(fullPath)) {
7995
+ hits.push({ path: fullPath, dir });
7996
+ }
7997
+ }
7998
+ return { hits, tried };
7999
+ }
8000
+
8001
+ // server/routes/admin/logs.ts
7981
8002
  var TAIL_BYTES = 8192;
7982
8003
  var app14 = new Hono();
7983
8004
  app14.get("/", async (c) => {
@@ -8040,31 +8061,29 @@ app14.get("/", async (c) => {
8040
8061
  }
8041
8062
  const cacheKey = cacheKeyParam ?? null;
8042
8063
  const conversationId = conversationIdParam ?? null;
8043
- const MISSING_SENTINEL = ".task702-identifier-not-supplied.log";
8044
- const fullFilename = conversationId ? `${prefix}-${conversationId}.log` : MISSING_SENTINEL;
8045
- const preflushFilename = cacheKey && typeParam === "public" ? `${prefix}-${preflushSliceOf(cacheKey)}.log` : MISSING_SENTINEL;
8046
- const { hits, stalePreflushPaths, tried } = resolveConversationLogPaths(
8047
- fullFilename,
8048
- preflushFilename,
8049
- logDirs
8050
- );
8051
- const stalePreflushCount = stalePreflushPaths.length;
8064
+ const sessionKeyFromConv = conversationId ? getSessionKeyByConversationId(conversationId) ?? null : null;
8065
+ const primaryId = cacheKey ?? sessionKeyFromConv ?? conversationId;
8066
+ const fallbackId = primaryId !== conversationId && conversationId ? conversationId : null;
8067
+ const tried = [];
8068
+ let hit = null;
8069
+ if (primaryId) {
8070
+ const filename = `${prefix}-${primaryId}.log`;
8071
+ tried.push(filename);
8072
+ const result = resolveSessionLogPaths(filename, logDirs);
8073
+ if (result.hits.length > 0) hit = result.hits[0];
8074
+ }
8075
+ if (!hit && fallbackId) {
8076
+ const filename = `${prefix}-${fallbackId}.log`;
8077
+ tried.push(filename);
8078
+ const result = resolveSessionLogPaths(filename, logDirs);
8079
+ if (result.hits.length > 0) hit = result.hits[0];
8080
+ }
8052
8081
  const cacheKeySlice = cacheKey ? cacheKey.slice(0, 12) : "none";
8053
8082
  const conversationIdSlice = conversationId ? conversationId.slice(0, 12) : "none";
8054
- if (hits.length > 0) {
8055
- const hit = hits[0];
8056
- console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} conversationId=${conversationIdSlice} shape=${hit.shape} stalePreflushCount=${stalePreflushCount}`);
8083
+ if (hit) {
8084
+ console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} conversationId=${conversationIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "conversationId-fallback"}`);
8057
8085
  try {
8058
8086
  const filename = basename2(hit.path);
8059
- if (stalePreflushCount > 0 && !download) {
8060
- const content = readFileSync11(hit.path, "utf-8");
8061
- return c.json({
8062
- log: content,
8063
- filename,
8064
- shape: hit.shape,
8065
- warnings: stalePreflushPaths.map((path2) => ({ kind: "stale-preflush", path: path2 }))
8066
- });
8067
- }
8068
8087
  const buffer = readFileSync11(hit.path);
8069
8088
  const onDiskBytes = statSync6(hit.path).size;
8070
8089
  const headers = {
@@ -8083,7 +8102,8 @@ app14.get("/", async (c) => {
8083
8102
  );
8084
8103
  }
8085
8104
  }
8086
- const reason = !conversationId ? "no preflush log on disk for cacheKey and conversationId not derivable" : !cacheKey ? "no full log on disk and cacheKey not derivable" : "no preflush log, no full log";
8105
+ const reason = "no log file on disk for the given identifier(s)";
8106
+ if (primaryId) emitMissingOnResolve(primaryId, "admin-logs-route", reason);
8087
8107
  console.warn(`[admin/logs] not-found tried=[${tried.join(",")}] cacheKey=${cacheKeySlice} conversationId=${conversationIdSlice} reason=${JSON.stringify(reason)}`);
8088
8108
  return c.json(
8089
8109
  {
@@ -8099,7 +8119,7 @@ app14.get("/", async (c) => {
8099
8119
  const seen = /* @__PURE__ */ new Set();
8100
8120
  const logs = {};
8101
8121
  for (const dir of logDirs) {
8102
- if (!existsSync12(dir)) continue;
8122
+ if (!existsSync13(dir)) continue;
8103
8123
  let files;
8104
8124
  try {
8105
8125
  files = readdirSync5(dir).filter((f) => f.endsWith(".log"));
@@ -8150,7 +8170,7 @@ var claude_info_default = app15;
8150
8170
 
8151
8171
  // server/routes/admin/attachment.ts
8152
8172
  import { readFile as readFile2, readdir } from "fs/promises";
8153
- import { existsSync as existsSync13 } from "fs";
8173
+ import { existsSync as existsSync14 } from "fs";
8154
8174
  import { resolve as resolve10 } from "path";
8155
8175
  var app16 = new Hono();
8156
8176
  app16.get("/:attachmentId", requireAdminSession, async (c) => {
@@ -8164,11 +8184,11 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
8164
8184
  return new Response("Not found", { status: 404 });
8165
8185
  }
8166
8186
  const dir = resolve10(ATTACHMENTS_ROOT, accountId, attachmentId);
8167
- if (!existsSync13(dir)) {
8187
+ if (!existsSync14(dir)) {
8168
8188
  return new Response("Not found", { status: 404 });
8169
8189
  }
8170
8190
  const metaPath = resolve10(dir, `${attachmentId}.meta.json`);
8171
- if (!existsSync13(metaPath)) {
8191
+ if (!existsSync14(metaPath)) {
8172
8192
  return new Response("Not found", { status: 404 });
8173
8193
  }
8174
8194
  let meta;
@@ -8196,13 +8216,13 @@ var attachment_default = app16;
8196
8216
 
8197
8217
  // server/routes/admin/agents.ts
8198
8218
  import { resolve as resolve11 } from "path";
8199
- import { readdirSync as readdirSync6, readFileSync as readFileSync12, existsSync as existsSync14, rmSync } from "fs";
8219
+ import { readdirSync as readdirSync6, readFileSync as readFileSync12, existsSync as existsSync15, rmSync } from "fs";
8200
8220
  var app17 = new Hono();
8201
8221
  app17.get("/", (c) => {
8202
8222
  const account = resolveAccount();
8203
8223
  if (!account) return c.json({ agents: [] });
8204
8224
  const agentsDir = resolve11(account.accountDir, "agents");
8205
- if (!existsSync14(agentsDir)) return c.json({ agents: [] });
8225
+ if (!existsSync15(agentsDir)) return c.json({ agents: [] });
8206
8226
  const agents = [];
8207
8227
  try {
8208
8228
  const entries = readdirSync6(agentsDir, { withFileTypes: true });
@@ -8210,7 +8230,7 @@ app17.get("/", (c) => {
8210
8230
  if (!entry.isDirectory()) continue;
8211
8231
  if (entry.name === "admin") continue;
8212
8232
  const configPath2 = resolve11(agentsDir, entry.name, "config.json");
8213
- if (!existsSync14(configPath2)) continue;
8233
+ if (!existsSync15(configPath2)) continue;
8214
8234
  try {
8215
8235
  const config = JSON.parse(readFileSync12(configPath2, "utf-8"));
8216
8236
  agents.push({
@@ -8239,7 +8259,7 @@ app17.delete("/:slug", async (c) => {
8239
8259
  return c.json({ error: "Invalid agent slug" }, 400);
8240
8260
  }
8241
8261
  const agentDir = resolve11(account.accountDir, "agents", slug);
8242
- if (!existsSync14(agentDir)) {
8262
+ if (!existsSync15(agentDir)) {
8243
8263
  return c.json({ error: "Agent not found" }, 404);
8244
8264
  }
8245
8265
  try {
@@ -8269,7 +8289,7 @@ app17.post("/:slug/project", async (c) => {
8269
8289
  return c.json({ error: "Invalid agent slug" }, 400);
8270
8290
  }
8271
8291
  const agentDir = resolve11(account.accountDir, "agents", slug);
8272
- if (!existsSync14(agentDir)) {
8292
+ if (!existsSync15(agentDir)) {
8273
8293
  return c.json({ error: "Agent not found on disk" }, 404);
8274
8294
  }
8275
8295
  try {
@@ -8285,7 +8305,7 @@ var agents_default = app17;
8285
8305
  // server/routes/admin/sessions.ts
8286
8306
  import crypto2 from "crypto";
8287
8307
  import { resolve as resolvePath } from "path";
8288
- import { appendFileSync as appendFileSync4, existsSync as existsSync16 } from "fs";
8308
+ import { appendFileSync as appendFileSync4, existsSync as existsSync17 } from "fs";
8289
8309
 
8290
8310
  // app/lib/synthetic-marker.ts
8291
8311
  var CLOUDFLARE_MARKER_PREFIX = "Cloudflare setup completed (actionId: ";
@@ -8297,9 +8317,9 @@ function isSyntheticUserMarker(content) {
8297
8317
  }
8298
8318
 
8299
8319
  // app/lib/claude-agent/jsonl-replay.ts
8300
- import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
8320
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
8301
8321
  function replayJsonl(jsonlPath) {
8302
- if (!existsSync15(jsonlPath)) {
8322
+ if (!existsSync16(jsonlPath)) {
8303
8323
  return { messages: [], jsonlMissing: true, malformedLines: 0 };
8304
8324
  }
8305
8325
  let raw;
@@ -8464,7 +8484,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, conversationId
8464
8484
  let reason = null;
8465
8485
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
8466
8486
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
8467
- else if (!existsSync16(a.storagePath)) reason = "missing-file";
8487
+ else if (!existsSync17(a.storagePath)) reason = "missing-file";
8468
8488
  if (reason) {
8469
8489
  invalid++;
8470
8490
  try {
@@ -8619,13 +8639,14 @@ app18.post("/new", requireAdminSession, async (c) => {
8619
8639
  if (!accountId || !userId) {
8620
8640
  return c.json({ error: "Session missing account or user context" }, 400);
8621
8641
  }
8622
- const newCacheKey = crypto2.randomUUID();
8642
+ const newSignedSessionToken = crypto2.randomUUID();
8643
+ const newCacheKey = fingerprintSessionKey(newSignedSessionToken);
8623
8644
  const userName = getUserNameForSession(oldCacheKey);
8624
8645
  registerSession(newCacheKey, "admin", accountId, void 0, userId, userName);
8625
8646
  const previousConversationId = clearSessionHistory(oldCacheKey);
8626
8647
  unregisterSession(oldCacheKey);
8627
8648
  console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} session reset for new conversation: oldCacheKey=${oldCacheKey.slice(0, 8)}\u2026 newCacheKey=${newCacheKey.slice(0, 8)}\u2026 previousConversationId=${previousConversationId?.slice(0, 8) ?? "none"}\u2026 newConversationId=deferred`);
8628
- return c.json({ session_key: newCacheKey, conversationId: null });
8649
+ return c.json({ session_key: newSignedSessionToken, conversationId: null });
8629
8650
  });
8630
8651
  app18.post("/switch", requireAdminSession, async (c) => {
8631
8652
  const cacheKey = c.var.cacheKey;
@@ -8635,11 +8656,12 @@ app18.post("/switch", requireAdminSession, async (c) => {
8635
8656
  return c.json({ error: "Session missing account or user context" }, 400);
8636
8657
  }
8637
8658
  const body = await c.req.json().catch(() => ({}));
8638
- const targetCacheKey = typeof body.target_session_key === "string" ? body.target_session_key : "";
8639
- if (!targetCacheKey) {
8659
+ const targetSignedSessionToken = typeof body.target_session_key === "string" ? body.target_session_key : "";
8660
+ if (!targetSignedSessionToken) {
8640
8661
  return c.json({ error: "target_session_key required" }, 400);
8641
8662
  }
8642
- const targetCheck = validateSession(targetCacheKey, "admin");
8663
+ const targetCacheKey = fingerprintSessionKey(targetSignedSessionToken);
8664
+ const targetCheck = validateSession(targetCacheKey, "admin", targetSignedSessionToken);
8643
8665
  if (!targetCheck.ok) {
8644
8666
  console.error(`[session-switch] reject reason=${targetCheck.reason} from=${cacheKey.slice(0, 8)} target=${targetCacheKey.slice(0, 8)}`);
8645
8667
  return c.json({ error: "Target session not registered or wrong agent type", code: targetCheck.reason }, 404);
@@ -8652,7 +8674,7 @@ app18.post("/switch", requireAdminSession, async (c) => {
8652
8674
  }
8653
8675
  const targetConversationId = getConversationIdForSession(targetCacheKey) ?? null;
8654
8676
  console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetConversationId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
8655
- return c.json({ session_key: targetCacheKey, conversationId: targetConversationId });
8677
+ return c.json({ session_key: targetSignedSessionToken, conversationId: targetConversationId });
8656
8678
  });
8657
8679
  app18.delete("/:id", requireAdminSession, async (c) => {
8658
8680
  const conversationId = c.req.param("id");
@@ -8671,13 +8693,14 @@ app18.delete("/:id", requireAdminSession, async (c) => {
8671
8693
  });
8672
8694
  app18.post("/:id/resume", async (c) => {
8673
8695
  const conversationId = c.req.param("id");
8674
- const cacheKey = c.req.query("session_key") ?? "";
8675
- if (!cacheKey) {
8696
+ const signedSessionToken = c.req.query("session_key") ?? "";
8697
+ if (!signedSessionToken) {
8676
8698
  console.error(`[session] middleware-reject status=400 code=session-missing reason="session_key required" path=${c.req.path}`);
8677
8699
  return c.json({ error: "session_key required", code: "session-missing" }, 400);
8678
8700
  }
8701
+ const cacheKey = fingerprintSessionKey(signedSessionToken);
8679
8702
  let bridged = false;
8680
- let result = validateSession(cacheKey, "admin");
8703
+ let result = validateSession(cacheKey, "admin", signedSessionToken);
8681
8704
  if (!result.ok) {
8682
8705
  if (result.reason === "session-not-registered") {
8683
8706
  const bridge = await tryCookieBridgeForConversation(c, cacheKey, conversationId);
@@ -8690,7 +8713,7 @@ app18.post("/:id/resume", async (c) => {
8690
8713
  return c.json({ error: "Invalid or expired admin session", code: "session-not-registered" }, 401);
8691
8714
  }
8692
8715
  bridged = true;
8693
- result = validateSession(cacheKey, "admin");
8716
+ result = validateSession(cacheKey, "admin", signedSessionToken);
8694
8717
  if (!result.ok) {
8695
8718
  const tail = cacheKey.slice(0, 8);
8696
8719
  console.error(`[session] middleware-reject status=401 code=session-not-registered reason="post-bridge re-validate failed" path=${c.req.path} cacheKey=${tail}\u2026`);
@@ -9255,12 +9278,12 @@ function isValidDomain(value) {
9255
9278
  }
9256
9279
 
9257
9280
  // app/lib/alias-domains.ts
9258
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
9281
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
9259
9282
  import { dirname as dirname5 } from "path";
9260
9283
  import { resolve as resolve12 } from "path";
9261
9284
  var ALIAS_DOMAINS_PATH = resolve12(MAXY_DIR, "alias-domains.json");
9262
9285
  function readExisting() {
9263
- if (!existsSync17(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
9286
+ if (!existsSync18(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
9264
9287
  try {
9265
9288
  const parsed = JSON.parse(readFileSync14(ALIAS_DOMAINS_PATH, "utf-8"));
9266
9289
  if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
@@ -9534,8 +9557,8 @@ app23.get("/tunnels", requireAdminSession, async (c) => {
9534
9557
  if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
9535
9558
  streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
9536
9559
  const certPath = resolve13(homedir2(), brand.configDir, "cloudflared", "cert.pem");
9537
- const { existsSync: existsSync24 } = await import("fs");
9538
- if (!existsSync24(certPath)) {
9560
+ const { existsSync: existsSync25 } = await import("fs");
9561
+ if (!existsSync25(certPath)) {
9539
9562
  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.`);
9540
9563
  }
9541
9564
  const result = await runFormSpawn({
@@ -9859,7 +9882,7 @@ var cloudflare_default = app23;
9859
9882
  import { createReadStream as createReadStream3 } from "fs";
9860
9883
  import { readdir as readdir2, readFile as readFile3, stat as stat3, mkdir as mkdir2, writeFile as writeFile3, unlink as unlink2 } from "fs/promises";
9861
9884
  import { realpathSync as realpathSync3 } from "fs";
9862
- import { basename as basename3, dirname as dirname6, join as join9, resolve as resolve15, sep as sep2 } from "path";
9885
+ import { basename as basename3, dirname as dirname6, join as join10, resolve as resolve15, sep as sep2 } from "path";
9863
9886
  import { Readable as Readable2 } from "stream";
9864
9887
 
9865
9888
  // app/lib/data-path.ts
@@ -10217,7 +10240,7 @@ async function cascadeDeleteDocument(params) {
10217
10240
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10218
10241
  async function readMeta(absDir, baseName) {
10219
10242
  try {
10220
- const raw = await readFile3(join9(absDir, `${baseName}.meta.json`), "utf8");
10243
+ const raw = await readFile3(join10(absDir, `${baseName}.meta.json`), "utf8");
10221
10244
  const parsed = JSON.parse(raw);
10222
10245
  if (typeof parsed?.filename === "string") {
10223
10246
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -10255,7 +10278,7 @@ async function readAccountNames() {
10255
10278
  }
10256
10279
  async function enrich(absolute, entry, accountNames) {
10257
10280
  if (entry.kind === "directory" && UUID_RE5.test(entry.name)) {
10258
- const meta = await readMeta(join9(absolute, entry.name), entry.name);
10281
+ const meta = await readMeta(join10(absolute, entry.name), entry.name);
10259
10282
  if (meta?.filename) {
10260
10283
  entry.displayName = meta.filename;
10261
10284
  entry.mimeType = meta.mimeType;
@@ -10314,7 +10337,7 @@ app24.get("/", requireAdminSession, async (c) => {
10314
10337
  continue;
10315
10338
  }
10316
10339
  try {
10317
- const entryPath = join9(absolute, name);
10340
+ const entryPath = join10(absolute, name);
10318
10341
  const s = await stat3(entryPath);
10319
10342
  entries.push({
10320
10343
  name,
@@ -10487,7 +10510,7 @@ app24.delete("/", requireAdminSession, async (c) => {
10487
10510
  }
10488
10511
  const dot = base.lastIndexOf(".");
10489
10512
  const stem = dot === -1 ? base : base.slice(0, dot);
10490
- const sidecarPath = UUID_RE5.test(stem) && base !== `${stem}.meta.json` ? join9(dirname6(absolute), `${stem}.meta.json`) : null;
10513
+ const sidecarPath = UUID_RE5.test(stem) && base !== `${stem}.meta.json` ? join10(dirname6(absolute), `${stem}.meta.json`) : null;
10491
10514
  await unlink2(absolute);
10492
10515
  if (sidecarPath) {
10493
10516
  try {
@@ -12178,7 +12201,7 @@ var adherence_default = app32;
12178
12201
  import neo4j3 from "neo4j-driver";
12179
12202
  import { readFile as readFile4, readdir as readdir3, stat as stat4 } from "fs/promises";
12180
12203
  import { resolve as resolve16, relative as relative2, isAbsolute } from "path";
12181
- import { existsSync as existsSync18 } from "fs";
12204
+ import { existsSync as existsSync19 } from "fs";
12182
12205
  var LIMIT = 50;
12183
12206
  var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
12184
12207
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -12326,7 +12349,7 @@ async function fetchAgentTemplateRows(accountDir) {
12326
12349
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
12327
12350
  const names = /* @__PURE__ */ new Set();
12328
12351
  for (const dir of [overrideDir, bundledDir]) {
12329
- if (!existsSync18(dir)) continue;
12352
+ if (!existsSync19(dir)) continue;
12330
12353
  try {
12331
12354
  const entries = await readdir3(dir);
12332
12355
  for (const entry of entries) {
@@ -12341,7 +12364,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
12341
12364
  }
12342
12365
  async function readAgentTemplateRow(inp) {
12343
12366
  let chosenPath = null;
12344
- if (existsSync18(inp.overridePath)) {
12367
+ if (existsSync19(inp.overridePath)) {
12345
12368
  try {
12346
12369
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
12347
12370
  chosenPath = inp.overridePath;
@@ -12352,7 +12375,7 @@ async function readAgentTemplateRow(inp) {
12352
12375
  );
12353
12376
  return null;
12354
12377
  }
12355
- } else if (existsSync18(inp.bundledPath)) {
12378
+ } else if (existsSync19(inp.bundledPath)) {
12356
12379
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
12357
12380
  console.error(
12358
12381
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -12394,7 +12417,7 @@ var sidebar_artefacts_default = app33;
12394
12417
  // server/routes/admin/sidebar-artefact-save.ts
12395
12418
  import { mkdir as mkdir3, readdir as readdir4, stat as stat5, writeFile as writeFile4 } from "fs/promises";
12396
12419
  import { resolve as resolve17 } from "path";
12397
- import { existsSync as existsSync19 } from "fs";
12420
+ import { existsSync as existsSync20 } from "fs";
12398
12421
  var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
12399
12422
  var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12400
12423
  var app34 = new Hono();
@@ -12462,7 +12485,7 @@ async function resolveSavePath(id, accountId, accountDir) {
12462
12485
  }
12463
12486
  if (UUID_RE6.test(id)) {
12464
12487
  const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
12465
- if (!existsSync19(dir)) {
12488
+ if (!existsSync20(dir)) {
12466
12489
  const attShort = id.slice(0, 8);
12467
12490
  if (isHealPending(accountId, id)) {
12468
12491
  console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=503-retry source=heal-pending`);
@@ -12514,7 +12537,7 @@ var sidebar_artefact_save_default = app34;
12514
12537
 
12515
12538
  // server/routes/admin/sidebar-artefact-content.ts
12516
12539
  import { readFile as readFile5, readdir as readdir5 } from "fs/promises";
12517
- import { existsSync as existsSync20 } from "fs";
12540
+ import { existsSync as existsSync21 } from "fs";
12518
12541
  import { resolve as resolve18 } from "path";
12519
12542
  var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
12520
12543
  var app35 = new Hono();
@@ -12528,7 +12551,7 @@ app35.get("/", requireAdminSession, async (c) => {
12528
12551
  return new Response("Not found", { status: 404 });
12529
12552
  }
12530
12553
  const dir = resolve18(ATTACHMENTS_ROOT, accountId, id);
12531
- if (!existsSync20(dir)) {
12554
+ if (!existsSync21(dir)) {
12532
12555
  console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
12533
12556
  return new Response("Not found", { status: 404 });
12534
12557
  }
@@ -12562,12 +12585,12 @@ app35.get("/", requireAdminSession, async (c) => {
12562
12585
  var sidebar_artefact_content_default = app35;
12563
12586
 
12564
12587
  // server/routes/admin/health.ts
12565
- import { existsSync as existsSync21, readFileSync as readFileSync16 } from "fs";
12566
- import { resolve as resolve19, join as join10 } from "path";
12588
+ import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
12589
+ import { resolve as resolve19, join as join11 } from "path";
12567
12590
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
12568
12591
  var brandHostname = "maxy";
12569
- var brandJsonPath = join10(PLATFORM_ROOT6, "config", "brand.json");
12570
- if (existsSync21(brandJsonPath)) {
12592
+ var brandJsonPath = join11(PLATFORM_ROOT6, "config", "brand.json");
12593
+ if (existsSync22(brandJsonPath)) {
12571
12594
  try {
12572
12595
  const brand = JSON.parse(readFileSync16(brandJsonPath, "utf-8"));
12573
12596
  if (brand.hostname) brandHostname = brand.hostname;
@@ -12578,7 +12601,7 @@ var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
12578
12601
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
12579
12602
  var PROBE_TIMEOUT_MS = 1e3;
12580
12603
  function readVersion() {
12581
- if (!existsSync21(VERSION_FILE)) return "unknown";
12604
+ if (!existsSync22(VERSION_FILE)) return "unknown";
12582
12605
  return readFileSync16(VERSION_FILE, "utf-8").trim() || "unknown";
12583
12606
  }
12584
12607
  async function probeConversationDb() {
@@ -12661,7 +12684,7 @@ app37.route("/health-brand", health_default2);
12661
12684
  var admin_default = app37;
12662
12685
 
12663
12686
  // server/routes/sites.ts
12664
- import { existsSync as existsSync22, readFileSync as readFileSync17, realpathSync as realpathSync4, statSync as statSync7 } from "fs";
12687
+ import { existsSync as existsSync23, readFileSync as readFileSync17, realpathSync as realpathSync4, statSync as statSync7 } from "fs";
12665
12688
  import { resolve as resolve20 } from "path";
12666
12689
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
12667
12690
  var MIME = {
@@ -12727,7 +12750,7 @@ app38.get("/:rel{.*}", (c) => {
12727
12750
  }
12728
12751
  let stat6;
12729
12752
  try {
12730
- stat6 = existsSync22(filePath) ? statSync7(filePath) : null;
12753
+ stat6 = existsSync23(filePath) ? statSync7(filePath) : null;
12731
12754
  } catch {
12732
12755
  stat6 = null;
12733
12756
  }
@@ -12746,7 +12769,7 @@ app38.get("/:rel{.*}", (c) => {
12746
12769
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
12747
12770
  return c.text("Forbidden", 403);
12748
12771
  }
12749
- if (!existsSync22(filePath)) {
12772
+ if (!existsSync23(filePath)) {
12750
12773
  console.error(`[sites] not-found path=${reqPath} status=404`);
12751
12774
  return c.text("Not found", 404);
12752
12775
  }
@@ -12867,10 +12890,42 @@ async function verifyUserProfileConstraint() {
12867
12890
  await session.close();
12868
12891
  }
12869
12892
  }
12893
+ async function verifySessionKeyAdherence() {
12894
+ const session = getSession();
12895
+ try {
12896
+ const convResult = await session.run(
12897
+ `MATCH (c:Conversation) WHERE c.sessionKey IS NULL RETURN count(c) AS n`
12898
+ );
12899
+ const convNull = convResult.records[0]?.get("n")?.toNumber?.() ?? 0;
12900
+ console.error(
12901
+ `[migration-1007] adherence-check label=Conversation rows-with-null-sessionkey=${convNull}`
12902
+ );
12903
+ const msgResult = await session.run(
12904
+ `MATCH (m:Message) WHERE m.sessionKey IS NULL RETURN count(m) AS n`
12905
+ );
12906
+ const msgNull = msgResult.records[0]?.get("n")?.toNumber?.() ?? 0;
12907
+ console.error(
12908
+ `[migration-1007] adherence-check label=Message rows-with-null-sessionkey=${msgNull}`
12909
+ );
12910
+ if (convNull > 0 || msgNull > 0) {
12911
+ console.error(
12912
+ `[migration-1007] adherence-check P0=true reason=null-sessionkey-on-boot \u2014 re-run seed-neo4j.sh`
12913
+ );
12914
+ }
12915
+ } catch (err) {
12916
+ console.error(
12917
+ `[migration-1007] adherence-check verify failed: ${err instanceof Error ? err.message : String(err)}`
12918
+ );
12919
+ } finally {
12920
+ await session.close();
12921
+ }
12922
+ }
12870
12923
  function startGraphHealthTimer() {
12871
12924
  if (timer) return;
12872
12925
  verifyUserProfileConstraint().catch(() => {
12873
12926
  });
12927
+ verifySessionKeyAdherence().catch(() => {
12928
+ });
12874
12929
  runGraphHealthTick().catch(() => {
12875
12930
  });
12876
12931
  timer = setInterval(() => {
@@ -12881,7 +12936,7 @@ function startGraphHealthTimer() {
12881
12936
  }
12882
12937
 
12883
12938
  // server/index.ts
12884
- import { existsSync as existsSyncBoot, readFileSync as readFileSyncBoot } from "fs";
12939
+ import { existsSync as existsSyncBoot } from "fs";
12885
12940
  import { resolve as resolveBoot } from "path";
12886
12941
  function requestIsTlsTerminated(c) {
12887
12942
  const remote = c.env?.incoming?.socket?.remoteAddress ?? "";
@@ -12897,12 +12952,12 @@ function clientFrom(c) {
12897
12952
  );
12898
12953
  }
12899
12954
  var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
12900
- var BRAND_JSON_PATH = PLATFORM_ROOT7 ? join11(PLATFORM_ROOT7, "config", "brand.json") : "";
12955
+ var BRAND_JSON_PATH = PLATFORM_ROOT7 ? join12(PLATFORM_ROOT7, "config", "brand.json") : "";
12901
12956
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
12902
- if (BRAND_JSON_PATH && !existsSync23(BRAND_JSON_PATH)) {
12957
+ if (BRAND_JSON_PATH && !existsSync24(BRAND_JSON_PATH)) {
12903
12958
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
12904
12959
  }
12905
- if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
12960
+ if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
12906
12961
  try {
12907
12962
  const parsed = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
12908
12963
  BRAND = { ...BRAND, ...parsed };
@@ -12923,10 +12978,10 @@ var brandLoginOpts = {
12923
12978
  bodyFont: BRAND.defaultFonts?.body,
12924
12979
  logoContainsName: !!BRAND.logoContainsName
12925
12980
  };
12926
- var ALIAS_DOMAINS_PATH2 = join11(homedir3(), BRAND.configDir, "alias-domains.json");
12981
+ var ALIAS_DOMAINS_PATH2 = join12(homedir3(), BRAND.configDir, "alias-domains.json");
12927
12982
  function loadAliasDomains() {
12928
12983
  try {
12929
- if (!existsSync23(ALIAS_DOMAINS_PATH2)) return null;
12984
+ if (!existsSync24(ALIAS_DOMAINS_PATH2)) return null;
12930
12985
  const parsed = JSON.parse(readFileSync18(ALIAS_DOMAINS_PATH2, "utf-8"));
12931
12986
  if (!Array.isArray(parsed)) {
12932
12987
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
@@ -13199,7 +13254,8 @@ app39.post("/api/remote-auth/set-password", async (c) => {
13199
13254
  } catch {
13200
13255
  return c.json({ error: "Invalid request" }, 400);
13201
13256
  }
13202
- if (!body.session_key || !validateSession(body.session_key, "admin").ok) {
13257
+ const cacheKey = body.session_key ? fingerprintSessionKey(body.session_key) : "";
13258
+ if (!cacheKey || !validateSession(cacheKey, "admin", body.session_key).ok) {
13203
13259
  return c.json({ error: "Unauthorized" }, 401);
13204
13260
  }
13205
13261
  if (!body.password) {
@@ -13306,7 +13362,7 @@ app39.get("/agent-assets/:slug/:filename", (c) => {
13306
13362
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
13307
13363
  return c.text("Forbidden", 403);
13308
13364
  }
13309
- if (!existsSync23(filePath)) {
13365
+ if (!existsSync24(filePath)) {
13310
13366
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
13311
13367
  return c.text("Not found", 404);
13312
13368
  }
@@ -13336,7 +13392,7 @@ app39.get("/generated/:filename", (c) => {
13336
13392
  console.error(`[generated] serve file=${filename} status=403`);
13337
13393
  return c.text("Forbidden", 403);
13338
13394
  }
13339
- if (!existsSync23(filePath)) {
13395
+ if (!existsSync24(filePath)) {
13340
13396
  console.error(`[generated] serve file=${filename} status=404`);
13341
13397
  return c.text("Not found", 404);
13342
13398
  }
@@ -13353,7 +13409,7 @@ app39.route("/sites", sites_default);
13353
13409
  var htmlCache = /* @__PURE__ */ new Map();
13354
13410
  var brandLogoPath = "/brand/maxy-monochrome.png";
13355
13411
  var brandIconPath = "/brand/maxy-monochrome.png";
13356
- if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
13412
+ if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
13357
13413
  try {
13358
13414
  const fullBrand = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
13359
13415
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
@@ -13372,8 +13428,8 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
13372
13428
  function readInstalledVersion() {
13373
13429
  try {
13374
13430
  if (!PLATFORM_ROOT7) return "unknown";
13375
- const versionFile = join11(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
13376
- if (!existsSync23(versionFile)) return "unknown";
13431
+ const versionFile = join12(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
13432
+ if (!existsSync24(versionFile)) return "unknown";
13377
13433
  const content = readFileSync18(versionFile, "utf-8").trim();
13378
13434
  return content || "unknown";
13379
13435
  } catch {
@@ -13431,15 +13487,15 @@ ${clientErrorReporterScript}
13431
13487
  }
13432
13488
  var brandedHtmlCache = /* @__PURE__ */ new Map();
13433
13489
  function loadBrandingCache(agentSlug) {
13434
- const configDir2 = join11(homedir3(), BRAND.configDir);
13490
+ const configDir2 = join12(homedir3(), BRAND.configDir);
13435
13491
  try {
13436
- const accountJsonPath = join11(configDir2, "account.json");
13437
- if (!existsSync23(accountJsonPath)) return null;
13492
+ const accountJsonPath = join12(configDir2, "account.json");
13493
+ if (!existsSync24(accountJsonPath)) return null;
13438
13494
  const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
13439
13495
  const accountId = account.accountId;
13440
13496
  if (!accountId) return null;
13441
- const cachePath = join11(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
13442
- if (!existsSync23(cachePath)) return null;
13497
+ const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
13498
+ if (!existsSync24(cachePath)) return null;
13443
13499
  return JSON.parse(readFileSync18(cachePath, "utf-8"));
13444
13500
  } catch {
13445
13501
  return null;
@@ -13447,9 +13503,9 @@ function loadBrandingCache(agentSlug) {
13447
13503
  }
13448
13504
  function resolveDefaultSlug() {
13449
13505
  try {
13450
- const configDir2 = join11(homedir3(), BRAND.configDir);
13451
- const accountJsonPath = join11(configDir2, "account.json");
13452
- if (!existsSync23(accountJsonPath)) return null;
13506
+ const configDir2 = join12(homedir3(), BRAND.configDir);
13507
+ const accountJsonPath = join12(configDir2, "account.json");
13508
+ if (!existsSync24(accountJsonPath)) return null;
13453
13509
  const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
13454
13510
  return account.defaultAgent || null;
13455
13511
  } catch {
@@ -13629,7 +13685,7 @@ try {
13629
13685
  (async () => {
13630
13686
  try {
13631
13687
  let userId = "";
13632
- if (existsSync23(USERS_FILE)) {
13688
+ if (existsSync24(USERS_FILE)) {
13633
13689
  const users = JSON.parse(readFileSync18(USERS_FILE, "utf-8").trim() || "[]");
13634
13690
  userId = users[0]?.userId ?? "";
13635
13691
  }
@@ -13647,7 +13703,7 @@ try {
13647
13703
  })();
13648
13704
  (async () => {
13649
13705
  try {
13650
- if (!existsSync23(USERS_FILE)) return;
13706
+ if (!existsSync24(USERS_FILE)) return;
13651
13707
  const usersRaw = readFileSync18(USERS_FILE, "utf-8").trim();
13652
13708
  if (!usersRaw) return;
13653
13709
  const users = JSON.parse(usersRaw);
@@ -13700,6 +13756,11 @@ autoDeliverPremiumPlugins(
13700
13756
  bootAccount?.accountDir,
13701
13757
  bootAccount?.config
13702
13758
  );
13759
+ reconcileEnabledPlugins(
13760
+ bootAccount?.accountDir,
13761
+ bootAccount?.config,
13762
+ bootEntitlement?.purchasedPlugins ?? void 0
13763
+ );
13703
13764
  (async () => {
13704
13765
  if (!bootAccount) return;
13705
13766
  try {
@@ -13749,25 +13810,8 @@ if (bootEntitlement?.purchasedPlugins?.length) {
13749
13810
  const enabledSet = new Set(bootEnabled);
13750
13811
  for (const purchased of bootEntitlement.purchasedPlugins) {
13751
13812
  const bundlePath = resolveBoot(PLATFORM_ROOT, "..", "premium-plugins", purchased, "BUNDLE.md");
13752
- if (!existsSyncBoot(bundlePath)) continue;
13753
- try {
13754
- const raw = readFileSyncBoot(bundlePath, "utf-8");
13755
- const fm = raw.match(/^---\n([\s\S]*?)\n---/);
13756
- if (!fm) continue;
13757
- let inPlugins = false;
13758
- for (const line of fm[1].split("\n")) {
13759
- if (/^plugins:/.test(line)) {
13760
- inPlugins = true;
13761
- continue;
13762
- }
13763
- if (inPlugins) {
13764
- const m = line.match(/^\s+- (.+)/);
13765
- if (!m) break;
13766
- const sub = m[1].trim();
13767
- if (!enabledSet.has(sub)) bootEnabledNotDelivered.push(sub);
13768
- }
13769
- }
13770
- } catch {
13813
+ for (const sub of readBundleSubPlugins(bundlePath)) {
13814
+ if (!enabledSet.has(sub)) bootEnabledNotDelivered.push(sub);
13771
13815
  }
13772
13816
  }
13773
13817
  }
@@ -13780,7 +13824,7 @@ if (bootAccountConfig?.whatsapp) {
13780
13824
  }
13781
13825
  init({
13782
13826
  configDir: configDirForWhatsApp,
13783
- platformRoot: resolve21(process.env.MAXY_PLATFORM_ROOT ?? join11(__dirname, "..")),
13827
+ platformRoot: resolve21(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
13784
13828
  accountConfig: bootAccountConfig,
13785
13829
  onMessage: async (msg) => {
13786
13830
  try {