@rubytech/create-realagent-code 0.1.252 → 0.1.254

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +4 -13
  3. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +1 -2
  4. package/payload/platform/plugins/docs/references/deployment.md +0 -1
  5. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  6. package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
  7. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  9. package/payload/platform/services/claude-session-manager/dist/http-server.js +14 -0
  10. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  11. package/payload/platform/services/claude-session-manager/dist/index.js +10 -0
  12. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  13. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +40 -0
  14. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -0
  15. package/payload/platform/services/claude-session-manager/dist/pty-census.js +125 -0
  16. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -0
  17. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +1 -0
  18. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  19. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +8 -1
  20. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  21. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  22. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +0 -11
  23. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  24. package/payload/server/server.js +498 -322
@@ -4514,10 +4514,10 @@ var require_browser = __commonJS({
4514
4514
  text = canvas;
4515
4515
  canvas = void 0;
4516
4516
  }
4517
- return new Promise(function(resolve26, reject) {
4517
+ return new Promise(function(resolve27, reject) {
4518
4518
  try {
4519
4519
  const data = QRCode2.create(text, opts);
4520
- resolve26(renderFunc(data, canvas, opts));
4520
+ resolve27(renderFunc(data, canvas, opts));
4521
4521
  } catch (e) {
4522
4522
  reject(e);
4523
4523
  }
@@ -4599,11 +4599,11 @@ var require_server = __commonJS({
4599
4599
  }
4600
4600
  function render(renderFunc, text, params) {
4601
4601
  if (!params.cb) {
4602
- return new Promise(function(resolve26, reject) {
4602
+ return new Promise(function(resolve27, reject) {
4603
4603
  try {
4604
4604
  const data = QRCode2.create(text, params.opts);
4605
4605
  return renderFunc(data, params.opts, function(err, data2) {
4606
- return err ? reject(err) : resolve26(data2);
4606
+ return err ? reject(err) : resolve27(data2);
4607
4607
  });
4608
4608
  } catch (e) {
4609
4609
  reject(e);
@@ -5435,7 +5435,7 @@ var serveStatic = (options = { root: "" }) => {
5435
5435
 
5436
5436
  // server/index.ts
5437
5437
  import { readFileSync as readFileSync22, existsSync as existsSync23, watchFile } from "fs";
5438
- import { resolve as resolve25, join as join17, basename as basename6 } from "path";
5438
+ import { resolve as resolve26, join as join17, basename as basename6 } from "path";
5439
5439
  import { homedir as homedir2 } from "os";
5440
5440
  import { monitorEventLoopDelay } from "perf_hooks";
5441
5441
 
@@ -5958,7 +5958,7 @@ var credsSaveQueue = Promise.resolve();
5958
5958
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
5959
5959
  console.error(`${TAG2} draining credential save queue\u2026`);
5960
5960
  const timer2 = new Promise(
5961
- (resolve26) => setTimeout(() => resolve26("timeout"), timeoutMs)
5961
+ (resolve27) => setTimeout(() => resolve27("timeout"), timeoutMs)
5962
5962
  );
5963
5963
  const result = await Promise.race([
5964
5964
  credsSaveQueue.then(() => "drained"),
@@ -6086,11 +6086,11 @@ async function createWaSocket(opts) {
6086
6086
  return sock;
6087
6087
  }
6088
6088
  async function waitForConnection(sock) {
6089
- return new Promise((resolve26, reject) => {
6089
+ return new Promise((resolve27, reject) => {
6090
6090
  const handler = (update) => {
6091
6091
  if (update.connection === "open") {
6092
6092
  sock.ev.off("connection.update", handler);
6093
- resolve26();
6093
+ resolve27();
6094
6094
  }
6095
6095
  if (update.connection === "close") {
6096
6096
  sock.ev.off("connection.update", handler);
@@ -6204,14 +6204,14 @@ ${inspected}`;
6204
6204
  return inspect2(err, INSPECT_OPTS2);
6205
6205
  }
6206
6206
  function withTimeout(label, promise, timeoutMs) {
6207
- return new Promise((resolve26, reject) => {
6207
+ return new Promise((resolve27, reject) => {
6208
6208
  const timer2 = setTimeout(() => {
6209
6209
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
6210
6210
  }, timeoutMs);
6211
6211
  promise.then(
6212
6212
  (value) => {
6213
6213
  clearTimeout(timer2);
6214
- resolve26(value);
6214
+ resolve27(value);
6215
6215
  },
6216
6216
  (err) => {
6217
6217
  clearTimeout(timer2);
@@ -6753,8 +6753,8 @@ async function persistWhatsAppMessage(input) {
6753
6753
  const { givenName, familyName } = splitName(input.pushName);
6754
6754
  const prev = sessionWriteLocks.get(input.cacheKey);
6755
6755
  let release;
6756
- const mine = new Promise((resolve26) => {
6757
- release = resolve26;
6756
+ const mine = new Promise((resolve27) => {
6757
+ release = resolve27;
6758
6758
  });
6759
6759
  const chained = (prev ?? Promise.resolve()).then(() => mine);
6760
6760
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -7790,11 +7790,11 @@ async function connectWithReconnect(conn) {
7790
7790
  console.error(
7791
7791
  `${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
7792
7792
  );
7793
- await new Promise((resolve26) => {
7794
- const timer2 = setTimeout(resolve26, delay);
7793
+ await new Promise((resolve27) => {
7794
+ const timer2 = setTimeout(resolve27, delay);
7795
7795
  conn.abortController.signal.addEventListener("abort", () => {
7796
7796
  clearTimeout(timer2);
7797
- resolve26();
7797
+ resolve27();
7798
7798
  }, { once: true });
7799
7799
  });
7800
7800
  }
@@ -7802,16 +7802,16 @@ async function connectWithReconnect(conn) {
7802
7802
  }
7803
7803
  }
7804
7804
  function waitForDisconnectEvent(conn) {
7805
- return new Promise((resolve26) => {
7805
+ return new Promise((resolve27) => {
7806
7806
  if (!conn.sock) {
7807
- resolve26();
7807
+ resolve27();
7808
7808
  return;
7809
7809
  }
7810
7810
  const sock = conn.sock;
7811
7811
  const handler = (update) => {
7812
7812
  if (update.connection === "close") {
7813
7813
  sock.ev.off("connection.update", handler);
7814
- resolve26();
7814
+ resolve27();
7815
7815
  }
7816
7816
  };
7817
7817
  sock.ev.on("connection.update", handler);
@@ -8078,8 +8078,8 @@ async function handleInboundMessage(conn, msg) {
8078
8078
  const conversationKey = isGroup ? remoteJid : senderPhone;
8079
8079
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
8080
8080
  let resolvePending;
8081
- const sttPending = new Promise((resolve26) => {
8082
- resolvePending = resolve26;
8081
+ const sttPending = new Promise((resolve27) => {
8082
+ resolvePending = resolve27;
8083
8083
  });
8084
8084
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
8085
8085
  try {
@@ -8488,20 +8488,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
8488
8488
 
8489
8489
  // server/routes/health.ts
8490
8490
  function checkPort(port2, timeoutMs = 500) {
8491
- return new Promise((resolve26) => {
8491
+ return new Promise((resolve27) => {
8492
8492
  const socket = createConnection2(port2, "127.0.0.1");
8493
8493
  socket.setTimeout(timeoutMs);
8494
8494
  socket.once("connect", () => {
8495
8495
  socket.destroy();
8496
- resolve26(true);
8496
+ resolve27(true);
8497
8497
  });
8498
8498
  socket.once("error", () => {
8499
8499
  socket.destroy();
8500
- resolve26(false);
8500
+ resolve27(false);
8501
8501
  });
8502
8502
  socket.once("timeout", () => {
8503
8503
  socket.destroy();
8504
- resolve26(false);
8504
+ resolve27(false);
8505
8505
  });
8506
8506
  });
8507
8507
  }
@@ -8773,7 +8773,7 @@ async function transcribeVoiceNote(file, source) {
8773
8773
  }
8774
8774
 
8775
8775
  // app/lib/channel-pty-bridge/bridge.ts
8776
- import { resolve as resolve4 } from "path";
8776
+ import { resolve as resolve5 } from "path";
8777
8777
 
8778
8778
  // app/lib/channel-pty-bridge/manager-client.ts
8779
8779
  function managerBase() {
@@ -8857,8 +8857,9 @@ async function managerDelete(sessionId) {
8857
8857
  await fetch(`${managerBase()}/${sessionId}`, { method: "DELETE" }).catch(() => {
8858
8858
  });
8859
8859
  }
8860
- function managerLogFollowUrl(sessionId) {
8861
- return `${managerBase()}/${sessionId}/log?follow=1`;
8860
+ function managerLogFollowUrl(sessionId, opts) {
8861
+ const base = `${managerBase()}/${sessionId}/log?follow=1`;
8862
+ return opts?.boundary ? `${base}&boundary=1` : base;
8862
8863
  }
8863
8864
 
8864
8865
  // app/lib/channel-pty-bridge/admin-session-id.ts
@@ -9044,9 +9045,10 @@ function startFollower(opts) {
9044
9045
  let res;
9045
9046
  let attempt = 0;
9046
9047
  for (; ; ) {
9047
- res = await fetch(managerLogFollowUrl(entry.sessionId), {
9048
- signal: abort.signal
9049
- });
9048
+ res = await fetch(
9049
+ managerLogFollowUrl(entry.sessionId, { boundary: opts.suppressResumeReplay === true }),
9050
+ { signal: abort.signal }
9051
+ );
9050
9052
  console.error(`${tag} follower-connect sessionId=${sid} status=${res.status}`);
9051
9053
  if (res.status === 202) {
9052
9054
  attempt += 1;
@@ -9073,6 +9075,11 @@ function startFollower(opts) {
9073
9075
  const reader = res.body.getReader();
9074
9076
  const decoder = new TextDecoder("utf8");
9075
9077
  let buffered = "";
9078
+ const fileDelivery = opts.fileDelivery ?? null;
9079
+ let firedFileTools = [];
9080
+ let suppressing = opts.suppressResumeReplay === true;
9081
+ let discardedTurns = 0;
9082
+ let discardedFileTools = 0;
9076
9083
  while (!abort.signal.aborted) {
9077
9084
  const { value, done } = await reader.read();
9078
9085
  if (done) break;
@@ -9092,8 +9099,18 @@ function startFollower(opts) {
9092
9099
  );
9093
9100
  continue;
9094
9101
  }
9102
+ if (event.type === "__channel_resume_boundary__") {
9103
+ if (suppressing) {
9104
+ suppressing = false;
9105
+ console.error(
9106
+ `${tag} follower-resume-boundary sessionId=${sid} discarded-head-turns=${discardedTurns} discarded-head-filetools=${discardedFileTools}`
9107
+ );
9108
+ }
9109
+ continue;
9110
+ }
9095
9111
  if (event.type === "user") {
9096
9112
  entry.pendingTurnText = "";
9113
+ firedFileTools = [];
9097
9114
  continue;
9098
9115
  }
9099
9116
  if (event.type !== "assistant") continue;
@@ -9103,15 +9120,45 @@ function startFollower(opts) {
9103
9120
  for (const block of msg.content) {
9104
9121
  if (block?.type === "text" && typeof block.text === "string") {
9105
9122
  entry.pendingTurnText += block.text;
9123
+ } else if (fileDelivery && block?.type === "tool_use" && typeof block.name === "string" && fileDelivery.isFileDeliveryTool(block.name)) {
9124
+ if (suppressing) {
9125
+ discardedFileTools += 1;
9126
+ continue;
9127
+ }
9128
+ firedFileTools.push(block.name);
9129
+ try {
9130
+ await fileDelivery.onFileToolUse({ toolName: block.name, input: block.input });
9131
+ } catch (err) {
9132
+ console.error(
9133
+ `${tag} file-delivery-error sessionId=${sid} tool=${block.name} message=${err instanceof Error ? err.message : String(err)}`
9134
+ );
9135
+ }
9106
9136
  }
9107
9137
  }
9108
9138
  }
9109
9139
  if (msg.stop_reason === "end_turn") {
9140
+ if (suppressing) {
9141
+ entry.pendingTurnText = "";
9142
+ firedFileTools = [];
9143
+ discardedTurns += 1;
9144
+ continue;
9145
+ }
9110
9146
  const flush = entry.pendingTurnText;
9111
9147
  entry.pendingTurnText = "";
9112
9148
  if (flush.trim()) {
9113
9149
  await fanOut(entry.subscribers, flush, opts.onError, tag);
9114
9150
  }
9151
+ if (fileDelivery && firedFileTools.length > 0) {
9152
+ const fired = firedFileTools;
9153
+ firedFileTools = [];
9154
+ try {
9155
+ fileDelivery.onTurnEnd(fired);
9156
+ } catch (err) {
9157
+ console.error(
9158
+ `${tag} file-delivery-error sessionId=${sid} phase=turn-end message=${err instanceof Error ? err.message : String(err)}`
9159
+ );
9160
+ }
9161
+ }
9115
9162
  }
9116
9163
  }
9117
9164
  }
@@ -9138,10 +9185,164 @@ async function fanOut(subscribers, text, onError, tag) {
9138
9185
  );
9139
9186
  }
9140
9187
 
9188
+ // app/lib/whatsapp/outbound/send-document.ts
9189
+ import { realpathSync as realpathSync2 } from "fs";
9190
+ import { readFile, stat as stat2 } from "fs/promises";
9191
+ import { resolve as resolve4, basename } from "path";
9192
+ var TAG15 = "[whatsapp:outbound]";
9193
+ var WHATSAPP_DOCUMENT_MAX_BYTES = 100 * 1024 * 1024;
9194
+ var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
9195
+ function normalizeJid(to) {
9196
+ return to.includes("@") ? to : toWhatsappJid(to);
9197
+ }
9198
+ function documentOutboundAt(to) {
9199
+ return lastDocumentOutboundAt.get(normalizeJid(to));
9200
+ }
9201
+ async function sendWhatsAppDocument(input) {
9202
+ const { to, filePath, caption, accountId, maxyAccountId, platformRoot: platformRoot2 } = input;
9203
+ if (!to || !filePath) {
9204
+ return { ok: false, status: 400, error: "Missing required fields: to, filePath" };
9205
+ }
9206
+ if (!maxyAccountId || !platformRoot2) {
9207
+ return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
9208
+ }
9209
+ const accountDir = resolve4(platformRoot2, "..", "data/accounts", maxyAccountId);
9210
+ let resolvedPath;
9211
+ try {
9212
+ resolvedPath = realpathSync2(filePath);
9213
+ const accountResolved = realpathSync2(accountDir);
9214
+ if (!resolvedPath.startsWith(accountResolved + "/")) {
9215
+ const sanitised = filePath.replace(accountDir, "<account>/");
9216
+ console.error(`${TAG15} document REJECTED path=${sanitised} reason=outside_account_directory`);
9217
+ return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
9218
+ }
9219
+ } catch (err) {
9220
+ const code = err.code;
9221
+ if (code === "ENOENT") {
9222
+ console.error(`${TAG15} document ENOENT path=${filePath}`);
9223
+ return { ok: false, status: 404, error: `File not found: ${filePath}` };
9224
+ }
9225
+ console.error(`${TAG15} document path error: ${String(err)}`);
9226
+ return { ok: false, status: 500, error: String(err) };
9227
+ }
9228
+ const fileStat = await stat2(resolvedPath);
9229
+ if (fileStat.size > WHATSAPP_DOCUMENT_MAX_BYTES) {
9230
+ return {
9231
+ ok: false,
9232
+ status: 400,
9233
+ error: `File exceeds 100 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
9234
+ };
9235
+ }
9236
+ const filename = basename(resolvedPath);
9237
+ const jid = normalizeJid(to);
9238
+ const sock = getSocket(accountId);
9239
+ if (!sock) {
9240
+ console.error(`${TAG15} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=false reason=not-connected`);
9241
+ return { ok: false, status: 503, error: `WhatsApp account "${accountId}" is not connected` };
9242
+ }
9243
+ const buffer = Buffer.from(await readFile(resolvedPath));
9244
+ const mimetype = detectMimeType(resolvedPath);
9245
+ const result = await sendMediaMessage(
9246
+ sock,
9247
+ to,
9248
+ { type: "document", buffer, mimetype, filename, caption },
9249
+ { accountId }
9250
+ );
9251
+ console.error(
9252
+ `${TAG15} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
9253
+ );
9254
+ if (result.success) {
9255
+ lastDocumentOutboundAt.set(jid, Date.now());
9256
+ return { ok: true, messageId: result.messageId };
9257
+ }
9258
+ return { ok: false, status: 500, error: result.error ?? "send failed" };
9259
+ }
9260
+
9261
+ // app/lib/whatsapp/inbound/file-delivery-bridge.ts
9262
+ var TAG16 = "[whatsapp-adaptor]";
9263
+ var SEND_USER_FILE = "SendUserFile";
9264
+ var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
9265
+ function platformRoot() {
9266
+ return process.env.MAXY_PLATFORM_ROOT || "";
9267
+ }
9268
+ function makeWhatsAppFileDelivery(entry) {
9269
+ let turnStartedAt = null;
9270
+ let failedFiles = [];
9271
+ let sendUserFileAttempts = 0;
9272
+ return {
9273
+ isFileDeliveryTool(toolName) {
9274
+ return toolName === SEND_USER_FILE || toolName === WHATSAPP_SEND_DOCUMENT;
9275
+ },
9276
+ async onFileToolUse(use) {
9277
+ if (turnStartedAt === null) turnStartedAt = Date.now();
9278
+ if (use.toolName !== SEND_USER_FILE) return;
9279
+ const input = use.input ?? {};
9280
+ const files = Array.isArray(input.files) ? input.files.filter((f) => typeof f === "string") : [];
9281
+ const caption = typeof input.caption === "string" ? input.caption : void 0;
9282
+ if (files.length === 0) return;
9283
+ let maxyAccountId;
9284
+ try {
9285
+ maxyAccountId = resolvePlatformAccountId();
9286
+ } catch (err) {
9287
+ console.error(
9288
+ `${TAG16} file-delivery reject reason=account-unresolved sender=${entry.senderId} message=${err instanceof Error ? err.message : String(err)}`
9289
+ );
9290
+ return;
9291
+ }
9292
+ for (let i = 0; i < files.length; i++) {
9293
+ sendUserFileAttempts++;
9294
+ const result = await sendWhatsAppDocument({
9295
+ to: entry.senderId,
9296
+ filePath: files[i],
9297
+ caption: i === 0 ? caption : void 0,
9298
+ accountId: entry.accountId,
9299
+ maxyAccountId,
9300
+ platformRoot: platformRoot()
9301
+ });
9302
+ if (!result.ok) {
9303
+ failedFiles.push(files[i]);
9304
+ console.error(
9305
+ `${TAG16} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
9306
+ );
9307
+ }
9308
+ }
9309
+ },
9310
+ onTurnEnd(firedTools) {
9311
+ const startedAt = turnStartedAt ?? 0;
9312
+ const failed = failedFiles;
9313
+ const attempts = sendUserFileAttempts;
9314
+ turnStartedAt = null;
9315
+ failedFiles = [];
9316
+ sendUserFileAttempts = 0;
9317
+ const sid = entry.sessionId.slice(0, 8);
9318
+ for (const file of failed) {
9319
+ console.error(
9320
+ `${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE} file=${file}`
9321
+ );
9322
+ }
9323
+ const okAt = documentOutboundAt(entry.senderId);
9324
+ const documentWentOut = okAt !== void 0 && okAt >= startedAt;
9325
+ if (firedTools.includes(WHATSAPP_SEND_DOCUMENT) && !documentWentOut) {
9326
+ console.error(
9327
+ `${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}`
9328
+ );
9329
+ }
9330
+ if (firedTools.includes(SEND_USER_FILE) && attempts === 0 && !documentWentOut) {
9331
+ console.error(
9332
+ `${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE}`
9333
+ );
9334
+ }
9335
+ }
9336
+ };
9337
+ }
9338
+
9141
9339
  // app/lib/channel-pty-bridge/bridge.ts
9142
9340
  function tagFor(channel) {
9143
9341
  return `[${channel}-adaptor]`;
9144
9342
  }
9343
+ function fileDeliveryFor(entry) {
9344
+ return entry.channel === "whatsapp" ? makeWhatsAppFileDelivery(entry) : null;
9345
+ }
9145
9346
  function publicIdleMs() {
9146
9347
  return Number(process.env.CHANNEL_PTY_IDLE_MS ?? String(5 * 6e4));
9147
9348
  }
@@ -9163,6 +9364,13 @@ async function ensureEntry(input) {
9163
9364
  existing.followerAbort = startFollower({
9164
9365
  entry: existing,
9165
9366
  tag,
9367
+ fileDelivery: fileDeliveryFor(existing),
9368
+ // Task 631 — every channel attach resumes an existing session after a
9369
+ // restart (the in-memory index is process memory and empty post-restart).
9370
+ // Suppress replay of the pre-attach JSONL so the first inbound is answered
9371
+ // by a fresh turn, not a historical end_turn, and historical SendUserFile
9372
+ // is not re-sent.
9373
+ suppressResumeReplay: true,
9166
9374
  onClose: () => {
9167
9375
  existing.followerRunning = false;
9168
9376
  }
@@ -9182,7 +9390,7 @@ async function ensureEntry(input) {
9182
9390
  });
9183
9391
  } else {
9184
9392
  console.error(`${tag} route role=${input.role} target=public-spawn senderId=${input.senderId}`);
9185
- const attachmentDir = resolve4(ATTACHMENTS_ROOT, "public", input.senderId);
9393
+ const attachmentDir = resolve5(ATTACHMENTS_ROOT, "public", input.senderId);
9186
9394
  spawned = await managerSpawn({
9187
9395
  senderId: input.senderId,
9188
9396
  role: input.role,
@@ -9223,6 +9431,12 @@ async function ensureEntry(input) {
9223
9431
  entry.followerAbort = startFollower({
9224
9432
  entry,
9225
9433
  tag,
9434
+ fileDelivery: fileDeliveryFor(entry),
9435
+ // Task 631 — see the existing-entry branch above. A fresh spawn has an
9436
+ // empty JSONL, so the manager emits the boundary sentinel right after an
9437
+ // empty head and the follower arms immediately; suppression is a no-op for
9438
+ // the cold-spawn first turn and correct for any resume.
9439
+ suppressResumeReplay: true,
9226
9440
  onClose: () => {
9227
9441
  entry.followerRunning = false;
9228
9442
  }
@@ -9308,12 +9522,12 @@ async function dispatchOnce(input) {
9308
9522
  });
9309
9523
  if (!entry) return { error: "spawn-failed" };
9310
9524
  entry.lastInboundAt = Date.now();
9311
- let resolve26;
9525
+ let resolve27;
9312
9526
  const turnPromise = new Promise((r) => {
9313
- resolve26 = r;
9527
+ resolve27 = r;
9314
9528
  });
9315
9529
  const listener = (text) => {
9316
- resolve26(text);
9530
+ resolve27(text);
9317
9531
  };
9318
9532
  entry.subscribers.add(listener);
9319
9533
  const writeOk = await writeInput(entry, input.text);
@@ -9672,19 +9886,18 @@ app2.post("/", async (c) => {
9672
9886
  var chat_default = app2;
9673
9887
 
9674
9888
  // server/routes/whatsapp.ts
9675
- import { join as join5, resolve as resolve6, basename } from "path";
9676
- import { readFile, stat as stat2 } from "fs/promises";
9677
- import { realpathSync as realpathSync2, readdirSync as readdirSync2, readFileSync as readFileSync6, existsSync as existsSync4 } from "fs";
9889
+ import { join as join5, resolve as resolve7 } from "path";
9890
+ import { readdirSync as readdirSync2, readFileSync as readFileSync6, existsSync as existsSync4 } from "fs";
9678
9891
 
9679
9892
  // app/lib/whatsapp/login.ts
9680
9893
  var import_qrcode = __toESM(require_lib(), 1);
9681
9894
  import { randomUUID as randomUUID6 } from "crypto";
9682
- var TAG15 = "[whatsapp:login]";
9895
+ var TAG17 = "[whatsapp:login]";
9683
9896
  async function renderQrTerminal(qr) {
9684
9897
  try {
9685
9898
  return await import_qrcode.default.toString(qr, { type: "utf8" });
9686
9899
  } catch (err) {
9687
- console.error(`${TAG15} terminal QR render failed: ${String(err)}`);
9900
+ console.error(`${TAG17} terminal QR render failed: ${String(err)}`);
9688
9901
  return void 0;
9689
9902
  }
9690
9903
  }
@@ -9694,7 +9907,7 @@ function closeSocket(sock) {
9694
9907
  try {
9695
9908
  sock.ws?.close?.();
9696
9909
  } catch (err) {
9697
- console.warn(`${TAG15} socket close error during cleanup: ${String(err)}`);
9910
+ console.warn(`${TAG17} socket close error during cleanup: ${String(err)}`);
9698
9911
  }
9699
9912
  }
9700
9913
  function resetActiveLogin(accountId) {
@@ -9717,7 +9930,7 @@ async function loginConnectionLoop(accountId, login) {
9717
9930
  const current = activeLogins.get(accountId);
9718
9931
  if (current?.id === login.id) {
9719
9932
  current.connected = true;
9720
- console.error(`${TAG15} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
9933
+ console.error(`${TAG17} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
9721
9934
  }
9722
9935
  return;
9723
9936
  } catch (err) {
@@ -9727,7 +9940,7 @@ async function loginConnectionLoop(accountId, login) {
9727
9940
  if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
9728
9941
  if (attempt >= LOGIN_MAX_RECONNECTS) {
9729
9942
  console.error(
9730
- `${TAG15} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
9943
+ `${TAG17} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
9731
9944
  );
9732
9945
  current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
9733
9946
  } else {
@@ -9739,7 +9952,7 @@ async function loginConnectionLoop(accountId, login) {
9739
9952
  attempt++;
9740
9953
  const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
9741
9954
  console.error(
9742
- `${TAG15} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
9955
+ `${TAG17} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
9743
9956
  );
9744
9957
  closeSocket(current.sock);
9745
9958
  await new Promise((r) => setTimeout(r, delay));
@@ -9750,7 +9963,7 @@ async function loginConnectionLoop(accountId, login) {
9750
9963
  current.sock = newSock;
9751
9964
  } catch (sockErr) {
9752
9965
  console.error(
9753
- `${TAG15} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
9966
+ `${TAG17} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
9754
9967
  );
9755
9968
  current.error = `Reconnection failed: ${String(sockErr)}`;
9756
9969
  return;
@@ -9764,7 +9977,7 @@ async function startLogin(opts) {
9764
9977
  const hasAuth = await authExists(authDir);
9765
9978
  const selfId = readSelfId(authDir);
9766
9979
  console.error(
9767
- `${TAG15} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasQr=${!!existing0.qr}}` : " activeLogin=none")
9980
+ `${TAG17} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasQr=${!!existing0.qr}}` : " activeLogin=none")
9768
9981
  );
9769
9982
  if (hasAuth && !force) {
9770
9983
  const who = selfId.e164 ?? selfId.jid ?? "unknown";
@@ -9776,7 +9989,7 @@ async function startLogin(opts) {
9776
9989
  await clearAuth(authDir);
9777
9990
  const existing = activeLogins.get(accountId);
9778
9991
  if (existing && isLoginFresh(existing) && existing.qrDataUrl && !force) {
9779
- console.error(`${TAG15} startLogin account=${accountId} guard: returning existing QR (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
9992
+ console.error(`${TAG17} startLogin account=${accountId} guard: returning existing QR (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
9780
9993
  return {
9781
9994
  qrDataUrl: existing.qrDataUrl,
9782
9995
  qrRaw: existing.qr,
@@ -9785,13 +9998,13 @@ async function startLogin(opts) {
9785
9998
  };
9786
9999
  }
9787
10000
  if (existing) {
9788
- console.error(`${TAG15} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
10001
+ console.error(`${TAG17} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
9789
10002
  }
9790
10003
  resetActiveLogin(accountId);
9791
10004
  let resolveQr = null;
9792
10005
  let rejectQr = null;
9793
- const qrPromise = new Promise((resolve26, reject) => {
9794
- resolveQr = resolve26;
10006
+ const qrPromise = new Promise((resolve27, reject) => {
10007
+ resolveQr = resolve27;
9795
10008
  rejectQr = reject;
9796
10009
  });
9797
10010
  const qrTimer = setTimeout(
@@ -9807,14 +10020,14 @@ async function startLogin(opts) {
9807
10020
  onQr: (qr2) => {
9808
10021
  loginQrCount++;
9809
10022
  if (pendingQr) {
9810
- console.error(`${TAG15} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
10023
+ console.error(`${TAG17} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
9811
10024
  return;
9812
10025
  }
9813
10026
  pendingQr = qr2;
9814
10027
  const current = activeLogins.get(accountId);
9815
10028
  if (current && !current.qr) current.qr = qr2;
9816
10029
  clearTimeout(qrTimer);
9817
- console.error(`${TAG15} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
10030
+ console.error(`${TAG17} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
9818
10031
  resolveQr?.(qr2);
9819
10032
  }
9820
10033
  });
@@ -9834,7 +10047,7 @@ async function startLogin(opts) {
9834
10047
  activeLogins.set(accountId, login);
9835
10048
  if (pendingQr && !login.qr) login.qr = pendingQr;
9836
10049
  loginConnectionLoop(accountId, login).catch((err) => {
9837
- console.error(`${TAG15} loginConnectionLoop unexpected error: ${String(err)}`);
10050
+ console.error(`${TAG17} loginConnectionLoop unexpected error: ${String(err)}`);
9838
10051
  const current = activeLogins.get(accountId);
9839
10052
  if (current?.id === login.id) {
9840
10053
  current.error = `Unexpected login error: ${String(err)}`;
@@ -9860,7 +10073,7 @@ async function waitForLogin(opts) {
9860
10073
  const { accountId, timeoutMs = 6e4 } = opts;
9861
10074
  const login = activeLogins.get(accountId);
9862
10075
  console.error(
9863
- `${TAG15} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasQr=${!!login.qr}}` : " login=none")
10076
+ `${TAG17} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasQr=${!!login.qr}}` : " login=none")
9864
10077
  );
9865
10078
  if (!login) {
9866
10079
  return { connected: false, message: "No active WhatsApp login in progress." };
@@ -9873,7 +10086,7 @@ async function waitForLogin(opts) {
9873
10086
  while (Date.now() < deadline) {
9874
10087
  if (login.connected) {
9875
10088
  const selfId = readSelfId(login.authDir);
9876
- console.error(`${TAG15} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
10089
+ console.error(`${TAG17} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
9877
10090
  const sock = login.sock;
9878
10091
  const authDir = login.authDir;
9879
10092
  activeLogins.delete(accountId);
@@ -9893,17 +10106,17 @@ async function waitForLogin(opts) {
9893
10106
  await new Promise((r) => setTimeout(r, 1e3));
9894
10107
  }
9895
10108
  const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
9896
- console.error(`${TAG15} waitForLogin timeout account=${accountId} elapsed=${elapsed}s \u2014 cleaning up active login`);
10109
+ console.error(`${TAG17} waitForLogin timeout account=${accountId} elapsed=${elapsed}s \u2014 cleaning up active login`);
9897
10110
  resetActiveLogin(accountId);
9898
10111
  return { connected: false, message: "Login timed out. Try generating a new QR." };
9899
10112
  }
9900
10113
 
9901
10114
  // app/lib/whatsapp/config-persist.ts
9902
10115
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
9903
- import { resolve as resolve5, join as join4 } from "path";
9904
- var TAG16 = "[whatsapp:config]";
10116
+ import { resolve as resolve6, join as join4 } from "path";
10117
+ var TAG18 = "[whatsapp:config]";
9905
10118
  function configPath(accountDir) {
9906
- return resolve5(accountDir, "account.json");
10119
+ return resolve6(accountDir, "account.json");
9907
10120
  }
9908
10121
  function readConfig(accountDir) {
9909
10122
  const path2 = configPath(accountDir);
@@ -9918,9 +10131,9 @@ function reloadManagerConfig(accountDir) {
9918
10131
  try {
9919
10132
  const config = readConfig(accountDir);
9920
10133
  reloadConfig(config);
9921
- console.error(`${TAG16} reloaded manager config`);
10134
+ console.error(`${TAG18} reloaded manager config`);
9922
10135
  } catch (err) {
9923
- console.error(`${TAG16} manager config reload failed: ${String(err)}`);
10136
+ console.error(`${TAG18} manager config reload failed: ${String(err)}`);
9924
10137
  }
9925
10138
  }
9926
10139
  var E164_PATTERN = /^\+\d{7,15}$/;
@@ -9946,25 +10159,25 @@ function persistAfterPairing(accountDir, accountId, selfPhone) {
9946
10159
  const adminPhones = wa.adminPhones;
9947
10160
  if (!adminPhones.includes(normalized)) {
9948
10161
  adminPhones.push(normalized);
9949
- console.error(`${TAG16} added selfPhone=${normalized} to adminPhones`);
10162
+ console.error(`${TAG18} added selfPhone=${normalized} to adminPhones`);
9950
10163
  }
9951
10164
  } else {
9952
- console.error(`${TAG16} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
10165
+ console.error(`${TAG18} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
9953
10166
  }
9954
10167
  const parsed = WhatsAppConfigSchema.safeParse(wa);
9955
10168
  if (!parsed.success) {
9956
10169
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
9957
- console.error(`${TAG16} validation failed after pairing: ${msg}`);
10170
+ console.error(`${TAG18} validation failed after pairing: ${msg}`);
9958
10171
  return { ok: false, error: `Validation failed: ${msg}` };
9959
10172
  }
9960
10173
  config.whatsapp = parsed.data;
9961
10174
  writeConfig(accountDir, config);
9962
- console.error(`${TAG16} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
10175
+ console.error(`${TAG18} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
9963
10176
  reloadManagerConfig(accountDir);
9964
10177
  return { ok: true };
9965
10178
  } catch (err) {
9966
10179
  const msg = err instanceof Error ? err.message : String(err);
9967
- console.error(`${TAG16} persist failed account=${accountId}: ${msg}`);
10180
+ console.error(`${TAG18} persist failed account=${accountId}: ${msg}`);
9968
10181
  return { ok: false, error: msg };
9969
10182
  }
9970
10183
  }
@@ -9994,12 +10207,12 @@ function addAdminPhone(accountDir, phone) {
9994
10207
  }
9995
10208
  config.whatsapp = parsed.data;
9996
10209
  writeConfig(accountDir, config);
9997
- console.error(`${TAG16} added admin phone=${normalized}`);
10210
+ console.error(`${TAG18} added admin phone=${normalized}`);
9998
10211
  reloadManagerConfig(accountDir);
9999
10212
  return { ok: true, message: `Added ${normalized} as admin phone. Messages from this number will route to the admin agent.` };
10000
10213
  } catch (err) {
10001
10214
  const msg = err instanceof Error ? err.message : String(err);
10002
- console.error(`${TAG16} addAdminPhone failed: ${msg}`);
10215
+ console.error(`${TAG18} addAdminPhone failed: ${msg}`);
10003
10216
  return { ok: false, error: msg };
10004
10217
  }
10005
10218
  }
@@ -10027,12 +10240,12 @@ function removeAdminPhone(accountDir, phone) {
10027
10240
  }
10028
10241
  config.whatsapp = parsed.data;
10029
10242
  writeConfig(accountDir, config);
10030
- console.error(`${TAG16} removed admin phone=${normalized}`);
10243
+ console.error(`${TAG18} removed admin phone=${normalized}`);
10031
10244
  reloadManagerConfig(accountDir);
10032
10245
  return { ok: true, message: `Removed ${normalized} from admin phones. Messages from this number will now route to the public agent.` };
10033
10246
  } catch (err) {
10034
10247
  const msg = err instanceof Error ? err.message : String(err);
10035
- console.error(`${TAG16} removeAdminPhone failed: ${msg}`);
10248
+ console.error(`${TAG18} removeAdminPhone failed: ${msg}`);
10036
10249
  return { ok: false, error: msg };
10037
10250
  }
10038
10251
  }
@@ -10070,12 +10283,12 @@ function setPublicAgent(accountDir, slug) {
10070
10283
  }
10071
10284
  config.whatsapp = parsed.data;
10072
10285
  writeConfig(accountDir, config);
10073
- console.error(`${TAG16} publicAgent set to ${trimmed}`);
10286
+ console.error(`${TAG18} publicAgent set to ${trimmed}`);
10074
10287
  reloadManagerConfig(accountDir);
10075
10288
  return { ok: true, message: `Public agent set to "${trimmed}". WhatsApp messages from non-admin phones will be handled by this agent.` };
10076
10289
  } catch (err) {
10077
10290
  const msg = err instanceof Error ? err.message : String(err);
10078
- console.error(`${TAG16} setPublicAgent failed: ${msg}`);
10291
+ console.error(`${TAG18} setPublicAgent failed: ${msg}`);
10079
10292
  return { ok: false, error: msg };
10080
10293
  }
10081
10294
  }
@@ -10139,12 +10352,12 @@ function setGroupPublicAgent(accountDir, accountId, groupJid, slug) {
10139
10352
  }
10140
10353
  config.whatsapp = parsed.data;
10141
10354
  writeConfig(accountDir, config);
10142
- console.error(`${TAG16} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
10355
+ console.error(`${TAG18} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
10143
10356
  reloadManagerConfig(accountDir);
10144
10357
  return { ok: true, message: `Per-group public agent set to "${trimmedSlug}" for group ${trimmedGroup}.` };
10145
10358
  } catch (err) {
10146
10359
  const msg = err instanceof Error ? err.message : String(err);
10147
- console.error(`${TAG16} setGroupPublicAgent failed: ${msg}`);
10360
+ console.error(`${TAG18} setGroupPublicAgent failed: ${msg}`);
10148
10361
  return { ok: false, error: msg };
10149
10362
  }
10150
10363
  }
@@ -10171,12 +10384,12 @@ function unsetGroupPublicAgent(accountDir, accountId, groupJid) {
10171
10384
  }
10172
10385
  config.whatsapp = parsed.data;
10173
10386
  writeConfig(accountDir, config);
10174
- console.error(`${TAG16} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
10387
+ console.error(`${TAG18} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
10175
10388
  reloadManagerConfig(accountDir);
10176
10389
  return { ok: true, message: `Per-group public agent override removed for group ${trimmedGroup}.` };
10177
10390
  } catch (err) {
10178
10391
  const msg = err instanceof Error ? err.message : String(err);
10179
- console.error(`${TAG16} unsetGroupPublicAgent failed: ${msg}`);
10392
+ console.error(`${TAG18} unsetGroupPublicAgent failed: ${msg}`);
10180
10393
  return { ok: false, error: msg };
10181
10394
  }
10182
10395
  }
@@ -10197,17 +10410,17 @@ function updateConfig(accountDir, fields) {
10197
10410
  const parsed = WhatsAppConfigSchema.safeParse(wa);
10198
10411
  if (!parsed.success) {
10199
10412
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
10200
- console.error(`${TAG16} update validation failed: ${msg}`);
10413
+ console.error(`${TAG18} update validation failed: ${msg}`);
10201
10414
  return { ok: false, error: `Validation failed: ${msg}` };
10202
10415
  }
10203
10416
  config.whatsapp = parsed.data;
10204
10417
  writeConfig(accountDir, config);
10205
- console.error(`${TAG16} updated fields=[${fieldNames.join(",")}]`);
10418
+ console.error(`${TAG18} updated fields=[${fieldNames.join(",")}]`);
10206
10419
  reloadManagerConfig(accountDir);
10207
10420
  return { ok: true, message: `Updated WhatsApp config: ${fieldNames.join(", ")}.` };
10208
10421
  } catch (err) {
10209
10422
  const msg = err instanceof Error ? err.message : String(err);
10210
- console.error(`${TAG16} updateConfig failed: ${msg}`);
10423
+ console.error(`${TAG18} updateConfig failed: ${msg}`);
10211
10424
  return { ok: false, error: msg };
10212
10425
  }
10213
10426
  }
@@ -10333,17 +10546,17 @@ function serializeWhatsAppSchema() {
10333
10546
  }
10334
10547
 
10335
10548
  // server/routes/whatsapp.ts
10336
- var TAG17 = "[whatsapp:api]";
10549
+ var TAG19 = "[whatsapp:api]";
10337
10550
  var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT || "";
10338
10551
  var app3 = new Hono();
10339
10552
  app3.get("/status", (c) => {
10340
10553
  try {
10341
10554
  const status = getStatus();
10342
10555
  const summary = status.map((a) => `${a.accountId}:${a.connected ? "up" : "down"}`).join(", ");
10343
- console.error(`${TAG17} status accounts=${status.length} [${summary}]`);
10556
+ console.error(`${TAG19} status accounts=${status.length} [${summary}]`);
10344
10557
  return c.json({ accounts: status });
10345
10558
  } catch (err) {
10346
- console.error(`${TAG17} status error: ${String(err)}`);
10559
+ console.error(`${TAG19} status error: ${String(err)}`);
10347
10560
  return c.json({ error: String(err) }, 500);
10348
10561
  }
10349
10562
  });
@@ -10354,10 +10567,10 @@ app3.post("/login/start", async (c) => {
10354
10567
  const force = body.force ?? false;
10355
10568
  const authDir = join5(MAXY_DIR, "credentials", "whatsapp", accountId);
10356
10569
  const result = await startLogin({ accountId, authDir, force });
10357
- console.error(`${TAG17} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
10570
+ console.error(`${TAG19} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
10358
10571
  return c.json(result);
10359
10572
  } catch (err) {
10360
- console.error(`${TAG17} login/start error: ${String(err)}`);
10573
+ console.error(`${TAG19} login/start error: ${String(err)}`);
10361
10574
  return c.json({ error: String(err) }, 500);
10362
10575
  }
10363
10576
  });
@@ -10372,7 +10585,7 @@ app3.post("/login/wait", async (c) => {
10372
10585
  try {
10373
10586
  await registerLoginSocket(accountId, result.sock, result.authDir);
10374
10587
  } catch (regErr) {
10375
- console.error(`${TAG17} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
10588
+ console.error(`${TAG19} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
10376
10589
  }
10377
10590
  try {
10378
10591
  const account = resolveAccount();
@@ -10380,16 +10593,16 @@ app3.post("/login/wait", async (c) => {
10380
10593
  const persistResult = persistAfterPairing(account.accountDir, accountId, result.selfPhone ?? null);
10381
10594
  configPersisted = persistResult.ok;
10382
10595
  if (!persistResult.ok) {
10383
- console.error(`${TAG17} config persist failed account=${accountId}: ${persistResult.error}`);
10596
+ console.error(`${TAG19} config persist failed account=${accountId}: ${persistResult.error}`);
10384
10597
  }
10385
10598
  } else {
10386
- console.error(`${TAG17} config persist skipped \u2014 no account resolved`);
10599
+ console.error(`${TAG19} config persist skipped \u2014 no account resolved`);
10387
10600
  }
10388
10601
  } catch (persistErr) {
10389
- console.error(`${TAG17} config persist error account=${accountId}: ${String(persistErr)}`);
10602
+ console.error(`${TAG19} config persist error account=${accountId}: ${String(persistErr)}`);
10390
10603
  }
10391
10604
  }
10392
- console.error(`${TAG17} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
10605
+ console.error(`${TAG19} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
10393
10606
  return c.json({
10394
10607
  connected: result.connected,
10395
10608
  message: result.message,
@@ -10397,7 +10610,7 @@ app3.post("/login/wait", async (c) => {
10397
10610
  configPersisted
10398
10611
  });
10399
10612
  } catch (err) {
10400
- console.error(`${TAG17} login/wait error: ${String(err)}`);
10613
+ console.error(`${TAG19} login/wait error: ${String(err)}`);
10401
10614
  return c.json({ error: String(err) }, 500);
10402
10615
  }
10403
10616
  });
@@ -10408,7 +10621,7 @@ app3.post("/disconnect", async (c) => {
10408
10621
  await stopConnection(accountId);
10409
10622
  return c.json({ disconnected: true, accountId });
10410
10623
  } catch (err) {
10411
- console.error(`${TAG17} disconnect error: ${String(err)}`);
10624
+ console.error(`${TAG19} disconnect error: ${String(err)}`);
10412
10625
  return c.json({ error: String(err) }, 500);
10413
10626
  }
10414
10627
  });
@@ -10419,7 +10632,7 @@ app3.post("/reconnect", async (c) => {
10419
10632
  await startConnection(accountId);
10420
10633
  return c.json({ reconnecting: true, accountId });
10421
10634
  } catch (err) {
10422
- console.error(`${TAG17} reconnect error: ${String(err)}`);
10635
+ console.error(`${TAG19} reconnect error: ${String(err)}`);
10423
10636
  return c.json({ error: String(err) }, 500);
10424
10637
  }
10425
10638
  });
@@ -10438,7 +10651,7 @@ app3.post("/send", async (c) => {
10438
10651
  const result = await sendTextMessage(sock, to, text, { accountId });
10439
10652
  return c.json(result);
10440
10653
  } catch (err) {
10441
- console.error(`${TAG17} send error: ${String(err)}`);
10654
+ console.error(`${TAG19} send error: ${String(err)}`);
10442
10655
  return c.json({ error: String(err) }, 500);
10443
10656
  }
10444
10657
  });
@@ -10459,7 +10672,7 @@ app3.post("/config", async (c) => {
10459
10672
  return c.json({ ok: false, error: 'Missing required field "phone" (E.164 format, e.g. +441234567890).' }, 400);
10460
10673
  }
10461
10674
  const result = addAdminPhone(account.accountDir, phone);
10462
- console.error(`${TAG17} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
10675
+ console.error(`${TAG19} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
10463
10676
  return c.json(result, result.ok ? 200 : 400);
10464
10677
  }
10465
10678
  case "remove-admin-phone": {
@@ -10467,12 +10680,12 @@ app3.post("/config", async (c) => {
10467
10680
  return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
10468
10681
  }
10469
10682
  const result = removeAdminPhone(account.accountDir, phone);
10470
- console.error(`${TAG17} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
10683
+ console.error(`${TAG19} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
10471
10684
  return c.json(result, result.ok ? 200 : 400);
10472
10685
  }
10473
10686
  case "list-admin-phones": {
10474
10687
  const phones = readAdminPhones(account.accountDir);
10475
- console.error(`${TAG17} config action=list-admin-phones count=${phones.length}`);
10688
+ console.error(`${TAG19} config action=list-admin-phones count=${phones.length}`);
10476
10689
  return c.json({ ok: true, phones });
10477
10690
  }
10478
10691
  case "set-public-agent": {
@@ -10480,14 +10693,14 @@ app3.post("/config", async (c) => {
10480
10693
  return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
10481
10694
  }
10482
10695
  const result = setPublicAgent(account.accountDir, slug);
10483
- console.error(`${TAG17} config action=set-public-agent slug=${slug} ok=${result.ok}`);
10696
+ console.error(`${TAG19} config action=set-public-agent slug=${slug} ok=${result.ok}`);
10484
10697
  return c.json(result, result.ok ? 200 : 400);
10485
10698
  }
10486
10699
  case "get-public-agent": {
10487
10700
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10488
10701
  const targetGroup = typeof groupJid === "string" && groupJid.trim() ? groupJid.trim() : void 0;
10489
10702
  const resolved = resolvePublicAgent(account.accountDir, { accountId: targetAccount, groupJid: targetGroup });
10490
- console.error(`${TAG17} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
10703
+ console.error(`${TAG19} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
10491
10704
  return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
10492
10705
  }
10493
10706
  case "set-group-public-agent": {
@@ -10499,7 +10712,7 @@ app3.post("/config", async (c) => {
10499
10712
  }
10500
10713
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10501
10714
  const result = setGroupPublicAgent(account.accountDir, targetAccount, groupJid, slug);
10502
- console.error(`${TAG17} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
10715
+ console.error(`${TAG19} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
10503
10716
  return c.json(result, result.ok ? 200 : 400);
10504
10717
  }
10505
10718
  case "unset-group-public-agent": {
@@ -10508,43 +10721,43 @@ app3.post("/config", async (c) => {
10508
10721
  }
10509
10722
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10510
10723
  const result = unsetGroupPublicAgent(account.accountDir, targetAccount, groupJid);
10511
- console.error(`${TAG17} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
10724
+ console.error(`${TAG19} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
10512
10725
  return c.json(result, result.ok ? 200 : 400);
10513
10726
  }
10514
10727
  case "list-public-agents": {
10515
- const agentsDir = resolve6(account.accountDir, "agents");
10728
+ const agentsDir = resolve7(account.accountDir, "agents");
10516
10729
  const agents = [];
10517
10730
  if (existsSync4(agentsDir)) {
10518
10731
  try {
10519
10732
  const entries = readdirSync2(agentsDir, { withFileTypes: true });
10520
10733
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
10521
10734
  if (!entry.isDirectory() || entry.name === "admin") continue;
10522
- const configPath2 = resolve6(agentsDir, entry.name, "config.json");
10735
+ const configPath2 = resolve7(agentsDir, entry.name, "config.json");
10523
10736
  if (!existsSync4(configPath2)) continue;
10524
10737
  try {
10525
10738
  const config = JSON.parse(readFileSync6(configPath2, "utf-8"));
10526
10739
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
10527
10740
  } catch {
10528
- console.error(`${TAG17} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
10741
+ console.error(`${TAG19} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
10529
10742
  }
10530
10743
  }
10531
10744
  } catch (err) {
10532
- console.error(`${TAG17} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
10745
+ console.error(`${TAG19} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
10533
10746
  }
10534
10747
  }
10535
- console.error(`${TAG17} config action=list-public-agents count=${agents.length}`);
10748
+ console.error(`${TAG19} config action=list-public-agents count=${agents.length}`);
10536
10749
  return c.json({ ok: true, agents });
10537
10750
  }
10538
10751
  case "schema": {
10539
10752
  const text = serializeWhatsAppSchema();
10540
- console.error(`${TAG17} config action=schema`);
10753
+ console.error(`${TAG19} config action=schema`);
10541
10754
  return c.json({ ok: true, text });
10542
10755
  }
10543
10756
  case "list-groups": {
10544
10757
  const groupAccountId = accountId ?? "default";
10545
10758
  const sock = getSocket(groupAccountId);
10546
10759
  if (!sock) {
10547
- console.error(`${TAG17} config action=list-groups error="not connected" accountId=${groupAccountId}`);
10760
+ console.error(`${TAG19} config action=list-groups error="not connected" accountId=${groupAccountId}`);
10548
10761
  return c.json({ ok: false, error: `WhatsApp account "${groupAccountId}" is not connected. Connect first, then retry.` });
10549
10762
  }
10550
10763
  try {
@@ -10554,10 +10767,10 @@ app3.post("/config", async (c) => {
10554
10767
  name: g.subject ?? g.id,
10555
10768
  participantCount: Array.isArray(g.participants) ? g.participants.length : 0
10556
10769
  }));
10557
- console.error(`${TAG17} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
10770
+ console.error(`${TAG19} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
10558
10771
  return c.json({ ok: true, groups });
10559
10772
  } catch (err) {
10560
- console.error(`${TAG17} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
10773
+ console.error(`${TAG19} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
10561
10774
  return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
10562
10775
  }
10563
10776
  }
@@ -10567,12 +10780,12 @@ app3.post("/config", async (c) => {
10567
10780
  }
10568
10781
  const result = updateConfig(account.accountDir, fields);
10569
10782
  const fieldNames = Object.keys(fields);
10570
- console.error(`${TAG17} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
10783
+ console.error(`${TAG19} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
10571
10784
  return c.json(result, result.ok ? 200 : 400);
10572
10785
  }
10573
10786
  case "get-config": {
10574
10787
  const waConfig = getConfig(account.accountDir);
10575
- console.error(`${TAG17} config action=get-config`);
10788
+ console.error(`${TAG19} config action=get-config`);
10576
10789
  return c.json({ ok: true, config: waConfig });
10577
10790
  }
10578
10791
  default:
@@ -10582,7 +10795,7 @@ app3.post("/config", async (c) => {
10582
10795
  );
10583
10796
  }
10584
10797
  } catch (err) {
10585
- console.error(`${TAG17} config error: ${String(err)}`);
10798
+ console.error(`${TAG19} config error: ${String(err)}`);
10586
10799
  return c.json({ ok: false, error: String(err) }, 500);
10587
10800
  }
10588
10801
  });
@@ -10591,55 +10804,18 @@ app3.post("/send-document", async (c) => {
10591
10804
  const body = await c.req.json();
10592
10805
  const { to, filePath, caption, maxyAccountId } = body;
10593
10806
  const accountId = validateAccountId(body.accountId);
10594
- if (!to || !filePath) {
10595
- return c.json({ error: "Missing required fields: to, filePath" }, 400);
10596
- }
10597
- if (!maxyAccountId || !PLATFORM_ROOT4) {
10598
- return c.json({ error: "Cannot validate file path: missing account or platform context" }, 400);
10599
- }
10600
- const accountDir = resolve6(PLATFORM_ROOT4, "..", "data/accounts", maxyAccountId);
10601
- let resolvedPath;
10602
- try {
10603
- resolvedPath = realpathSync2(filePath);
10604
- const accountResolved = realpathSync2(accountDir);
10605
- if (!resolvedPath.startsWith(accountResolved + "/")) {
10606
- const sanitised = filePath.replace(accountDir, "<account>/");
10607
- console.error(`${TAG17} send-document REJECTED path=${sanitised} reason=outside_account_directory`);
10608
- return c.json({ error: "Access denied: file is outside the account directory" }, 403);
10609
- }
10610
- } catch (err) {
10611
- const code = err.code;
10612
- if (code === "ENOENT") {
10613
- console.error(`${TAG17} send-document ENOENT path=${filePath}`);
10614
- return c.json({ error: `File not found: ${filePath}` }, 404);
10615
- }
10616
- console.error(`${TAG17} send-document path error: ${String(err)}`);
10617
- return c.json({ error: String(err) }, 500);
10618
- }
10619
- const fileStat = await stat2(resolvedPath);
10620
- if (fileStat.size > MAX_FILE_SIZE_BYTES) {
10621
- return c.json({ error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)` }, 400);
10622
- }
10623
- const buffer = Buffer.from(await readFile(resolvedPath));
10624
- const filename = basename(resolvedPath);
10625
- const mimetype = detectMimeType(resolvedPath);
10626
- const sock = getSocket(accountId);
10627
- if (!sock) {
10628
- return c.json({ error: `WhatsApp account "${accountId}" is not connected` }, 503);
10629
- }
10630
- const result = await sendMediaMessage(sock, to, {
10631
- type: "document",
10632
- buffer,
10633
- mimetype,
10634
- filename,
10635
- caption
10636
- }, { accountId });
10637
- console.error(
10638
- `${TAG17} send-document to=${to} size=${fileStat.size} mime=${mimetype} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
10639
- );
10640
- return c.json(result);
10807
+ const result = await sendWhatsAppDocument({
10808
+ to,
10809
+ filePath,
10810
+ caption,
10811
+ accountId,
10812
+ maxyAccountId,
10813
+ platformRoot: PLATFORM_ROOT4
10814
+ });
10815
+ if (!result.ok) return c.json({ error: result.error }, result.status);
10816
+ return c.json({ success: true, messageId: result.messageId });
10641
10817
  } catch (err) {
10642
- console.error(`${TAG17} send-document error: ${String(err)}`);
10818
+ console.error(`${TAG19} send-document error: ${String(err)}`);
10643
10819
  return c.json({ error: String(err) }, 500);
10644
10820
  }
10645
10821
  });
@@ -10649,11 +10825,11 @@ app3.get("/activity", (c) => {
10649
10825
  const result = getChannelActivity(accountId);
10650
10826
  const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
10651
10827
  console.error(
10652
- `${TAG17} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
10828
+ `${TAG19} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
10653
10829
  );
10654
10830
  return c.json(result);
10655
10831
  } catch (err) {
10656
- console.error(`${TAG17} activity error: ${String(err)}`);
10832
+ console.error(`${TAG19} activity error: ${String(err)}`);
10657
10833
  return c.json({ error: String(err) }, 500);
10658
10834
  }
10659
10835
  });
@@ -10672,10 +10848,10 @@ app3.get("/conversations", (c) => {
10672
10848
  };
10673
10849
  });
10674
10850
  conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
10675
- console.error(`${TAG17} conversations account=${accountId} count=${conversations.length}`);
10851
+ console.error(`${TAG19} conversations account=${accountId} count=${conversations.length}`);
10676
10852
  return c.json({ conversations });
10677
10853
  } catch (err) {
10678
- console.error(`${TAG17} conversations error: ${String(err)}`);
10854
+ console.error(`${TAG19} conversations error: ${String(err)}`);
10679
10855
  return c.json({ error: String(err) }, 500);
10680
10856
  }
10681
10857
  });
@@ -10690,10 +10866,10 @@ app3.get("/messages", (c) => {
10690
10866
  const limit = limitParam ? parseInt(limitParam, 10) : void 0;
10691
10867
  const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
10692
10868
  const messages = getMessages(accountId, jid, effectiveLimit);
10693
- console.error(`${TAG17} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
10869
+ console.error(`${TAG19} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
10694
10870
  return c.json({ messages });
10695
10871
  } catch (err) {
10696
- console.error(`${TAG17} messages error: ${String(err)}`);
10872
+ console.error(`${TAG19} messages error: ${String(err)}`);
10697
10873
  return c.json({ error: String(err) }, 500);
10698
10874
  }
10699
10875
  });
@@ -10774,7 +10950,7 @@ app3.get("/conversation-graph-state", async (c) => {
10774
10950
  }
10775
10951
  } catch (err) {
10776
10952
  const msg = err instanceof Error ? err.message : String(err);
10777
- console.error(`${TAG17} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
10953
+ console.error(`${TAG19} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
10778
10954
  return c.json({ error: `Graph query failed: ${msg}`, cacheKey, cypher: cypher.trim() }, 500);
10779
10955
  }
10780
10956
  const ms = Date.now() - t0;
@@ -10787,7 +10963,7 @@ app3.get("/conversation-graph-state", async (c) => {
10787
10963
  ms
10788
10964
  });
10789
10965
  } catch (err) {
10790
- console.error(`${TAG17} conversation-graph-state error: ${String(err)}`);
10966
+ console.error(`${TAG19} conversation-graph-state error: ${String(err)}`);
10791
10967
  return c.json({ error: String(err) }, 500);
10792
10968
  }
10793
10969
  });
@@ -10799,12 +10975,12 @@ app3.get("/group-info", async (c) => {
10799
10975
  return c.json({ error: "Missing required parameter: jid" }, 400);
10800
10976
  }
10801
10977
  if (!isGroupJid(jid)) {
10802
- console.error(`${TAG17} group-info error="not a group JID" jid=${jid} account=${accountId}`);
10978
+ console.error(`${TAG19} group-info error="not a group JID" jid=${jid} account=${accountId}`);
10803
10979
  return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
10804
10980
  }
10805
10981
  const sock = getSocket(accountId);
10806
10982
  if (!sock) {
10807
- console.error(`${TAG17} group-info error="not connected" account=${accountId}`);
10983
+ console.error(`${TAG19} group-info error="not connected" account=${accountId}`);
10808
10984
  return c.json({ error: `WhatsApp account "${accountId}" is not connected. Connect first, then retry.` }, 400);
10809
10985
  }
10810
10986
  const meta = await sock.groupMetadata(jid);
@@ -10817,10 +10993,10 @@ app3.get("/group-info", async (c) => {
10817
10993
  participantCount: meta.participants.length,
10818
10994
  participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
10819
10995
  };
10820
- console.error(`${TAG17} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
10996
+ console.error(`${TAG19} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
10821
10997
  return c.json(result);
10822
10998
  } catch (err) {
10823
- console.error(`${TAG17} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
10999
+ console.error(`${TAG19} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
10824
11000
  return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
10825
11001
  }
10826
11002
  });
@@ -11605,7 +11781,7 @@ var session_default = app6;
11605
11781
 
11606
11782
  // server/routes/admin/logs.ts
11607
11783
  import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync10, statSync as statSync5 } from "fs";
11608
- import { resolve as resolve7, basename as basename2 } from "path";
11784
+ import { resolve as resolve8, basename as basename2 } from "path";
11609
11785
 
11610
11786
  // app/lib/logs-read-resolve.ts
11611
11787
  import { existsSync as existsSync9 } from "fs";
@@ -11632,7 +11808,7 @@ app7.get("/", async (c) => {
11632
11808
  const cacheKeyParam = c.req.query("cacheKey");
11633
11809
  const download = c.req.query("download") === "1";
11634
11810
  const account = resolveAccount();
11635
- const accountLogDir = account ? resolve7(account.accountDir, "logs") : null;
11811
+ const accountLogDir = account ? resolve8(account.accountDir, "logs") : null;
11636
11812
  const logDirs = [];
11637
11813
  if (accountLogDir) logDirs.push(accountLogDir);
11638
11814
  logDirs.push(LOG_DIR);
@@ -11640,7 +11816,7 @@ app7.get("/", async (c) => {
11640
11816
  const safe = basename2(fileParam);
11641
11817
  const searched = [];
11642
11818
  for (const dir of logDirs) {
11643
- const filePath = resolve7(dir, safe);
11819
+ const filePath = resolve8(dir, safe);
11644
11820
  searched.push(filePath);
11645
11821
  try {
11646
11822
  const buffer = readFileSync10(filePath);
@@ -11752,10 +11928,10 @@ app7.get("/", async (c) => {
11752
11928
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
11753
11929
  continue;
11754
11930
  }
11755
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync5(resolve7(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
11931
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync5(resolve8(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
11756
11932
  seen.add(name);
11757
11933
  try {
11758
- const content = readFileSync10(resolve7(dir, name));
11934
+ const content = readFileSync10(resolve8(dir, name));
11759
11935
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
11760
11936
  logs[name] = tail.trim() || "(empty)";
11761
11937
  } catch (err) {
@@ -11795,7 +11971,7 @@ var claude_info_default = app8;
11795
11971
  // server/routes/admin/attachment.ts
11796
11972
  import { readFile as readFile2, readdir } from "fs/promises";
11797
11973
  import { existsSync as existsSync11 } from "fs";
11798
- import { resolve as resolve8 } from "path";
11974
+ import { resolve as resolve9 } from "path";
11799
11975
  var app9 = new Hono();
11800
11976
  app9.get("/:attachmentId", requireAdminSession, async (c) => {
11801
11977
  const attachmentId = c.req.param("attachmentId");
@@ -11807,11 +11983,11 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11807
11983
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
11808
11984
  return new Response("Not found", { status: 404 });
11809
11985
  }
11810
- const dir = resolve8(ATTACHMENTS_ROOT, accountId, attachmentId);
11986
+ const dir = resolve9(ATTACHMENTS_ROOT, accountId, attachmentId);
11811
11987
  if (!existsSync11(dir)) {
11812
11988
  return new Response("Not found", { status: 404 });
11813
11989
  }
11814
- const metaPath = resolve8(dir, `${attachmentId}.meta.json`);
11990
+ const metaPath = resolve9(dir, `${attachmentId}.meta.json`);
11815
11991
  if (!existsSync11(metaPath)) {
11816
11992
  return new Response("Not found", { status: 404 });
11817
11993
  }
@@ -11826,7 +12002,7 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11826
12002
  if (!dataFile) {
11827
12003
  return new Response("Not found", { status: 404 });
11828
12004
  }
11829
- const filePath = resolve8(dir, dataFile);
12005
+ const filePath = resolve9(dir, dataFile);
11830
12006
  const buffer = await readFile2(filePath);
11831
12007
  return new Response(new Uint8Array(buffer), {
11832
12008
  headers: {
@@ -11839,13 +12015,13 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11839
12015
  var attachment_default = app9;
11840
12016
 
11841
12017
  // server/routes/admin/agents.ts
11842
- import { resolve as resolve9 } from "path";
12018
+ import { resolve as resolve10 } from "path";
11843
12019
  import { readdirSync as readdirSync6, readFileSync as readFileSync11, existsSync as existsSync12, rmSync } from "fs";
11844
12020
  var app10 = new Hono();
11845
12021
  app10.get("/", (c) => {
11846
12022
  const account = resolveAccount();
11847
12023
  if (!account) return c.json({ agents: [] });
11848
- const agentsDir = resolve9(account.accountDir, "agents");
12024
+ const agentsDir = resolve10(account.accountDir, "agents");
11849
12025
  if (!existsSync12(agentsDir)) return c.json({ agents: [] });
11850
12026
  const agents = [];
11851
12027
  try {
@@ -11853,7 +12029,7 @@ app10.get("/", (c) => {
11853
12029
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
11854
12030
  if (!entry.isDirectory()) continue;
11855
12031
  if (entry.name === "admin") continue;
11856
- const configPath2 = resolve9(agentsDir, entry.name, "config.json");
12032
+ const configPath2 = resolve10(agentsDir, entry.name, "config.json");
11857
12033
  if (!existsSync12(configPath2)) continue;
11858
12034
  try {
11859
12035
  const config = JSON.parse(readFileSync11(configPath2, "utf-8"));
@@ -11882,7 +12058,7 @@ app10.delete("/:slug", async (c) => {
11882
12058
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
11883
12059
  return c.json({ error: "Invalid agent slug" }, 400);
11884
12060
  }
11885
- const agentDir = resolve9(account.accountDir, "agents", slug);
12061
+ const agentDir = resolve10(account.accountDir, "agents", slug);
11886
12062
  if (!existsSync12(agentDir)) {
11887
12063
  return c.json({ error: "Agent not found" }, 404);
11888
12064
  }
@@ -11912,7 +12088,7 @@ app10.post("/:slug/project", async (c) => {
11912
12088
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
11913
12089
  return c.json({ error: "Invalid agent slug" }, 400);
11914
12090
  }
11915
- const agentDir = resolve9(account.accountDir, "agents", slug);
12091
+ const agentDir = resolve10(account.accountDir, "agents", slug);
11916
12092
  if (!existsSync12(agentDir)) {
11917
12093
  return c.json({ error: "Agent not found on disk" }, 404);
11918
12094
  }
@@ -12617,7 +12793,7 @@ var sessions_default = app11;
12617
12793
 
12618
12794
  // app/lib/claude-agent/spawn-context.ts
12619
12795
  import { existsSync as existsSync14, readFileSync as readFileSync12, readdirSync as readdirSync7, statSync as statSync6 } from "fs";
12620
- import { dirname as dirname2, resolve as resolve10, join as join10 } from "path";
12796
+ import { dirname as dirname2, resolve as resolve11, join as join10 } from "path";
12621
12797
  async function resolveOwnerProfileBlock(accountId, userId) {
12622
12798
  if (!userId) return { ok: false, reason: "missing-user-id" };
12623
12799
  try {
@@ -12702,7 +12878,7 @@ function parseSkillPathsFromFrontmatter(fm) {
12702
12878
  }
12703
12879
  function listPluginDirs() {
12704
12880
  const out = /* @__PURE__ */ new Map();
12705
- const platformPlugins = resolve10(PLATFORM_ROOT, "plugins");
12881
+ const platformPlugins = resolve11(PLATFORM_ROOT, "plugins");
12706
12882
  if (existsSync14(platformPlugins)) {
12707
12883
  for (const name of readdirSync7(platformPlugins)) {
12708
12884
  const dir = join10(platformPlugins, name);
@@ -12712,7 +12888,7 @@ function listPluginDirs() {
12712
12888
  }
12713
12889
  }
12714
12890
  }
12715
- const premiumRoot = resolve10(dirname2(PLATFORM_ROOT), "premium-plugins");
12891
+ const premiumRoot = resolve11(dirname2(PLATFORM_ROOT), "premium-plugins");
12716
12892
  if (existsSync14(premiumRoot)) {
12717
12893
  for (const bundle of readdirSync7(premiumRoot)) {
12718
12894
  const bundlePlugins = join10(premiumRoot, bundle, "plugins");
@@ -12732,7 +12908,7 @@ function listPluginDirs() {
12732
12908
  return out;
12733
12909
  }
12734
12910
  function readEnabledPlugins(accountId) {
12735
- const accountFile = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12911
+ const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12736
12912
  if (!existsSync14(accountFile)) return /* @__PURE__ */ new Set();
12737
12913
  try {
12738
12914
  const parsed = JSON.parse(readFileSync12(accountFile, "utf-8"));
@@ -12805,7 +12981,7 @@ ${skillFm}
12805
12981
  return out;
12806
12982
  }
12807
12983
  function computeSpecialistDomains(accountId) {
12808
- const specialistsDir = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
12984
+ const specialistsDir = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
12809
12985
  if (!existsSync14(specialistsDir)) return [];
12810
12986
  let entries;
12811
12987
  try {
@@ -12851,7 +13027,7 @@ ${fm}
12851
13027
  return out;
12852
13028
  }
12853
13029
  function computeDormantPlugins(accountId) {
12854
- const accountFile = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
13030
+ const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12855
13031
  if (!existsSync14(accountFile)) return [];
12856
13032
  let enabled;
12857
13033
  try {
@@ -12866,7 +13042,7 @@ function computeDormantPlugins(accountId) {
12866
13042
  );
12867
13043
  return [];
12868
13044
  }
12869
- const pluginsDir = resolve10(PLATFORM_ROOT, "plugins");
13045
+ const pluginsDir = resolve11(PLATFORM_ROOT, "plugins");
12870
13046
  if (!existsSync14(pluginsDir)) return [];
12871
13047
  let entries;
12872
13048
  try {
@@ -12877,7 +13053,7 @@ function computeDormantPlugins(accountId) {
12877
13053
  const out = [];
12878
13054
  for (const name of entries) {
12879
13055
  if (enabled.has(name)) continue;
12880
- const manifestPath = resolve10(pluginsDir, name, "PLUGIN.md");
13056
+ const manifestPath = resolve11(pluginsDir, name, "PLUGIN.md");
12881
13057
  if (!existsSync14(manifestPath)) continue;
12882
13058
  let manifest;
12883
13059
  try {
@@ -12896,7 +13072,7 @@ function computeDormantPlugins(accountId) {
12896
13072
 
12897
13073
  // server/routes/admin/claude-sessions.ts
12898
13074
  import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
12899
- import { resolve as resolve11 } from "path";
13075
+ import { resolve as resolve12 } from "path";
12900
13076
  function readTunnelState(brandConfigDir) {
12901
13077
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
12902
13078
  if (!existsSync15(statePath)) return null;
@@ -12912,10 +13088,10 @@ function readTunnelState(brandConfigDir) {
12912
13088
  }
12913
13089
  }
12914
13090
  function resolveTunnelUrl() {
12915
- const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve11(process.cwd(), "..");
13091
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
12916
13092
  let brand;
12917
13093
  try {
12918
- brand = JSON.parse(readFileSync13(resolve11(platformRoot, "config", "brand.json"), "utf-8"));
13094
+ brand = JSON.parse(readFileSync13(resolve12(platformRoot2, "config", "brand.json"), "utf-8"));
12919
13095
  } catch {
12920
13096
  return null;
12921
13097
  }
@@ -12926,7 +13102,7 @@ function resolveTunnelUrl() {
12926
13102
  if (!state) return null;
12927
13103
  return `https://${hostname2}.${state.domain}`;
12928
13104
  }
12929
- var TAG18 = "[claude-session-manager:wrapper]";
13105
+ var TAG20 = "[claude-session-manager:wrapper]";
12930
13106
  async function refuseIfClaudeAuthDead(c, route, sessionId) {
12931
13107
  const auth = await ensureAuth();
12932
13108
  if (auth.status !== "dead" && auth.status !== "missing") return null;
@@ -12948,12 +13124,12 @@ async function performSpawnWithInitialMessage(args) {
12948
13124
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
12949
13125
  const ownerMs = Date.now() - ownerStart;
12950
13126
  const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
12951
- console.log(`${TAG18} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
13127
+ console.log(`${TAG20} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
12952
13128
  const dormantPlugins = computeDormantPlugins(args.senderId);
12953
13129
  const activePlugins = computeActivePlugins(args.senderId);
12954
13130
  const specialistDomains = computeSpecialistDomains(args.senderId);
12955
13131
  const tunnelUrl = resolveTunnelUrl();
12956
- console.log(`${TAG18} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
13132
+ console.log(`${TAG20} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
12957
13133
  const upstreamPayload = JSON.stringify({
12958
13134
  senderId: args.senderId,
12959
13135
  // Task 205 — pass userId through to the manager so it lands as
@@ -12980,24 +13156,24 @@ async function performSpawnWithInitialMessage(args) {
12980
13156
  // unshapely values.
12981
13157
  conversationNodeId: args.conversationNodeId
12982
13158
  });
12983
- console.log(`${TAG18} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
13159
+ console.log(`${TAG20} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
12984
13160
  const forwardStart = Date.now();
12985
13161
  const upstream = await fetch(`${managerBase3()}/public-spawn`, {
12986
13162
  method: "POST",
12987
13163
  headers: { "content-type": "application/json" },
12988
13164
  body: upstreamPayload
12989
13165
  }).catch((err) => {
12990
- console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
13166
+ console.error(`${TAG20} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
12991
13167
  return null;
12992
13168
  });
12993
13169
  if (!upstream) return {
12994
13170
  response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
12995
13171
  claudeSessionId: null
12996
13172
  };
12997
- console.log(`${TAG18} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
13173
+ console.log(`${TAG20} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
12998
13174
  if (args.initialMessage) {
12999
13175
  const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
13000
- console.log(`${TAG18} initial-message-inlined bytes=${inputBytes}`);
13176
+ console.log(`${TAG20} initial-message-inlined bytes=${inputBytes}`);
13001
13177
  }
13002
13178
  const bodyText = await upstream.text().catch(() => "");
13003
13179
  let claudeSessionId = null;
@@ -13032,7 +13208,7 @@ app12.post("/", async (c) => {
13032
13208
  if (refusal) return refusal;
13033
13209
  const senderId = getAccountIdForSession(cacheKey) ?? "";
13034
13210
  if (!senderId) {
13035
- console.error(`${TAG18} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
13211
+ console.error(`${TAG20} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
13036
13212
  return c.json({ error: "admin-account-not-resolved" }, 500);
13037
13213
  }
13038
13214
  const userId = getUserIdForSession(cacheKey) ?? void 0;
@@ -13041,7 +13217,7 @@ app12.post("/", async (c) => {
13041
13217
  const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
13042
13218
  const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
13043
13219
  const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
13044
- console.log(`${TAG18} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
13220
+ console.log(`${TAG20} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
13045
13221
  const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
13046
13222
  const { response, claudeSessionId } = await performSpawnWithInitialMessage({
13047
13223
  senderId,
@@ -13060,13 +13236,13 @@ app12.post("/", async (c) => {
13060
13236
  claudeSessionId,
13061
13237
  senderId
13062
13238
  );
13063
- console.log(`${TAG18} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
13239
+ console.log(`${TAG20} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
13064
13240
  return response;
13065
13241
  });
13066
13242
  var claude_sessions_default = app12;
13067
13243
 
13068
13244
  // server/routes/admin/log-ingest.ts
13069
- var TAG19 = "[log-ingest]";
13245
+ var TAG21 = "[log-ingest]";
13070
13246
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
13071
13247
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
13072
13248
  var MAX_LINE_BYTES = 4096;
@@ -13077,7 +13253,7 @@ function isLoopbackAddr(addr) {
13077
13253
  app13.post("/", async (c) => {
13078
13254
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13079
13255
  if (!isLoopbackAddr(remoteAddr)) {
13080
- console.error(`${TAG19} reject reason=non-loopback remoteAddr=${remoteAddr}`);
13256
+ console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
13081
13257
  return c.json({ error: "log-ingest-loopback-only" }, 403);
13082
13258
  }
13083
13259
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -13086,7 +13262,7 @@ app13.post("/", async (c) => {
13086
13262
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
13087
13263
  const offender = tokens.find((t) => !isLoopbackAddr(t));
13088
13264
  if (offender !== void 0) {
13089
- console.error(`${TAG19} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
13265
+ console.error(`${TAG21} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
13090
13266
  return c.json({ error: "log-ingest-loopback-only" }, 403);
13091
13267
  }
13092
13268
  }
@@ -13128,18 +13304,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
13128
13304
  ]);
13129
13305
  var app14 = new Hono();
13130
13306
  app14.post("/", async (c) => {
13131
- const TAG29 = "[admin:events]";
13307
+ const TAG31 = "[admin:events]";
13132
13308
  let body;
13133
13309
  try {
13134
13310
  body = await c.req.json();
13135
13311
  } catch (err) {
13136
13312
  const detail = err instanceof Error ? err.message : String(err);
13137
- console.error(`${TAG29} reject reason=body-not-json detail=${detail}`);
13313
+ console.error(`${TAG31} reject reason=body-not-json detail=${detail}`);
13138
13314
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
13139
13315
  }
13140
13316
  const event = typeof body.event === "string" ? body.event : "";
13141
13317
  if (!ALLOWED_EVENTS.has(event)) {
13142
- console.error(`${TAG29} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
13318
+ console.error(`${TAG31} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
13143
13319
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
13144
13320
  }
13145
13321
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
@@ -13164,15 +13340,15 @@ var events_default = app14;
13164
13340
  import { createReadStream as createReadStream2 } from "fs";
13165
13341
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
13166
13342
  import { realpathSync as realpathSync4 } from "fs";
13167
- import { basename as basename4, dirname as dirname3, join as join12, resolve as resolve14, sep as sep4 } from "path";
13343
+ import { basename as basename4, dirname as dirname3, join as join12, resolve as resolve15, sep as sep4 } from "path";
13168
13344
  import { Readable as Readable2 } from "stream";
13169
13345
 
13170
13346
  // app/lib/data-path.ts
13171
13347
  import { realpathSync as realpathSync3 } from "fs";
13172
- import { resolve as resolve12, normalize, sep as sep2, relative } from "path";
13173
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve12(process.cwd(), "../platform");
13174
- var DATA_ROOT = resolve12(PLATFORM_ROOT5, "..", "data");
13175
- var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve12(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
13348
+ import { resolve as resolve13, normalize, sep as sep2, relative } from "path";
13349
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "../platform");
13350
+ var DATA_ROOT = resolve13(PLATFORM_ROOT5, "..", "data");
13351
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve13(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
13176
13352
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
13177
13353
  var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13178
13354
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -13185,7 +13361,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
13185
13361
  }
13186
13362
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
13187
13363
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
13188
- const absolute = resolve12(rootAbs, cleaned);
13364
+ const absolute = resolve13(rootAbs, cleaned);
13189
13365
  let rootReal;
13190
13366
  try {
13191
13367
  rootReal = realpathSync3(rootAbs);
@@ -13544,7 +13720,7 @@ async function cascadeDeleteDocument(params) {
13544
13720
 
13545
13721
  // app/lib/file-index.ts
13546
13722
  import * as fsp from "fs/promises";
13547
- import { resolve as resolve13, relative as relative2, join as join11, basename as basename3, extname as extname2, sep as sep3 } from "path";
13723
+ import { resolve as resolve14, relative as relative2, join as join11, basename as basename3, extname as extname2, sep as sep3 } from "path";
13548
13724
  import { tmpdir as tmpdir2 } from "os";
13549
13725
  import { execFile as execFile2 } from "child_process";
13550
13726
  import { promisify as promisify2 } from "util";
@@ -13852,8 +14028,8 @@ async function reconcileFileIndex(accountId, opts) {
13852
14028
  return withSession(opts, async (session) => {
13853
14029
  const walked = [];
13854
14030
  const subtreeRoots = [
13855
- resolve13(dataRoot, "uploads", accountId),
13856
- resolve13(dataRoot, "accounts", accountId)
14031
+ resolve14(dataRoot, "uploads", accountId),
14032
+ resolve14(dataRoot, "accounts", accountId)
13857
14033
  ];
13858
14034
  let clean = true;
13859
14035
  for (const root of subtreeRoots) {
@@ -13934,7 +14110,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
13934
14110
  async function indexFile(accountId, relativePath, opts) {
13935
14111
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
13936
14112
  const embed2 = opts?.embed ?? embed;
13937
- const absolute = resolve13(dataRoot, relativePath);
14113
+ const absolute = resolve14(dataRoot, relativePath);
13938
14114
  await withSession(opts, async (session) => {
13939
14115
  const st = await fsp.stat(absolute);
13940
14116
  const wf = {
@@ -13979,7 +14155,7 @@ async function readMeta(absDir, baseName) {
13979
14155
  }
13980
14156
  async function readAccountNames() {
13981
14157
  const map = /* @__PURE__ */ new Map();
13982
- const accountsDir = resolve14(DATA_ROOT, "accounts");
14158
+ const accountsDir = resolve15(DATA_ROOT, "accounts");
13983
14159
  let names;
13984
14160
  try {
13985
14161
  names = await readdir3(accountsDir);
@@ -13988,7 +14164,7 @@ async function readAccountNames() {
13988
14164
  }
13989
14165
  for (const name of names) {
13990
14166
  if (!UUID_RE3.test(name)) continue;
13991
- const configPath2 = resolve14(accountsDir, name, "account.json");
14167
+ const configPath2 = resolve15(accountsDir, name, "account.json");
13992
14168
  try {
13993
14169
  const raw = await readFile4(configPath2, "utf8");
13994
14170
  const parsed = JSON.parse(raw);
@@ -14229,8 +14405,8 @@ app15.post("/upload", requireAdminSession, async (c) => {
14229
14405
  }
14230
14406
  const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
14231
14407
  const finalName = `${Date.now()}-${safeName}`;
14232
- const destDir = resolve14(DATA_ROOT, "uploads", accountId);
14233
- const destPath = resolve14(destDir, finalName);
14408
+ const destDir = resolve15(DATA_ROOT, "uploads", accountId);
14409
+ const destPath = resolve15(destDir, finalName);
14234
14410
  try {
14235
14411
  await mkdir3(destDir, { recursive: true });
14236
14412
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -16337,7 +16513,7 @@ var graph_default_view_default = app21;
16337
16513
 
16338
16514
  // server/routes/admin/sidebar-artefacts.ts
16339
16515
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
16340
- import { resolve as resolve15, relative as relative3, isAbsolute, sep as sep5, basename as basename5 } from "path";
16516
+ import { resolve as resolve16, relative as relative3, isAbsolute, sep as sep5, basename as basename5 } from "path";
16341
16517
  import { existsSync as existsSync16 } from "fs";
16342
16518
  var LIMIT = 50;
16343
16519
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -16357,7 +16533,7 @@ app22.get("/", requireAdminSession, async (c) => {
16357
16533
  if (outputs === null) {
16358
16534
  return c.json({ error: "Failed to load artefacts" }, 500);
16359
16535
  }
16360
- const accountDir = resolve15(ACCOUNTS_DIR, accountId);
16536
+ const accountDir = resolve16(ACCOUNTS_DIR, accountId);
16361
16537
  const agents = await fetchAgentTemplateRows(accountDir);
16362
16538
  const artefacts = [...outputs, ...agents].sort(
16363
16539
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -16408,8 +16584,8 @@ async function fetchOutputArtefacts(accountId) {
16408
16584
  async function fetchAgentTemplateRows(accountDir) {
16409
16585
  const rows = [];
16410
16586
  for (const filename of ADMIN_AGENT_FILES) {
16411
- const overridePath = resolve15(accountDir, "agents", "admin", filename);
16412
- const bundledPath = resolve15(PLATFORM_ROOT, "templates", "agents", "admin", filename);
16587
+ const overridePath = resolve16(accountDir, "agents", "admin", filename);
16588
+ const bundledPath = resolve16(PLATFORM_ROOT, "templates", "agents", "admin", filename);
16413
16589
  const labelStem = filename.replace(/\.md$/, "");
16414
16590
  const row = await readAgentTemplateRow({
16415
16591
  id: `agent-template:admin:${filename}`,
@@ -16422,12 +16598,12 @@ async function fetchAgentTemplateRows(accountDir) {
16422
16598
  });
16423
16599
  if (row) rows.push(row);
16424
16600
  }
16425
- const overrideDir = resolve15(accountDir, "specialists", "agents");
16426
- const bundledDir = resolve15(PLATFORM_ROOT, "templates", "specialists", "agents");
16601
+ const overrideDir = resolve16(accountDir, "specialists", "agents");
16602
+ const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
16427
16603
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
16428
16604
  for (const filename of specialistNames) {
16429
- const overridePath = resolve15(overrideDir, filename);
16430
- const bundledPath = resolve15(bundledDir, filename);
16605
+ const overridePath = resolve16(overrideDir, filename);
16606
+ const bundledPath = resolve16(bundledDir, filename);
16431
16607
  const row = await readAgentTemplateRow({
16432
16608
  id: `agent-template:specialist:${filename}`,
16433
16609
  displayName: filename.replace(/\.md$/, ""),
@@ -16513,7 +16689,7 @@ var sidebar_artefacts_default = app22;
16513
16689
 
16514
16690
  // server/routes/admin/sidebar-sessions.ts
16515
16691
  import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
16516
- import { join as join13, resolve as resolve16 } from "path";
16692
+ import { join as join13, resolve as resolve17 } from "path";
16517
16693
  var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
16518
16694
  var PID_FILE_RE = /^([0-9]+)\.json$/;
16519
16695
  var TITLE_MAX = 80;
@@ -16694,7 +16870,7 @@ app23.get("/", requireAdminSession, async (c) => {
16694
16870
  const projectsRoot = join13(configDir2, "projects");
16695
16871
  const jsonls = enumerateJsonls(projectsRoot);
16696
16872
  const pidsBySession = sessionIdToPidMap(configDir2);
16697
- const accountDir = accountId ? resolve16(ACCOUNTS_DIR, accountId) : null;
16873
+ const accountDir = accountId ? resolve17(ACCOUNTS_DIR, accountId) : null;
16698
16874
  const userTitles = loadUserTitles(accountDir);
16699
16875
  const rows = [];
16700
16876
  const seenIds = /* @__PURE__ */ new Set();
@@ -16748,7 +16924,7 @@ var sidebar_sessions_default = app23;
16748
16924
 
16749
16925
  // server/routes/admin/session-delete.ts
16750
16926
  import { existsSync as existsSync17, readdirSync as readdirSync9, readFileSync as readFileSync15, unlinkSync as unlinkSync2 } from "fs";
16751
- import { join as join14, resolve as resolve17 } from "path";
16927
+ import { join as join14, resolve as resolve18 } from "path";
16752
16928
  var app24 = new Hono();
16753
16929
  var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
16754
16930
  var PID_FILE_RE2 = /^([0-9]+)\.json$/;
@@ -16797,7 +16973,7 @@ function isPidAlive(pid) {
16797
16973
  }
16798
16974
  }
16799
16975
  function sleep2(ms) {
16800
- return new Promise((resolve26) => setTimeout(resolve26, ms));
16976
+ return new Promise((resolve27) => setTimeout(resolve27, ms));
16801
16977
  }
16802
16978
  function sendSignal(pid, signal) {
16803
16979
  try {
@@ -16865,8 +17041,8 @@ app24.post("/", requireAdminSession, async (c) => {
16865
17041
  if (!configDir2) {
16866
17042
  return c.json({ error: "CLAUDE_CONFIG_DIR not set" }, 500);
16867
17043
  }
16868
- const projectsRoot = resolve17(join14(configDir2, "projects")) + "/";
16869
- const resolvedProject = resolve17(projectDir) + "/";
17044
+ const projectsRoot = resolve18(join14(configDir2, "projects")) + "/";
17045
+ const resolvedProject = resolve18(projectDir) + "/";
16870
17046
  if (!resolvedProject.startsWith(projectsRoot)) {
16871
17047
  console.error(`[sessions-delete] reject reason=projectDir-outside-tree projectDir=${projectDir}`);
16872
17048
  return c.json({ error: "projectDir is not under CLAUDE_CONFIG_DIR/projects/" }, 400);
@@ -17097,8 +17273,8 @@ var system_stats_default = app26;
17097
17273
 
17098
17274
  // server/routes/admin/health.ts
17099
17275
  import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
17100
- import { resolve as resolve18, join as join15 } from "path";
17101
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
17276
+ import { resolve as resolve19, join as join15 } from "path";
17277
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
17102
17278
  var brandHostname = "maxy";
17103
17279
  var brandJsonPath = join15(PLATFORM_ROOT6, "config", "brand.json");
17104
17280
  if (existsSync18(brandJsonPath)) {
@@ -17108,7 +17284,7 @@ if (existsSync18(brandJsonPath)) {
17108
17284
  } catch {
17109
17285
  }
17110
17286
  }
17111
- var VERSION_FILE = resolve18(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
17287
+ var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
17112
17288
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
17113
17289
  var PROBE_TIMEOUT_MS = 1e3;
17114
17290
  function readVersion() {
@@ -17165,7 +17341,7 @@ var health_default2 = app27;
17165
17341
 
17166
17342
  // server/routes/admin/linkedin-ingest.ts
17167
17343
  import { randomUUID as randomUUID9 } from "crypto";
17168
- var TAG20 = "[linkedin-ingest-route]";
17344
+ var TAG22 = "[linkedin-ingest-route]";
17169
17345
  var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
17170
17346
  var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
17171
17347
  var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
@@ -17269,29 +17445,29 @@ app28.post("/", requireAdminSession, async (c) => {
17269
17445
  try {
17270
17446
  body = await c.req.json();
17271
17447
  } catch {
17272
- console.error(TAG20 + " rejected status=400 reason=schema:body-not-json");
17448
+ console.error(TAG22 + " rejected status=400 reason=schema:body-not-json");
17273
17449
  return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
17274
17450
  }
17275
17451
  const v = validate(body);
17276
17452
  if (!v.ok) {
17277
- console.error(TAG20 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
17453
+ console.error(TAG22 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
17278
17454
  return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
17279
17455
  }
17280
17456
  const envelope = v.envelope;
17281
17457
  const cacheKey = c.var.cacheKey ?? "";
17282
17458
  const senderId = getAccountIdForSession(cacheKey) ?? "";
17283
17459
  if (!senderId) {
17284
- console.error(TAG20 + " rejected status=500 reason=admin-account-not-resolved");
17460
+ console.error(TAG22 + " rejected status=500 reason=admin-account-not-resolved");
17285
17461
  return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
17286
17462
  }
17287
17463
  const payloadBytes = JSON.stringify(envelope).length;
17288
17464
  console.log(
17289
- TAG20 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
17465
+ TAG22 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
17290
17466
  );
17291
17467
  const initialMessage = buildInitialMessage(envelope);
17292
17468
  const spawnStart = Date.now();
17293
17469
  const sessionId = randomUUID9();
17294
- console.log(TAG20 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
17470
+ console.log(TAG22 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
17295
17471
  const spawned = await managerRcSpawn({
17296
17472
  sessionId,
17297
17473
  initialMessage,
@@ -17300,12 +17476,12 @@ app28.post("/", requireAdminSession, async (c) => {
17300
17476
  });
17301
17477
  if ("error" in spawned) {
17302
17478
  console.error(
17303
- TAG20 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
17479
+ TAG22 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
17304
17480
  );
17305
17481
  return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
17306
17482
  }
17307
17483
  console.log(
17308
- TAG20 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
17484
+ TAG22 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
17309
17485
  );
17310
17486
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
17311
17487
  });
@@ -17313,7 +17489,7 @@ var linkedin_ingest_default = app28;
17313
17489
 
17314
17490
  // server/routes/admin/post-turn-context.ts
17315
17491
  import neo4j2 from "neo4j-driver";
17316
- var TAG21 = "[post-turn-context]";
17492
+ var TAG23 = "[post-turn-context]";
17317
17493
  var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
17318
17494
  "embedding",
17319
17495
  "passwordHash",
@@ -17355,7 +17531,7 @@ var app29 = new Hono();
17355
17531
  app29.get("/", async (c) => {
17356
17532
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17357
17533
  if (!isLoopbackAddr2(remoteAddr)) {
17358
- console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17534
+ console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17359
17535
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
17360
17536
  }
17361
17537
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17364,7 +17540,7 @@ app29.get("/", async (c) => {
17364
17540
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17365
17541
  const offender = tokens.find((t) => !isLoopbackAddr2(t));
17366
17542
  if (offender !== void 0) {
17367
- console.error(`${TAG21} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17543
+ console.error(`${TAG23} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17368
17544
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
17369
17545
  }
17370
17546
  }
@@ -17396,7 +17572,7 @@ app29.get("/", async (c) => {
17396
17572
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
17397
17573
  const total = Date.now() - started;
17398
17574
  console.log(
17399
- `${TAG21} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
17575
+ `${TAG23} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
17400
17576
  );
17401
17577
  return c.json({
17402
17578
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
@@ -17405,7 +17581,7 @@ app29.get("/", async (c) => {
17405
17581
  const elapsed = Date.now() - started;
17406
17582
  const message = err instanceof Error ? err.message : String(err);
17407
17583
  console.error(
17408
- `${TAG21} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
17584
+ `${TAG23} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
17409
17585
  );
17410
17586
  return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
17411
17587
  } finally {
@@ -17416,7 +17592,7 @@ var post_turn_context_default = app29;
17416
17592
 
17417
17593
  // server/routes/admin/public-session-context.ts
17418
17594
  import neo4j3 from "neo4j-driver";
17419
- var TAG22 = "[public-session-context]";
17595
+ var TAG24 = "[public-session-context]";
17420
17596
  var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
17421
17597
  "embedding",
17422
17598
  "passwordHash",
@@ -17458,7 +17634,7 @@ var app30 = new Hono();
17458
17634
  app30.get("/", async (c) => {
17459
17635
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17460
17636
  if (!isLoopbackAddr3(remoteAddr)) {
17461
- console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17637
+ console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17462
17638
  return c.json({ error: "public-session-context-loopback-only" }, 403);
17463
17639
  }
17464
17640
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17467,7 +17643,7 @@ app30.get("/", async (c) => {
17467
17643
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17468
17644
  const offender = tokens.find((t) => !isLoopbackAddr3(t));
17469
17645
  if (offender !== void 0) {
17470
- console.error(`${TAG22} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17646
+ console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17471
17647
  return c.json({ error: "public-session-context-loopback-only" }, 403);
17472
17648
  }
17473
17649
  }
@@ -17498,7 +17674,7 @@ app30.get("/", async (c) => {
17498
17674
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
17499
17675
  const total = Date.now() - started;
17500
17676
  console.log(
17501
- `${TAG22} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
17677
+ `${TAG24} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
17502
17678
  );
17503
17679
  return c.json({
17504
17680
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
@@ -17507,7 +17683,7 @@ app30.get("/", async (c) => {
17507
17683
  const elapsed = Date.now() - started;
17508
17684
  const message = err instanceof Error ? err.message : String(err);
17509
17685
  console.error(
17510
- `${TAG22} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
17686
+ `${TAG24} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
17511
17687
  );
17512
17688
  return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
17513
17689
  } finally {
@@ -17517,7 +17693,7 @@ app30.get("/", async (c) => {
17517
17693
  var public_session_context_default = app30;
17518
17694
 
17519
17695
  // server/routes/admin/public-session-exit.ts
17520
- var TAG23 = "[public-session-exit-route]";
17696
+ var TAG25 = "[public-session-exit-route]";
17521
17697
  function isLoopbackAddr4(addr) {
17522
17698
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
17523
17699
  }
@@ -17525,7 +17701,7 @@ var app31 = new Hono();
17525
17701
  app31.post("/", async (c) => {
17526
17702
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17527
17703
  if (!isLoopbackAddr4(remoteAddr)) {
17528
- console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17704
+ console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17529
17705
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
17530
17706
  }
17531
17707
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17534,7 +17710,7 @@ app31.post("/", async (c) => {
17534
17710
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17535
17711
  const offender = tokens.find((t) => !isLoopbackAddr4(t));
17536
17712
  if (offender !== void 0) {
17537
- console.error(`${TAG23} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17713
+ console.error(`${TAG25} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17538
17714
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
17539
17715
  }
17540
17716
  }
@@ -17552,7 +17728,7 @@ app31.post("/", async (c) => {
17552
17728
  var public_session_exit_default = app31;
17553
17729
 
17554
17730
  // server/routes/admin/access-session-evict.ts
17555
- var TAG24 = "[access-session-evict]";
17731
+ var TAG26 = "[access-session-evict]";
17556
17732
  function isLoopbackAddr5(addr) {
17557
17733
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
17558
17734
  }
@@ -17560,7 +17736,7 @@ var app32 = new Hono();
17560
17736
  app32.post("/", async (c) => {
17561
17737
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17562
17738
  if (!isLoopbackAddr5(remoteAddr)) {
17563
- console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17739
+ console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17564
17740
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
17565
17741
  }
17566
17742
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17569,7 +17745,7 @@ app32.post("/", async (c) => {
17569
17745
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17570
17746
  const offender = tokens.find((t) => !isLoopbackAddr5(t));
17571
17747
  if (offender !== void 0) {
17572
- console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17748
+ console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17573
17749
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
17574
17750
  }
17575
17751
  }
@@ -17582,7 +17758,7 @@ app32.post("/", async (c) => {
17582
17758
  const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
17583
17759
  if (!grantId) return c.json({ error: "grantId required" }, 400);
17584
17760
  const dropped = evictAccessSessionsByGrant(grantId);
17585
- console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
17761
+ console.log(`${TAG26} grantId=${grantId} dropped=${dropped}`);
17586
17762
  return c.json({ ok: true, dropped });
17587
17763
  });
17588
17764
  var access_session_evict_default = app32;
@@ -17590,7 +17766,7 @@ var access_session_evict_default = app32;
17590
17766
  // server/routes/admin/identity.ts
17591
17767
  var import_dist4 = __toESM(require_dist3(), 1);
17592
17768
  var app33 = new Hono();
17593
- var TAG25 = "[admin-identity]";
17769
+ var TAG27 = "[admin-identity]";
17594
17770
  function managerBase5() {
17595
17771
  const port2 = (0, import_dist4.requirePortEnv)("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-identity" });
17596
17772
  return `http://127.0.0.1:${port2}`;
@@ -17621,20 +17797,20 @@ app33.post("/validate", async (c) => {
17621
17797
  const verdict = validatePin(pin, USERS_FILE);
17622
17798
  if (verdict.kind !== "match") {
17623
17799
  if (verdict.kind === "miss") fireStop();
17624
- console.log(`${TAG25} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
17800
+ console.log(`${TAG27} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
17625
17801
  return c.json({ kind: verdict.kind });
17626
17802
  }
17627
17803
  const { userId } = verdict;
17628
17804
  const accounts = resolveUserAccounts(userId);
17629
17805
  if (accounts.length === 0) {
17630
17806
  fireStop();
17631
- console.log(`${TAG25} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
17807
+ console.log(`${TAG27} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
17632
17808
  return c.json({ kind: "miss" });
17633
17809
  }
17634
17810
  const accountId = accounts[0].accountId;
17635
17811
  const { userName } = await resolveUserIdentity(accountId, userId);
17636
17812
  const aboutOwner = await resolveOwnerProfileBlock(accountId, userId);
17637
- console.log(`${TAG25} op=endpoint-validate result=match userId=${userId.slice(0, 8)} aboutOwner=${aboutOwner.ok ? "ok" : `unresolved:${aboutOwner.reason}`}`);
17813
+ console.log(`${TAG27} op=endpoint-validate result=match userId=${userId.slice(0, 8)} aboutOwner=${aboutOwner.ok ? "ok" : `unresolved:${aboutOwner.reason}`}`);
17638
17814
  return c.json({ kind: "match", userId, userName, aboutOwner });
17639
17815
  });
17640
17816
  var identity_default = app33;
@@ -17674,13 +17850,13 @@ var admin_default = app34;
17674
17850
  // app/lib/access-gate.ts
17675
17851
  import neo4j4 from "neo4j-driver";
17676
17852
  import { readFileSync as readFileSync17 } from "fs";
17677
- import { resolve as resolve19 } from "path";
17853
+ import { resolve as resolve20 } from "path";
17678
17854
  import { randomUUID as randomUUID10 } from "crypto";
17679
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
17855
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
17680
17856
  var driver = null;
17681
17857
  function readPassword() {
17682
17858
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
17683
- const passwordFile = resolve19(PLATFORM_ROOT7, "config/.neo4j-password");
17859
+ const passwordFile = resolve20(PLATFORM_ROOT7, "config/.neo4j-password");
17684
17860
  try {
17685
17861
  return readFileSync17(passwordFile, "utf-8").trim();
17686
17862
  } catch {
@@ -17880,7 +18056,7 @@ async function generateNewMagicToken(grantId) {
17880
18056
  }
17881
18057
 
17882
18058
  // server/routes/access/verify-token.ts
17883
- var TAG26 = "[access-verify]";
18059
+ var TAG28 = "[access-verify]";
17884
18060
  var MINT_TAG = "[access-session-mint]";
17885
18061
  var COOKIE_NAME = "__access_session";
17886
18062
  var app35 = new Hono();
@@ -17899,39 +18075,39 @@ app35.post("/", async (c) => {
17899
18075
  }
17900
18076
  const rateMsg = checkAccessRateLimit(ip, agentSlug);
17901
18077
  if (rateMsg) {
17902
- console.error(`${TAG26} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
18078
+ console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
17903
18079
  return c.json({ error: rateMsg }, 429);
17904
18080
  }
17905
18081
  const grant = await findGrantByMagicToken(token);
17906
18082
  if (!grant) {
17907
18083
  recordAccessFailedAttempt(ip, agentSlug);
17908
- console.error(`${TAG26} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
18084
+ console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
17909
18085
  return c.json({ error: "invalid-or-expired-link" }, 401);
17910
18086
  }
17911
18087
  if (grant.agentSlug !== agentSlug) {
17912
18088
  recordAccessFailedAttempt(ip, agentSlug);
17913
18089
  console.error(
17914
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
18090
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
17915
18091
  );
17916
18092
  return c.json({ error: "invalid-or-expired-link" }, 401);
17917
18093
  }
17918
18094
  if (grant.status === "expired" || grant.status === "revoked") {
17919
18095
  recordAccessFailedAttempt(ip, agentSlug);
17920
18096
  console.error(
17921
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
18097
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
17922
18098
  );
17923
18099
  return c.json({ error: "access-no-longer-valid" }, 401);
17924
18100
  }
17925
18101
  if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
17926
18102
  recordAccessFailedAttempt(ip, agentSlug);
17927
18103
  console.error(
17928
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
18104
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
17929
18105
  );
17930
18106
  return c.json({ error: "access-no-longer-valid" }, 401);
17931
18107
  }
17932
18108
  if (!grant.sliceToken) {
17933
18109
  console.error(
17934
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
18110
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
17935
18111
  );
17936
18112
  return c.json({ error: "grant-misconfigured" }, 500);
17937
18113
  }
@@ -17947,12 +18123,12 @@ app35.post("/", async (c) => {
17947
18123
  await consumeMagicTokenAndActivate(grant.grantId);
17948
18124
  } catch (err) {
17949
18125
  console.error(
17950
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
18126
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
17951
18127
  );
17952
18128
  return c.json({ error: "verification-failed" }, 500);
17953
18129
  }
17954
18130
  clearAccessRateLimit(ip, agentSlug);
17955
- console.log(`${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
18131
+ console.log(`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
17956
18132
  console.log(
17957
18133
  `${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
17958
18134
  );
@@ -17970,9 +18146,9 @@ var verify_token_default = app35;
17970
18146
 
17971
18147
  // app/lib/access-email.ts
17972
18148
  import { spawn as spawn2 } from "child_process";
17973
- import { resolve as resolve20 } from "path";
17974
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
17975
- var SEND_SCRIPT = resolve20(
18149
+ import { resolve as resolve21 } from "path";
18150
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
18151
+ var SEND_SCRIPT = resolve21(
17976
18152
  PLATFORM_ROOT8,
17977
18153
  "plugins",
17978
18154
  "email",
@@ -18028,7 +18204,7 @@ async function sendMagicLinkEmail(payload) {
18028
18204
  }
18029
18205
 
18030
18206
  // server/routes/access/request-magic-link.ts
18031
- var TAG27 = "[access-request-link]";
18207
+ var TAG29 = "[access-request-link]";
18032
18208
  var app36 = new Hono();
18033
18209
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
18034
18210
  app36.post("/", async (c) => {
@@ -18045,18 +18221,18 @@ app36.post("/", async (c) => {
18045
18221
  }
18046
18222
  const rateMsg = checkRequestLinkRateLimit(contactValue);
18047
18223
  if (rateMsg) {
18048
- console.error(`${TAG27} contactValue=${maskContact(contactValue)} result=rate-limited`);
18224
+ console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=rate-limited`);
18049
18225
  return c.json({ error: rateMsg }, 429);
18050
18226
  }
18051
18227
  recordRequestLinkAttempt(contactValue);
18052
18228
  const accountId = process.env.ACCOUNT_ID ?? "";
18053
18229
  if (!accountId) {
18054
- console.error(`${TAG27} contactValue=${maskContact(contactValue)} result=no-account-id`);
18230
+ console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=no-account-id`);
18055
18231
  return c.json({ message: VISITOR_MESSAGE }, 200);
18056
18232
  }
18057
18233
  const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
18058
18234
  if (!grant) {
18059
- console.log(`${TAG27} contactValue=${maskContact(contactValue)} result=notfound`);
18235
+ console.log(`${TAG29} contactValue=${maskContact(contactValue)} result=notfound`);
18060
18236
  return c.json({ message: VISITOR_MESSAGE }, 200);
18061
18237
  }
18062
18238
  let token;
@@ -18064,7 +18240,7 @@ app36.post("/", async (c) => {
18064
18240
  token = await generateNewMagicToken(grant.grantId);
18065
18241
  } catch (err) {
18066
18242
  console.error(
18067
- `${TAG27} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
18243
+ `${TAG29} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
18068
18244
  );
18069
18245
  return c.json({ message: VISITOR_MESSAGE }, 200);
18070
18246
  }
@@ -18096,12 +18272,12 @@ app36.post("/", async (c) => {
18096
18272
  });
18097
18273
  if (!sendResult.ok) {
18098
18274
  console.error(
18099
- `${TAG27} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
18275
+ `${TAG29} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
18100
18276
  );
18101
18277
  return c.json({ message: VISITOR_MESSAGE }, 200);
18102
18278
  }
18103
18279
  console.log(
18104
- `${TAG27} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
18280
+ `${TAG29} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
18105
18281
  );
18106
18282
  return c.json({ message: VISITOR_MESSAGE }, 200);
18107
18283
  });
@@ -18115,7 +18291,7 @@ var access_default = app37;
18115
18291
 
18116
18292
  // server/routes/sites.ts
18117
18293
  import { existsSync as existsSync19, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
18118
- import { resolve as resolve21 } from "path";
18294
+ import { resolve as resolve22 } from "path";
18119
18295
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
18120
18296
  var MIME = {
18121
18297
  ".html": "text/html; charset=utf-8",
@@ -18172,8 +18348,8 @@ app38.get("/:rel{.*}", (c) => {
18172
18348
  }
18173
18349
  segments.push(seg);
18174
18350
  }
18175
- const rootDir = resolve21(account.accountDir, "sites");
18176
- let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
18351
+ const rootDir = resolve22(account.accountDir, "sites");
18352
+ let filePath = segments.length === 0 ? rootDir : resolve22(rootDir, ...segments);
18177
18353
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
18178
18354
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
18179
18355
  return c.text("Forbidden", 403);
@@ -18193,7 +18369,7 @@ app38.get("/:rel{.*}", (c) => {
18193
18369
  return c.redirect(target, 301);
18194
18370
  }
18195
18371
  if (stat7?.isDirectory()) {
18196
- filePath = resolve21(filePath, "index.html");
18372
+ filePath = resolve22(filePath, "index.html");
18197
18373
  }
18198
18374
  if (!filePath.startsWith(rootDir + "/")) {
18199
18375
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -18337,9 +18513,9 @@ var cachedAttempted = false;
18337
18513
  function readBrandConfig() {
18338
18514
  if (cachedAttempted) return cached2;
18339
18515
  cachedAttempted = true;
18340
- const platformRoot = process.env.MAXY_PLATFORM_ROOT;
18341
- if (!platformRoot) return null;
18342
- const brandPath = join16(platformRoot, "config", "brand.json");
18516
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
18517
+ if (!platformRoot2) return null;
18518
+ const brandPath = join16(platformRoot2, "config", "brand.json");
18343
18519
  if (!existsSync20(brandPath)) return null;
18344
18520
  try {
18345
18521
  cached2 = JSON.parse(readFileSync20(brandPath, "utf-8"));
@@ -18830,14 +19006,14 @@ async function writeEvent(opts) {
18830
19006
  var visitor_event_default = app41;
18831
19007
 
18832
19008
  // server/routes/session.ts
18833
- import { resolve as resolve22 } from "path";
19009
+ import { resolve as resolve23 } from "path";
18834
19010
  import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
18835
19011
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18836
19012
  function writeBrandingCache(accountId, agentSlug, branding) {
18837
19013
  try {
18838
- const cacheDir = resolve22(MAXY_DIR, "branding-cache", accountId);
19014
+ const cacheDir = resolve23(MAXY_DIR, "branding-cache", accountId);
18839
19015
  mkdirSync5(cacheDir, { recursive: true });
18840
- writeFileSync7(resolve22(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
19016
+ writeFileSync7(resolve23(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
18841
19017
  } catch (err) {
18842
19018
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
18843
19019
  }
@@ -18916,8 +19092,8 @@ app42.post("/", async (c) => {
18916
19092
  }
18917
19093
  let agentConfig = null;
18918
19094
  if (account) {
18919
- const agentDir = resolve22(account.accountDir, "agents", agentSlug);
18920
- if (!existsSync21(agentDir) || !existsSync21(resolve22(agentDir, "config.json"))) {
19095
+ const agentDir = resolve23(account.accountDir, "agents", agentSlug);
19096
+ if (!existsSync21(agentDir) || !existsSync21(resolve23(agentDir, "config.json"))) {
18921
19097
  return c.json({ error: "Agent not found" }, 404);
18922
19098
  }
18923
19099
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -19154,7 +19330,7 @@ function startGraphHealthTimer() {
19154
19330
 
19155
19331
  // app/lib/file-watcher.ts
19156
19332
  import * as fsp2 from "fs/promises";
19157
- import { resolve as resolve23, sep as sep6 } from "path";
19333
+ import { resolve as resolve24, sep as sep6 } from "path";
19158
19334
  var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19159
19335
  var DEFAULT_COALESCE_MS = 500;
19160
19336
  var ROOTS = ["uploads", "accounts"];
@@ -19173,7 +19349,7 @@ async function startFileWatcher(opts = {}) {
19173
19349
  const dropFn = opts.drop ?? dropFileIndex;
19174
19350
  for (const r of ROOTS) {
19175
19351
  try {
19176
- await fsp2.mkdir(resolve23(dataRoot, r), { recursive: true });
19352
+ await fsp2.mkdir(resolve24(dataRoot, r), { recursive: true });
19177
19353
  } catch (err) {
19178
19354
  console.error(
19179
19355
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -19194,7 +19370,7 @@ async function startFileWatcher(opts = {}) {
19194
19370
  timers.set(relativePath, t);
19195
19371
  }
19196
19372
  async function runHook(relativePath, accountId) {
19197
- const absolute = resolve23(dataRoot, relativePath);
19373
+ const absolute = resolve24(dataRoot, relativePath);
19198
19374
  let exists = false;
19199
19375
  try {
19200
19376
  const st = await fsp2.stat(absolute);
@@ -19218,7 +19394,7 @@ async function startFileWatcher(opts = {}) {
19218
19394
  }
19219
19395
  }
19220
19396
  async function watchRoot(rootName) {
19221
- const absRoot = resolve23(dataRoot, rootName);
19397
+ const absRoot = resolve24(dataRoot, rootName);
19222
19398
  try {
19223
19399
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
19224
19400
  for await (const event of iter) {
@@ -19256,7 +19432,7 @@ async function startFileWatcher(opts = {}) {
19256
19432
  }
19257
19433
 
19258
19434
  // app/lib/whatsapp/inbound/claude-bridge.ts
19259
- var TAG28 = "[whatsapp-adaptor]";
19435
+ var TAG30 = "[whatsapp-adaptor]";
19260
19436
  function whatsappTurnTimeoutMs() {
19261
19437
  return Number(process.env.WHATSAPP_PTY_TURN_TIMEOUT_MS ?? String(5 * 6e4));
19262
19438
  }
@@ -19278,7 +19454,7 @@ async function dispatchToClaude(input) {
19278
19454
  await input.reply(result.turnText);
19279
19455
  } catch (err) {
19280
19456
  const m = err instanceof Error ? err.message : String(err);
19281
- console.error(`${TAG28} reject reason=reply-failed senderId=${input.senderId} message=${m}`);
19457
+ console.error(`${TAG30} reject reason=reply-failed senderId=${input.senderId} message=${m}`);
19282
19458
  }
19283
19459
  }
19284
19460
  function startReaper2() {
@@ -19316,7 +19492,7 @@ function broadcastAdminShutdown(reason) {
19316
19492
  // ../lib/entitlement/src/index.ts
19317
19493
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
19318
19494
  import { existsSync as existsSync22, readFileSync as readFileSync21, statSync as statSync9 } from "fs";
19319
- import { resolve as resolve24 } from "path";
19495
+ import { resolve as resolve25 } from "path";
19320
19496
 
19321
19497
  // ../lib/entitlement/src/canonicalize.ts
19322
19498
  function canonicalize(value) {
@@ -19351,7 +19527,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
19351
19527
  var GRACE_DAYS = 7;
19352
19528
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
19353
19529
  function pubkeyPath(brand) {
19354
- return resolve24(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
19530
+ return resolve25(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
19355
19531
  }
19356
19532
  var memo = null;
19357
19533
  function memoKey(mtimeMs, account) {
@@ -19363,7 +19539,7 @@ function resolveEntitlement(brand, account) {
19363
19539
  if (brand.commercialMode !== true) {
19364
19540
  return logResolved(implicitTrust(account), null);
19365
19541
  }
19366
- const entitlementPath = resolve24(brand.configDir, "entitlement.json");
19542
+ const entitlementPath = resolve25(brand.configDir, "entitlement.json");
19367
19543
  if (!existsSync22(entitlementPath)) {
19368
19544
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
19369
19545
  }
@@ -19925,8 +20101,8 @@ app43.get("/agent-assets/:slug/:filename", (c) => {
19925
20101
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
19926
20102
  return c.text("Not found", 404);
19927
20103
  }
19928
- const filePath = resolve25(account.accountDir, "agents", slug, "assets", filename);
19929
- const expectedDir = resolve25(account.accountDir, "agents", slug, "assets");
20104
+ const filePath = resolve26(account.accountDir, "agents", slug, "assets", filename);
20105
+ const expectedDir = resolve26(account.accountDir, "agents", slug, "assets");
19930
20106
  if (!filePath.startsWith(expectedDir + "/")) {
19931
20107
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
19932
20108
  return c.text("Forbidden", 403);
@@ -19955,8 +20131,8 @@ app43.get("/generated/:filename", (c) => {
19955
20131
  console.error(`[generated] serve file=${filename} status=404`);
19956
20132
  return c.text("Not found", 404);
19957
20133
  }
19958
- const filePath = resolve25(account.accountDir, "generated", filename);
19959
- const expectedDir = resolve25(account.accountDir, "generated");
20134
+ const filePath = resolve26(account.accountDir, "generated", filename);
20135
+ const expectedDir = resolve26(account.accountDir, "generated");
19960
20136
  if (!filePath.startsWith(expectedDir + "/")) {
19961
20137
  console.error(`[generated] serve file=${filename} status=403`);
19962
20138
  return c.text("Forbidden", 403);
@@ -20043,7 +20219,7 @@ var clientErrorReporterScript = `<script>
20043
20219
  function cachedHtml(file) {
20044
20220
  let html = htmlCache.get(file);
20045
20221
  if (!html) {
20046
- html = readFileSync22(resolve25(process.cwd(), "public", file), "utf-8");
20222
+ html = readFileSync22(resolve26(process.cwd(), "public", file), "utf-8");
20047
20223
  const productNameEsc = escapeHtml(BRAND.productName);
20048
20224
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
20049
20225
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -20161,7 +20337,7 @@ app43.use("/vnc-popout.html", logViewerFetch);
20161
20337
  app43.get("/vnc-popout.html", (c) => {
20162
20338
  let html = htmlCache.get("vnc-popout.html");
20163
20339
  if (!html) {
20164
- html = readFileSync22(resolve25(process.cwd(), "public", "vnc-popout.html"), "utf-8");
20340
+ html = readFileSync22(resolve26(process.cwd(), "public", "vnc-popout.html"), "utf-8");
20165
20341
  const name = escapeHtml(BRAND.productName);
20166
20342
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
20167
20343
  html = html.replace("</head>", ` ${brandScript}
@@ -20405,7 +20581,7 @@ if (bootAccountConfig?.whatsapp) {
20405
20581
  }
20406
20582
  init({
20407
20583
  configDir: configDirForWhatsApp,
20408
- platformRoot: resolve25(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
20584
+ platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
20409
20585
  accountConfig: bootAccountConfig,
20410
20586
  onMessage: async (msg) => {
20411
20587
  if (msg.text && !msg.isOwnerMirror) {