@rubytech/create-realagent-code 0.1.252 → 0.1.253

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 (21) 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/index.js +10 -0
  9. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  10. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +40 -0
  11. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -0
  12. package/payload/platform/services/claude-session-manager/dist/pty-census.js +125 -0
  13. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -0
  14. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +1 -0
  15. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  16. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +8 -1
  17. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  18. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  19. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +0 -11
  20. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  21. package/payload/server/server.js +439 -317
@@ -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() {
@@ -9073,6 +9073,8 @@ function startFollower(opts) {
9073
9073
  const reader = res.body.getReader();
9074
9074
  const decoder = new TextDecoder("utf8");
9075
9075
  let buffered = "";
9076
+ const fileDelivery = opts.fileDelivery ?? null;
9077
+ let firedFileTools = [];
9076
9078
  while (!abort.signal.aborted) {
9077
9079
  const { value, done } = await reader.read();
9078
9080
  if (done) break;
@@ -9094,6 +9096,7 @@ function startFollower(opts) {
9094
9096
  }
9095
9097
  if (event.type === "user") {
9096
9098
  entry.pendingTurnText = "";
9099
+ firedFileTools = [];
9097
9100
  continue;
9098
9101
  }
9099
9102
  if (event.type !== "assistant") continue;
@@ -9103,6 +9106,15 @@ function startFollower(opts) {
9103
9106
  for (const block of msg.content) {
9104
9107
  if (block?.type === "text" && typeof block.text === "string") {
9105
9108
  entry.pendingTurnText += block.text;
9109
+ } else if (fileDelivery && block?.type === "tool_use" && typeof block.name === "string" && fileDelivery.isFileDeliveryTool(block.name)) {
9110
+ firedFileTools.push(block.name);
9111
+ try {
9112
+ await fileDelivery.onFileToolUse({ toolName: block.name, input: block.input });
9113
+ } catch (err) {
9114
+ console.error(
9115
+ `${tag} file-delivery-error sessionId=${sid} tool=${block.name} message=${err instanceof Error ? err.message : String(err)}`
9116
+ );
9117
+ }
9106
9118
  }
9107
9119
  }
9108
9120
  }
@@ -9112,6 +9124,17 @@ function startFollower(opts) {
9112
9124
  if (flush.trim()) {
9113
9125
  await fanOut(entry.subscribers, flush, opts.onError, tag);
9114
9126
  }
9127
+ if (fileDelivery && firedFileTools.length > 0) {
9128
+ const fired = firedFileTools;
9129
+ firedFileTools = [];
9130
+ try {
9131
+ fileDelivery.onTurnEnd(fired);
9132
+ } catch (err) {
9133
+ console.error(
9134
+ `${tag} file-delivery-error sessionId=${sid} phase=turn-end message=${err instanceof Error ? err.message : String(err)}`
9135
+ );
9136
+ }
9137
+ }
9115
9138
  }
9116
9139
  }
9117
9140
  }
@@ -9138,10 +9161,145 @@ async function fanOut(subscribers, text, onError, tag) {
9138
9161
  );
9139
9162
  }
9140
9163
 
9164
+ // app/lib/whatsapp/outbound/send-document.ts
9165
+ import { realpathSync as realpathSync2 } from "fs";
9166
+ import { readFile, stat as stat2 } from "fs/promises";
9167
+ import { resolve as resolve4, basename } from "path";
9168
+ var TAG15 = "[whatsapp:outbound]";
9169
+ var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
9170
+ function normalizeJid(to) {
9171
+ return to.includes("@") ? to : toWhatsappJid(to);
9172
+ }
9173
+ function documentOutboundAt(to) {
9174
+ return lastDocumentOutboundAt.get(normalizeJid(to));
9175
+ }
9176
+ async function sendWhatsAppDocument(input) {
9177
+ const { to, filePath, caption, accountId, maxyAccountId, platformRoot: platformRoot2 } = input;
9178
+ if (!to || !filePath) {
9179
+ return { ok: false, status: 400, error: "Missing required fields: to, filePath" };
9180
+ }
9181
+ if (!maxyAccountId || !platformRoot2) {
9182
+ return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
9183
+ }
9184
+ const accountDir = resolve4(platformRoot2, "..", "data/accounts", maxyAccountId);
9185
+ let resolvedPath;
9186
+ try {
9187
+ resolvedPath = realpathSync2(filePath);
9188
+ const accountResolved = realpathSync2(accountDir);
9189
+ if (!resolvedPath.startsWith(accountResolved + "/")) {
9190
+ const sanitised = filePath.replace(accountDir, "<account>/");
9191
+ console.error(`${TAG15} document REJECTED path=${sanitised} reason=outside_account_directory`);
9192
+ return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
9193
+ }
9194
+ } catch (err) {
9195
+ const code = err.code;
9196
+ if (code === "ENOENT") {
9197
+ console.error(`${TAG15} document ENOENT path=${filePath}`);
9198
+ return { ok: false, status: 404, error: `File not found: ${filePath}` };
9199
+ }
9200
+ console.error(`${TAG15} document path error: ${String(err)}`);
9201
+ return { ok: false, status: 500, error: String(err) };
9202
+ }
9203
+ const fileStat = await stat2(resolvedPath);
9204
+ if (fileStat.size > MAX_FILE_SIZE_BYTES) {
9205
+ return {
9206
+ ok: false,
9207
+ status: 400,
9208
+ error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
9209
+ };
9210
+ }
9211
+ const filename = basename(resolvedPath);
9212
+ const jid = normalizeJid(to);
9213
+ const sock = getSocket(accountId);
9214
+ if (!sock) {
9215
+ console.error(`${TAG15} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=false reason=not-connected`);
9216
+ return { ok: false, status: 503, error: `WhatsApp account "${accountId}" is not connected` };
9217
+ }
9218
+ const buffer = Buffer.from(await readFile(resolvedPath));
9219
+ const mimetype = detectMimeType(resolvedPath);
9220
+ const result = await sendMediaMessage(
9221
+ sock,
9222
+ to,
9223
+ { type: "document", buffer, mimetype, filename, caption },
9224
+ { accountId }
9225
+ );
9226
+ console.error(
9227
+ `${TAG15} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
9228
+ );
9229
+ if (result.success) {
9230
+ lastDocumentOutboundAt.set(jid, Date.now());
9231
+ return { ok: true, messageId: result.messageId };
9232
+ }
9233
+ return { ok: false, status: 500, error: result.error ?? "send failed" };
9234
+ }
9235
+
9236
+ // app/lib/whatsapp/inbound/file-delivery-bridge.ts
9237
+ var TAG16 = "[whatsapp-adaptor]";
9238
+ var SEND_USER_FILE = "SendUserFile";
9239
+ var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
9240
+ function platformRoot() {
9241
+ return process.env.MAXY_PLATFORM_ROOT || "";
9242
+ }
9243
+ function makeWhatsAppFileDelivery(entry) {
9244
+ let turnStartedAt = null;
9245
+ return {
9246
+ isFileDeliveryTool(toolName) {
9247
+ return toolName === SEND_USER_FILE || toolName === WHATSAPP_SEND_DOCUMENT;
9248
+ },
9249
+ async onFileToolUse(use) {
9250
+ if (turnStartedAt === null) turnStartedAt = Date.now();
9251
+ if (use.toolName !== SEND_USER_FILE) return;
9252
+ const input = use.input ?? {};
9253
+ const files = Array.isArray(input.files) ? input.files.filter((f) => typeof f === "string") : [];
9254
+ const caption = typeof input.caption === "string" ? input.caption : void 0;
9255
+ if (files.length === 0) return;
9256
+ let maxyAccountId;
9257
+ try {
9258
+ maxyAccountId = resolvePlatformAccountId();
9259
+ } catch (err) {
9260
+ console.error(
9261
+ `${TAG16} file-delivery reject reason=account-unresolved sender=${entry.senderId} message=${err instanceof Error ? err.message : String(err)}`
9262
+ );
9263
+ return;
9264
+ }
9265
+ for (let i = 0; i < files.length; i++) {
9266
+ const result = await sendWhatsAppDocument({
9267
+ to: entry.senderId,
9268
+ filePath: files[i],
9269
+ caption: i === 0 ? caption : void 0,
9270
+ accountId: entry.accountId,
9271
+ maxyAccountId,
9272
+ platformRoot: platformRoot()
9273
+ });
9274
+ if (!result.ok) {
9275
+ console.error(
9276
+ `${TAG16} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
9277
+ );
9278
+ }
9279
+ }
9280
+ },
9281
+ onTurnEnd(firedTools) {
9282
+ const startedAt = turnStartedAt ?? 0;
9283
+ turnStartedAt = null;
9284
+ const okAt = documentOutboundAt(entry.senderId);
9285
+ if (okAt !== void 0 && okAt >= startedAt) return;
9286
+ const sid = entry.sessionId.slice(0, 8);
9287
+ for (const tool of firedTools) {
9288
+ console.error(
9289
+ `${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${tool}`
9290
+ );
9291
+ }
9292
+ }
9293
+ };
9294
+ }
9295
+
9141
9296
  // app/lib/channel-pty-bridge/bridge.ts
9142
9297
  function tagFor(channel) {
9143
9298
  return `[${channel}-adaptor]`;
9144
9299
  }
9300
+ function fileDeliveryFor(entry) {
9301
+ return entry.channel === "whatsapp" ? makeWhatsAppFileDelivery(entry) : null;
9302
+ }
9145
9303
  function publicIdleMs() {
9146
9304
  return Number(process.env.CHANNEL_PTY_IDLE_MS ?? String(5 * 6e4));
9147
9305
  }
@@ -9163,6 +9321,7 @@ async function ensureEntry(input) {
9163
9321
  existing.followerAbort = startFollower({
9164
9322
  entry: existing,
9165
9323
  tag,
9324
+ fileDelivery: fileDeliveryFor(existing),
9166
9325
  onClose: () => {
9167
9326
  existing.followerRunning = false;
9168
9327
  }
@@ -9182,7 +9341,7 @@ async function ensureEntry(input) {
9182
9341
  });
9183
9342
  } else {
9184
9343
  console.error(`${tag} route role=${input.role} target=public-spawn senderId=${input.senderId}`);
9185
- const attachmentDir = resolve4(ATTACHMENTS_ROOT, "public", input.senderId);
9344
+ const attachmentDir = resolve5(ATTACHMENTS_ROOT, "public", input.senderId);
9186
9345
  spawned = await managerSpawn({
9187
9346
  senderId: input.senderId,
9188
9347
  role: input.role,
@@ -9223,6 +9382,7 @@ async function ensureEntry(input) {
9223
9382
  entry.followerAbort = startFollower({
9224
9383
  entry,
9225
9384
  tag,
9385
+ fileDelivery: fileDeliveryFor(entry),
9226
9386
  onClose: () => {
9227
9387
  entry.followerRunning = false;
9228
9388
  }
@@ -9308,12 +9468,12 @@ async function dispatchOnce(input) {
9308
9468
  });
9309
9469
  if (!entry) return { error: "spawn-failed" };
9310
9470
  entry.lastInboundAt = Date.now();
9311
- let resolve26;
9471
+ let resolve27;
9312
9472
  const turnPromise = new Promise((r) => {
9313
- resolve26 = r;
9473
+ resolve27 = r;
9314
9474
  });
9315
9475
  const listener = (text) => {
9316
- resolve26(text);
9476
+ resolve27(text);
9317
9477
  };
9318
9478
  entry.subscribers.add(listener);
9319
9479
  const writeOk = await writeInput(entry, input.text);
@@ -9672,19 +9832,18 @@ app2.post("/", async (c) => {
9672
9832
  var chat_default = app2;
9673
9833
 
9674
9834
  // 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";
9835
+ import { join as join5, resolve as resolve7 } from "path";
9836
+ import { readdirSync as readdirSync2, readFileSync as readFileSync6, existsSync as existsSync4 } from "fs";
9678
9837
 
9679
9838
  // app/lib/whatsapp/login.ts
9680
9839
  var import_qrcode = __toESM(require_lib(), 1);
9681
9840
  import { randomUUID as randomUUID6 } from "crypto";
9682
- var TAG15 = "[whatsapp:login]";
9841
+ var TAG17 = "[whatsapp:login]";
9683
9842
  async function renderQrTerminal(qr) {
9684
9843
  try {
9685
9844
  return await import_qrcode.default.toString(qr, { type: "utf8" });
9686
9845
  } catch (err) {
9687
- console.error(`${TAG15} terminal QR render failed: ${String(err)}`);
9846
+ console.error(`${TAG17} terminal QR render failed: ${String(err)}`);
9688
9847
  return void 0;
9689
9848
  }
9690
9849
  }
@@ -9694,7 +9853,7 @@ function closeSocket(sock) {
9694
9853
  try {
9695
9854
  sock.ws?.close?.();
9696
9855
  } catch (err) {
9697
- console.warn(`${TAG15} socket close error during cleanup: ${String(err)}`);
9856
+ console.warn(`${TAG17} socket close error during cleanup: ${String(err)}`);
9698
9857
  }
9699
9858
  }
9700
9859
  function resetActiveLogin(accountId) {
@@ -9717,7 +9876,7 @@ async function loginConnectionLoop(accountId, login) {
9717
9876
  const current = activeLogins.get(accountId);
9718
9877
  if (current?.id === login.id) {
9719
9878
  current.connected = true;
9720
- console.error(`${TAG15} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
9879
+ console.error(`${TAG17} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
9721
9880
  }
9722
9881
  return;
9723
9882
  } catch (err) {
@@ -9727,7 +9886,7 @@ async function loginConnectionLoop(accountId, login) {
9727
9886
  if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
9728
9887
  if (attempt >= LOGIN_MAX_RECONNECTS) {
9729
9888
  console.error(
9730
- `${TAG15} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
9889
+ `${TAG17} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
9731
9890
  );
9732
9891
  current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
9733
9892
  } else {
@@ -9739,7 +9898,7 @@ async function loginConnectionLoop(accountId, login) {
9739
9898
  attempt++;
9740
9899
  const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
9741
9900
  console.error(
9742
- `${TAG15} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
9901
+ `${TAG17} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
9743
9902
  );
9744
9903
  closeSocket(current.sock);
9745
9904
  await new Promise((r) => setTimeout(r, delay));
@@ -9750,7 +9909,7 @@ async function loginConnectionLoop(accountId, login) {
9750
9909
  current.sock = newSock;
9751
9910
  } catch (sockErr) {
9752
9911
  console.error(
9753
- `${TAG15} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
9912
+ `${TAG17} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
9754
9913
  );
9755
9914
  current.error = `Reconnection failed: ${String(sockErr)}`;
9756
9915
  return;
@@ -9764,7 +9923,7 @@ async function startLogin(opts) {
9764
9923
  const hasAuth = await authExists(authDir);
9765
9924
  const selfId = readSelfId(authDir);
9766
9925
  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")
9926
+ `${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
9927
  );
9769
9928
  if (hasAuth && !force) {
9770
9929
  const who = selfId.e164 ?? selfId.jid ?? "unknown";
@@ -9776,7 +9935,7 @@ async function startLogin(opts) {
9776
9935
  await clearAuth(authDir);
9777
9936
  const existing = activeLogins.get(accountId);
9778
9937
  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)`);
9938
+ console.error(`${TAG17} startLogin account=${accountId} guard: returning existing QR (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
9780
9939
  return {
9781
9940
  qrDataUrl: existing.qrDataUrl,
9782
9941
  qrRaw: existing.qr,
@@ -9785,13 +9944,13 @@ async function startLogin(opts) {
9785
9944
  };
9786
9945
  }
9787
9946
  if (existing) {
9788
- console.error(`${TAG15} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
9947
+ console.error(`${TAG17} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
9789
9948
  }
9790
9949
  resetActiveLogin(accountId);
9791
9950
  let resolveQr = null;
9792
9951
  let rejectQr = null;
9793
- const qrPromise = new Promise((resolve26, reject) => {
9794
- resolveQr = resolve26;
9952
+ const qrPromise = new Promise((resolve27, reject) => {
9953
+ resolveQr = resolve27;
9795
9954
  rejectQr = reject;
9796
9955
  });
9797
9956
  const qrTimer = setTimeout(
@@ -9807,14 +9966,14 @@ async function startLogin(opts) {
9807
9966
  onQr: (qr2) => {
9808
9967
  loginQrCount++;
9809
9968
  if (pendingQr) {
9810
- console.error(`${TAG15} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
9969
+ console.error(`${TAG17} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
9811
9970
  return;
9812
9971
  }
9813
9972
  pendingQr = qr2;
9814
9973
  const current = activeLogins.get(accountId);
9815
9974
  if (current && !current.qr) current.qr = qr2;
9816
9975
  clearTimeout(qrTimer);
9817
- console.error(`${TAG15} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
9976
+ console.error(`${TAG17} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
9818
9977
  resolveQr?.(qr2);
9819
9978
  }
9820
9979
  });
@@ -9834,7 +9993,7 @@ async function startLogin(opts) {
9834
9993
  activeLogins.set(accountId, login);
9835
9994
  if (pendingQr && !login.qr) login.qr = pendingQr;
9836
9995
  loginConnectionLoop(accountId, login).catch((err) => {
9837
- console.error(`${TAG15} loginConnectionLoop unexpected error: ${String(err)}`);
9996
+ console.error(`${TAG17} loginConnectionLoop unexpected error: ${String(err)}`);
9838
9997
  const current = activeLogins.get(accountId);
9839
9998
  if (current?.id === login.id) {
9840
9999
  current.error = `Unexpected login error: ${String(err)}`;
@@ -9860,7 +10019,7 @@ async function waitForLogin(opts) {
9860
10019
  const { accountId, timeoutMs = 6e4 } = opts;
9861
10020
  const login = activeLogins.get(accountId);
9862
10021
  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")
10022
+ `${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
10023
  );
9865
10024
  if (!login) {
9866
10025
  return { connected: false, message: "No active WhatsApp login in progress." };
@@ -9873,7 +10032,7 @@ async function waitForLogin(opts) {
9873
10032
  while (Date.now() < deadline) {
9874
10033
  if (login.connected) {
9875
10034
  const selfId = readSelfId(login.authDir);
9876
- console.error(`${TAG15} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
10035
+ console.error(`${TAG17} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
9877
10036
  const sock = login.sock;
9878
10037
  const authDir = login.authDir;
9879
10038
  activeLogins.delete(accountId);
@@ -9893,17 +10052,17 @@ async function waitForLogin(opts) {
9893
10052
  await new Promise((r) => setTimeout(r, 1e3));
9894
10053
  }
9895
10054
  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`);
10055
+ console.error(`${TAG17} waitForLogin timeout account=${accountId} elapsed=${elapsed}s \u2014 cleaning up active login`);
9897
10056
  resetActiveLogin(accountId);
9898
10057
  return { connected: false, message: "Login timed out. Try generating a new QR." };
9899
10058
  }
9900
10059
 
9901
10060
  // app/lib/whatsapp/config-persist.ts
9902
10061
  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]";
10062
+ import { resolve as resolve6, join as join4 } from "path";
10063
+ var TAG18 = "[whatsapp:config]";
9905
10064
  function configPath(accountDir) {
9906
- return resolve5(accountDir, "account.json");
10065
+ return resolve6(accountDir, "account.json");
9907
10066
  }
9908
10067
  function readConfig(accountDir) {
9909
10068
  const path2 = configPath(accountDir);
@@ -9918,9 +10077,9 @@ function reloadManagerConfig(accountDir) {
9918
10077
  try {
9919
10078
  const config = readConfig(accountDir);
9920
10079
  reloadConfig(config);
9921
- console.error(`${TAG16} reloaded manager config`);
10080
+ console.error(`${TAG18} reloaded manager config`);
9922
10081
  } catch (err) {
9923
- console.error(`${TAG16} manager config reload failed: ${String(err)}`);
10082
+ console.error(`${TAG18} manager config reload failed: ${String(err)}`);
9924
10083
  }
9925
10084
  }
9926
10085
  var E164_PATTERN = /^\+\d{7,15}$/;
@@ -9946,25 +10105,25 @@ function persistAfterPairing(accountDir, accountId, selfPhone) {
9946
10105
  const adminPhones = wa.adminPhones;
9947
10106
  if (!adminPhones.includes(normalized)) {
9948
10107
  adminPhones.push(normalized);
9949
- console.error(`${TAG16} added selfPhone=${normalized} to adminPhones`);
10108
+ console.error(`${TAG18} added selfPhone=${normalized} to adminPhones`);
9950
10109
  }
9951
10110
  } else {
9952
- console.error(`${TAG16} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
10111
+ console.error(`${TAG18} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
9953
10112
  }
9954
10113
  const parsed = WhatsAppConfigSchema.safeParse(wa);
9955
10114
  if (!parsed.success) {
9956
10115
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
9957
- console.error(`${TAG16} validation failed after pairing: ${msg}`);
10116
+ console.error(`${TAG18} validation failed after pairing: ${msg}`);
9958
10117
  return { ok: false, error: `Validation failed: ${msg}` };
9959
10118
  }
9960
10119
  config.whatsapp = parsed.data;
9961
10120
  writeConfig(accountDir, config);
9962
- console.error(`${TAG16} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
10121
+ console.error(`${TAG18} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
9963
10122
  reloadManagerConfig(accountDir);
9964
10123
  return { ok: true };
9965
10124
  } catch (err) {
9966
10125
  const msg = err instanceof Error ? err.message : String(err);
9967
- console.error(`${TAG16} persist failed account=${accountId}: ${msg}`);
10126
+ console.error(`${TAG18} persist failed account=${accountId}: ${msg}`);
9968
10127
  return { ok: false, error: msg };
9969
10128
  }
9970
10129
  }
@@ -9994,12 +10153,12 @@ function addAdminPhone(accountDir, phone) {
9994
10153
  }
9995
10154
  config.whatsapp = parsed.data;
9996
10155
  writeConfig(accountDir, config);
9997
- console.error(`${TAG16} added admin phone=${normalized}`);
10156
+ console.error(`${TAG18} added admin phone=${normalized}`);
9998
10157
  reloadManagerConfig(accountDir);
9999
10158
  return { ok: true, message: `Added ${normalized} as admin phone. Messages from this number will route to the admin agent.` };
10000
10159
  } catch (err) {
10001
10160
  const msg = err instanceof Error ? err.message : String(err);
10002
- console.error(`${TAG16} addAdminPhone failed: ${msg}`);
10161
+ console.error(`${TAG18} addAdminPhone failed: ${msg}`);
10003
10162
  return { ok: false, error: msg };
10004
10163
  }
10005
10164
  }
@@ -10027,12 +10186,12 @@ function removeAdminPhone(accountDir, phone) {
10027
10186
  }
10028
10187
  config.whatsapp = parsed.data;
10029
10188
  writeConfig(accountDir, config);
10030
- console.error(`${TAG16} removed admin phone=${normalized}`);
10189
+ console.error(`${TAG18} removed admin phone=${normalized}`);
10031
10190
  reloadManagerConfig(accountDir);
10032
10191
  return { ok: true, message: `Removed ${normalized} from admin phones. Messages from this number will now route to the public agent.` };
10033
10192
  } catch (err) {
10034
10193
  const msg = err instanceof Error ? err.message : String(err);
10035
- console.error(`${TAG16} removeAdminPhone failed: ${msg}`);
10194
+ console.error(`${TAG18} removeAdminPhone failed: ${msg}`);
10036
10195
  return { ok: false, error: msg };
10037
10196
  }
10038
10197
  }
@@ -10070,12 +10229,12 @@ function setPublicAgent(accountDir, slug) {
10070
10229
  }
10071
10230
  config.whatsapp = parsed.data;
10072
10231
  writeConfig(accountDir, config);
10073
- console.error(`${TAG16} publicAgent set to ${trimmed}`);
10232
+ console.error(`${TAG18} publicAgent set to ${trimmed}`);
10074
10233
  reloadManagerConfig(accountDir);
10075
10234
  return { ok: true, message: `Public agent set to "${trimmed}". WhatsApp messages from non-admin phones will be handled by this agent.` };
10076
10235
  } catch (err) {
10077
10236
  const msg = err instanceof Error ? err.message : String(err);
10078
- console.error(`${TAG16} setPublicAgent failed: ${msg}`);
10237
+ console.error(`${TAG18} setPublicAgent failed: ${msg}`);
10079
10238
  return { ok: false, error: msg };
10080
10239
  }
10081
10240
  }
@@ -10139,12 +10298,12 @@ function setGroupPublicAgent(accountDir, accountId, groupJid, slug) {
10139
10298
  }
10140
10299
  config.whatsapp = parsed.data;
10141
10300
  writeConfig(accountDir, config);
10142
- console.error(`${TAG16} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
10301
+ console.error(`${TAG18} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
10143
10302
  reloadManagerConfig(accountDir);
10144
10303
  return { ok: true, message: `Per-group public agent set to "${trimmedSlug}" for group ${trimmedGroup}.` };
10145
10304
  } catch (err) {
10146
10305
  const msg = err instanceof Error ? err.message : String(err);
10147
- console.error(`${TAG16} setGroupPublicAgent failed: ${msg}`);
10306
+ console.error(`${TAG18} setGroupPublicAgent failed: ${msg}`);
10148
10307
  return { ok: false, error: msg };
10149
10308
  }
10150
10309
  }
@@ -10171,12 +10330,12 @@ function unsetGroupPublicAgent(accountDir, accountId, groupJid) {
10171
10330
  }
10172
10331
  config.whatsapp = parsed.data;
10173
10332
  writeConfig(accountDir, config);
10174
- console.error(`${TAG16} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
10333
+ console.error(`${TAG18} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
10175
10334
  reloadManagerConfig(accountDir);
10176
10335
  return { ok: true, message: `Per-group public agent override removed for group ${trimmedGroup}.` };
10177
10336
  } catch (err) {
10178
10337
  const msg = err instanceof Error ? err.message : String(err);
10179
- console.error(`${TAG16} unsetGroupPublicAgent failed: ${msg}`);
10338
+ console.error(`${TAG18} unsetGroupPublicAgent failed: ${msg}`);
10180
10339
  return { ok: false, error: msg };
10181
10340
  }
10182
10341
  }
@@ -10197,17 +10356,17 @@ function updateConfig(accountDir, fields) {
10197
10356
  const parsed = WhatsAppConfigSchema.safeParse(wa);
10198
10357
  if (!parsed.success) {
10199
10358
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
10200
- console.error(`${TAG16} update validation failed: ${msg}`);
10359
+ console.error(`${TAG18} update validation failed: ${msg}`);
10201
10360
  return { ok: false, error: `Validation failed: ${msg}` };
10202
10361
  }
10203
10362
  config.whatsapp = parsed.data;
10204
10363
  writeConfig(accountDir, config);
10205
- console.error(`${TAG16} updated fields=[${fieldNames.join(",")}]`);
10364
+ console.error(`${TAG18} updated fields=[${fieldNames.join(",")}]`);
10206
10365
  reloadManagerConfig(accountDir);
10207
10366
  return { ok: true, message: `Updated WhatsApp config: ${fieldNames.join(", ")}.` };
10208
10367
  } catch (err) {
10209
10368
  const msg = err instanceof Error ? err.message : String(err);
10210
- console.error(`${TAG16} updateConfig failed: ${msg}`);
10369
+ console.error(`${TAG18} updateConfig failed: ${msg}`);
10211
10370
  return { ok: false, error: msg };
10212
10371
  }
10213
10372
  }
@@ -10333,17 +10492,17 @@ function serializeWhatsAppSchema() {
10333
10492
  }
10334
10493
 
10335
10494
  // server/routes/whatsapp.ts
10336
- var TAG17 = "[whatsapp:api]";
10495
+ var TAG19 = "[whatsapp:api]";
10337
10496
  var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT || "";
10338
10497
  var app3 = new Hono();
10339
10498
  app3.get("/status", (c) => {
10340
10499
  try {
10341
10500
  const status = getStatus();
10342
10501
  const summary = status.map((a) => `${a.accountId}:${a.connected ? "up" : "down"}`).join(", ");
10343
- console.error(`${TAG17} status accounts=${status.length} [${summary}]`);
10502
+ console.error(`${TAG19} status accounts=${status.length} [${summary}]`);
10344
10503
  return c.json({ accounts: status });
10345
10504
  } catch (err) {
10346
- console.error(`${TAG17} status error: ${String(err)}`);
10505
+ console.error(`${TAG19} status error: ${String(err)}`);
10347
10506
  return c.json({ error: String(err) }, 500);
10348
10507
  }
10349
10508
  });
@@ -10354,10 +10513,10 @@ app3.post("/login/start", async (c) => {
10354
10513
  const force = body.force ?? false;
10355
10514
  const authDir = join5(MAXY_DIR, "credentials", "whatsapp", accountId);
10356
10515
  const result = await startLogin({ accountId, authDir, force });
10357
- console.error(`${TAG17} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
10516
+ console.error(`${TAG19} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
10358
10517
  return c.json(result);
10359
10518
  } catch (err) {
10360
- console.error(`${TAG17} login/start error: ${String(err)}`);
10519
+ console.error(`${TAG19} login/start error: ${String(err)}`);
10361
10520
  return c.json({ error: String(err) }, 500);
10362
10521
  }
10363
10522
  });
@@ -10372,7 +10531,7 @@ app3.post("/login/wait", async (c) => {
10372
10531
  try {
10373
10532
  await registerLoginSocket(accountId, result.sock, result.authDir);
10374
10533
  } catch (regErr) {
10375
- console.error(`${TAG17} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
10534
+ console.error(`${TAG19} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
10376
10535
  }
10377
10536
  try {
10378
10537
  const account = resolveAccount();
@@ -10380,16 +10539,16 @@ app3.post("/login/wait", async (c) => {
10380
10539
  const persistResult = persistAfterPairing(account.accountDir, accountId, result.selfPhone ?? null);
10381
10540
  configPersisted = persistResult.ok;
10382
10541
  if (!persistResult.ok) {
10383
- console.error(`${TAG17} config persist failed account=${accountId}: ${persistResult.error}`);
10542
+ console.error(`${TAG19} config persist failed account=${accountId}: ${persistResult.error}`);
10384
10543
  }
10385
10544
  } else {
10386
- console.error(`${TAG17} config persist skipped \u2014 no account resolved`);
10545
+ console.error(`${TAG19} config persist skipped \u2014 no account resolved`);
10387
10546
  }
10388
10547
  } catch (persistErr) {
10389
- console.error(`${TAG17} config persist error account=${accountId}: ${String(persistErr)}`);
10548
+ console.error(`${TAG19} config persist error account=${accountId}: ${String(persistErr)}`);
10390
10549
  }
10391
10550
  }
10392
- console.error(`${TAG17} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
10551
+ console.error(`${TAG19} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
10393
10552
  return c.json({
10394
10553
  connected: result.connected,
10395
10554
  message: result.message,
@@ -10397,7 +10556,7 @@ app3.post("/login/wait", async (c) => {
10397
10556
  configPersisted
10398
10557
  });
10399
10558
  } catch (err) {
10400
- console.error(`${TAG17} login/wait error: ${String(err)}`);
10559
+ console.error(`${TAG19} login/wait error: ${String(err)}`);
10401
10560
  return c.json({ error: String(err) }, 500);
10402
10561
  }
10403
10562
  });
@@ -10408,7 +10567,7 @@ app3.post("/disconnect", async (c) => {
10408
10567
  await stopConnection(accountId);
10409
10568
  return c.json({ disconnected: true, accountId });
10410
10569
  } catch (err) {
10411
- console.error(`${TAG17} disconnect error: ${String(err)}`);
10570
+ console.error(`${TAG19} disconnect error: ${String(err)}`);
10412
10571
  return c.json({ error: String(err) }, 500);
10413
10572
  }
10414
10573
  });
@@ -10419,7 +10578,7 @@ app3.post("/reconnect", async (c) => {
10419
10578
  await startConnection(accountId);
10420
10579
  return c.json({ reconnecting: true, accountId });
10421
10580
  } catch (err) {
10422
- console.error(`${TAG17} reconnect error: ${String(err)}`);
10581
+ console.error(`${TAG19} reconnect error: ${String(err)}`);
10423
10582
  return c.json({ error: String(err) }, 500);
10424
10583
  }
10425
10584
  });
@@ -10438,7 +10597,7 @@ app3.post("/send", async (c) => {
10438
10597
  const result = await sendTextMessage(sock, to, text, { accountId });
10439
10598
  return c.json(result);
10440
10599
  } catch (err) {
10441
- console.error(`${TAG17} send error: ${String(err)}`);
10600
+ console.error(`${TAG19} send error: ${String(err)}`);
10442
10601
  return c.json({ error: String(err) }, 500);
10443
10602
  }
10444
10603
  });
@@ -10459,7 +10618,7 @@ app3.post("/config", async (c) => {
10459
10618
  return c.json({ ok: false, error: 'Missing required field "phone" (E.164 format, e.g. +441234567890).' }, 400);
10460
10619
  }
10461
10620
  const result = addAdminPhone(account.accountDir, phone);
10462
- console.error(`${TAG17} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
10621
+ console.error(`${TAG19} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
10463
10622
  return c.json(result, result.ok ? 200 : 400);
10464
10623
  }
10465
10624
  case "remove-admin-phone": {
@@ -10467,12 +10626,12 @@ app3.post("/config", async (c) => {
10467
10626
  return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
10468
10627
  }
10469
10628
  const result = removeAdminPhone(account.accountDir, phone);
10470
- console.error(`${TAG17} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
10629
+ console.error(`${TAG19} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
10471
10630
  return c.json(result, result.ok ? 200 : 400);
10472
10631
  }
10473
10632
  case "list-admin-phones": {
10474
10633
  const phones = readAdminPhones(account.accountDir);
10475
- console.error(`${TAG17} config action=list-admin-phones count=${phones.length}`);
10634
+ console.error(`${TAG19} config action=list-admin-phones count=${phones.length}`);
10476
10635
  return c.json({ ok: true, phones });
10477
10636
  }
10478
10637
  case "set-public-agent": {
@@ -10480,14 +10639,14 @@ app3.post("/config", async (c) => {
10480
10639
  return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
10481
10640
  }
10482
10641
  const result = setPublicAgent(account.accountDir, slug);
10483
- console.error(`${TAG17} config action=set-public-agent slug=${slug} ok=${result.ok}`);
10642
+ console.error(`${TAG19} config action=set-public-agent slug=${slug} ok=${result.ok}`);
10484
10643
  return c.json(result, result.ok ? 200 : 400);
10485
10644
  }
10486
10645
  case "get-public-agent": {
10487
10646
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10488
10647
  const targetGroup = typeof groupJid === "string" && groupJid.trim() ? groupJid.trim() : void 0;
10489
10648
  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"}`);
10649
+ console.error(`${TAG19} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
10491
10650
  return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
10492
10651
  }
10493
10652
  case "set-group-public-agent": {
@@ -10499,7 +10658,7 @@ app3.post("/config", async (c) => {
10499
10658
  }
10500
10659
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10501
10660
  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}`);
10661
+ console.error(`${TAG19} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
10503
10662
  return c.json(result, result.ok ? 200 : 400);
10504
10663
  }
10505
10664
  case "unset-group-public-agent": {
@@ -10508,43 +10667,43 @@ app3.post("/config", async (c) => {
10508
10667
  }
10509
10668
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
10510
10669
  const result = unsetGroupPublicAgent(account.accountDir, targetAccount, groupJid);
10511
- console.error(`${TAG17} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
10670
+ console.error(`${TAG19} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
10512
10671
  return c.json(result, result.ok ? 200 : 400);
10513
10672
  }
10514
10673
  case "list-public-agents": {
10515
- const agentsDir = resolve6(account.accountDir, "agents");
10674
+ const agentsDir = resolve7(account.accountDir, "agents");
10516
10675
  const agents = [];
10517
10676
  if (existsSync4(agentsDir)) {
10518
10677
  try {
10519
10678
  const entries = readdirSync2(agentsDir, { withFileTypes: true });
10520
10679
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
10521
10680
  if (!entry.isDirectory() || entry.name === "admin") continue;
10522
- const configPath2 = resolve6(agentsDir, entry.name, "config.json");
10681
+ const configPath2 = resolve7(agentsDir, entry.name, "config.json");
10523
10682
  if (!existsSync4(configPath2)) continue;
10524
10683
  try {
10525
10684
  const config = JSON.parse(readFileSync6(configPath2, "utf-8"));
10526
10685
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
10527
10686
  } catch {
10528
- console.error(`${TAG17} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
10687
+ console.error(`${TAG19} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
10529
10688
  }
10530
10689
  }
10531
10690
  } catch (err) {
10532
- console.error(`${TAG17} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
10691
+ console.error(`${TAG19} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
10533
10692
  }
10534
10693
  }
10535
- console.error(`${TAG17} config action=list-public-agents count=${agents.length}`);
10694
+ console.error(`${TAG19} config action=list-public-agents count=${agents.length}`);
10536
10695
  return c.json({ ok: true, agents });
10537
10696
  }
10538
10697
  case "schema": {
10539
10698
  const text = serializeWhatsAppSchema();
10540
- console.error(`${TAG17} config action=schema`);
10699
+ console.error(`${TAG19} config action=schema`);
10541
10700
  return c.json({ ok: true, text });
10542
10701
  }
10543
10702
  case "list-groups": {
10544
10703
  const groupAccountId = accountId ?? "default";
10545
10704
  const sock = getSocket(groupAccountId);
10546
10705
  if (!sock) {
10547
- console.error(`${TAG17} config action=list-groups error="not connected" accountId=${groupAccountId}`);
10706
+ console.error(`${TAG19} config action=list-groups error="not connected" accountId=${groupAccountId}`);
10548
10707
  return c.json({ ok: false, error: `WhatsApp account "${groupAccountId}" is not connected. Connect first, then retry.` });
10549
10708
  }
10550
10709
  try {
@@ -10554,10 +10713,10 @@ app3.post("/config", async (c) => {
10554
10713
  name: g.subject ?? g.id,
10555
10714
  participantCount: Array.isArray(g.participants) ? g.participants.length : 0
10556
10715
  }));
10557
- console.error(`${TAG17} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
10716
+ console.error(`${TAG19} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
10558
10717
  return c.json({ ok: true, groups });
10559
10718
  } catch (err) {
10560
- console.error(`${TAG17} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
10719
+ console.error(`${TAG19} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
10561
10720
  return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
10562
10721
  }
10563
10722
  }
@@ -10567,12 +10726,12 @@ app3.post("/config", async (c) => {
10567
10726
  }
10568
10727
  const result = updateConfig(account.accountDir, fields);
10569
10728
  const fieldNames = Object.keys(fields);
10570
- console.error(`${TAG17} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
10729
+ console.error(`${TAG19} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
10571
10730
  return c.json(result, result.ok ? 200 : 400);
10572
10731
  }
10573
10732
  case "get-config": {
10574
10733
  const waConfig = getConfig(account.accountDir);
10575
- console.error(`${TAG17} config action=get-config`);
10734
+ console.error(`${TAG19} config action=get-config`);
10576
10735
  return c.json({ ok: true, config: waConfig });
10577
10736
  }
10578
10737
  default:
@@ -10582,7 +10741,7 @@ app3.post("/config", async (c) => {
10582
10741
  );
10583
10742
  }
10584
10743
  } catch (err) {
10585
- console.error(`${TAG17} config error: ${String(err)}`);
10744
+ console.error(`${TAG19} config error: ${String(err)}`);
10586
10745
  return c.json({ ok: false, error: String(err) }, 500);
10587
10746
  }
10588
10747
  });
@@ -10591,55 +10750,18 @@ app3.post("/send-document", async (c) => {
10591
10750
  const body = await c.req.json();
10592
10751
  const { to, filePath, caption, maxyAccountId } = body;
10593
10752
  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);
10753
+ const result = await sendWhatsAppDocument({
10754
+ to,
10755
+ filePath,
10756
+ caption,
10757
+ accountId,
10758
+ maxyAccountId,
10759
+ platformRoot: PLATFORM_ROOT4
10760
+ });
10761
+ if (!result.ok) return c.json({ error: result.error }, result.status);
10762
+ return c.json({ success: true, messageId: result.messageId });
10641
10763
  } catch (err) {
10642
- console.error(`${TAG17} send-document error: ${String(err)}`);
10764
+ console.error(`${TAG19} send-document error: ${String(err)}`);
10643
10765
  return c.json({ error: String(err) }, 500);
10644
10766
  }
10645
10767
  });
@@ -10649,11 +10771,11 @@ app3.get("/activity", (c) => {
10649
10771
  const result = getChannelActivity(accountId);
10650
10772
  const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
10651
10773
  console.error(
10652
- `${TAG17} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
10774
+ `${TAG19} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
10653
10775
  );
10654
10776
  return c.json(result);
10655
10777
  } catch (err) {
10656
- console.error(`${TAG17} activity error: ${String(err)}`);
10778
+ console.error(`${TAG19} activity error: ${String(err)}`);
10657
10779
  return c.json({ error: String(err) }, 500);
10658
10780
  }
10659
10781
  });
@@ -10672,10 +10794,10 @@ app3.get("/conversations", (c) => {
10672
10794
  };
10673
10795
  });
10674
10796
  conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
10675
- console.error(`${TAG17} conversations account=${accountId} count=${conversations.length}`);
10797
+ console.error(`${TAG19} conversations account=${accountId} count=${conversations.length}`);
10676
10798
  return c.json({ conversations });
10677
10799
  } catch (err) {
10678
- console.error(`${TAG17} conversations error: ${String(err)}`);
10800
+ console.error(`${TAG19} conversations error: ${String(err)}`);
10679
10801
  return c.json({ error: String(err) }, 500);
10680
10802
  }
10681
10803
  });
@@ -10690,10 +10812,10 @@ app3.get("/messages", (c) => {
10690
10812
  const limit = limitParam ? parseInt(limitParam, 10) : void 0;
10691
10813
  const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
10692
10814
  const messages = getMessages(accountId, jid, effectiveLimit);
10693
- console.error(`${TAG17} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
10815
+ console.error(`${TAG19} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
10694
10816
  return c.json({ messages });
10695
10817
  } catch (err) {
10696
- console.error(`${TAG17} messages error: ${String(err)}`);
10818
+ console.error(`${TAG19} messages error: ${String(err)}`);
10697
10819
  return c.json({ error: String(err) }, 500);
10698
10820
  }
10699
10821
  });
@@ -10774,7 +10896,7 @@ app3.get("/conversation-graph-state", async (c) => {
10774
10896
  }
10775
10897
  } catch (err) {
10776
10898
  const msg = err instanceof Error ? err.message : String(err);
10777
- console.error(`${TAG17} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
10899
+ console.error(`${TAG19} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
10778
10900
  return c.json({ error: `Graph query failed: ${msg}`, cacheKey, cypher: cypher.trim() }, 500);
10779
10901
  }
10780
10902
  const ms = Date.now() - t0;
@@ -10787,7 +10909,7 @@ app3.get("/conversation-graph-state", async (c) => {
10787
10909
  ms
10788
10910
  });
10789
10911
  } catch (err) {
10790
- console.error(`${TAG17} conversation-graph-state error: ${String(err)}`);
10912
+ console.error(`${TAG19} conversation-graph-state error: ${String(err)}`);
10791
10913
  return c.json({ error: String(err) }, 500);
10792
10914
  }
10793
10915
  });
@@ -10799,12 +10921,12 @@ app3.get("/group-info", async (c) => {
10799
10921
  return c.json({ error: "Missing required parameter: jid" }, 400);
10800
10922
  }
10801
10923
  if (!isGroupJid(jid)) {
10802
- console.error(`${TAG17} group-info error="not a group JID" jid=${jid} account=${accountId}`);
10924
+ console.error(`${TAG19} group-info error="not a group JID" jid=${jid} account=${accountId}`);
10803
10925
  return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
10804
10926
  }
10805
10927
  const sock = getSocket(accountId);
10806
10928
  if (!sock) {
10807
- console.error(`${TAG17} group-info error="not connected" account=${accountId}`);
10929
+ console.error(`${TAG19} group-info error="not connected" account=${accountId}`);
10808
10930
  return c.json({ error: `WhatsApp account "${accountId}" is not connected. Connect first, then retry.` }, 400);
10809
10931
  }
10810
10932
  const meta = await sock.groupMetadata(jid);
@@ -10817,10 +10939,10 @@ app3.get("/group-info", async (c) => {
10817
10939
  participantCount: meta.participants.length,
10818
10940
  participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
10819
10941
  };
10820
- console.error(`${TAG17} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
10942
+ console.error(`${TAG19} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
10821
10943
  return c.json(result);
10822
10944
  } catch (err) {
10823
- console.error(`${TAG17} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
10945
+ console.error(`${TAG19} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
10824
10946
  return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
10825
10947
  }
10826
10948
  });
@@ -11605,7 +11727,7 @@ var session_default = app6;
11605
11727
 
11606
11728
  // server/routes/admin/logs.ts
11607
11729
  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";
11730
+ import { resolve as resolve8, basename as basename2 } from "path";
11609
11731
 
11610
11732
  // app/lib/logs-read-resolve.ts
11611
11733
  import { existsSync as existsSync9 } from "fs";
@@ -11632,7 +11754,7 @@ app7.get("/", async (c) => {
11632
11754
  const cacheKeyParam = c.req.query("cacheKey");
11633
11755
  const download = c.req.query("download") === "1";
11634
11756
  const account = resolveAccount();
11635
- const accountLogDir = account ? resolve7(account.accountDir, "logs") : null;
11757
+ const accountLogDir = account ? resolve8(account.accountDir, "logs") : null;
11636
11758
  const logDirs = [];
11637
11759
  if (accountLogDir) logDirs.push(accountLogDir);
11638
11760
  logDirs.push(LOG_DIR);
@@ -11640,7 +11762,7 @@ app7.get("/", async (c) => {
11640
11762
  const safe = basename2(fileParam);
11641
11763
  const searched = [];
11642
11764
  for (const dir of logDirs) {
11643
- const filePath = resolve7(dir, safe);
11765
+ const filePath = resolve8(dir, safe);
11644
11766
  searched.push(filePath);
11645
11767
  try {
11646
11768
  const buffer = readFileSync10(filePath);
@@ -11752,10 +11874,10 @@ app7.get("/", async (c) => {
11752
11874
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
11753
11875
  continue;
11754
11876
  }
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 }) => {
11877
+ 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
11878
  seen.add(name);
11757
11879
  try {
11758
- const content = readFileSync10(resolve7(dir, name));
11880
+ const content = readFileSync10(resolve8(dir, name));
11759
11881
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
11760
11882
  logs[name] = tail.trim() || "(empty)";
11761
11883
  } catch (err) {
@@ -11795,7 +11917,7 @@ var claude_info_default = app8;
11795
11917
  // server/routes/admin/attachment.ts
11796
11918
  import { readFile as readFile2, readdir } from "fs/promises";
11797
11919
  import { existsSync as existsSync11 } from "fs";
11798
- import { resolve as resolve8 } from "path";
11920
+ import { resolve as resolve9 } from "path";
11799
11921
  var app9 = new Hono();
11800
11922
  app9.get("/:attachmentId", requireAdminSession, async (c) => {
11801
11923
  const attachmentId = c.req.param("attachmentId");
@@ -11807,11 +11929,11 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11807
11929
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
11808
11930
  return new Response("Not found", { status: 404 });
11809
11931
  }
11810
- const dir = resolve8(ATTACHMENTS_ROOT, accountId, attachmentId);
11932
+ const dir = resolve9(ATTACHMENTS_ROOT, accountId, attachmentId);
11811
11933
  if (!existsSync11(dir)) {
11812
11934
  return new Response("Not found", { status: 404 });
11813
11935
  }
11814
- const metaPath = resolve8(dir, `${attachmentId}.meta.json`);
11936
+ const metaPath = resolve9(dir, `${attachmentId}.meta.json`);
11815
11937
  if (!existsSync11(metaPath)) {
11816
11938
  return new Response("Not found", { status: 404 });
11817
11939
  }
@@ -11826,7 +11948,7 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11826
11948
  if (!dataFile) {
11827
11949
  return new Response("Not found", { status: 404 });
11828
11950
  }
11829
- const filePath = resolve8(dir, dataFile);
11951
+ const filePath = resolve9(dir, dataFile);
11830
11952
  const buffer = await readFile2(filePath);
11831
11953
  return new Response(new Uint8Array(buffer), {
11832
11954
  headers: {
@@ -11839,13 +11961,13 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
11839
11961
  var attachment_default = app9;
11840
11962
 
11841
11963
  // server/routes/admin/agents.ts
11842
- import { resolve as resolve9 } from "path";
11964
+ import { resolve as resolve10 } from "path";
11843
11965
  import { readdirSync as readdirSync6, readFileSync as readFileSync11, existsSync as existsSync12, rmSync } from "fs";
11844
11966
  var app10 = new Hono();
11845
11967
  app10.get("/", (c) => {
11846
11968
  const account = resolveAccount();
11847
11969
  if (!account) return c.json({ agents: [] });
11848
- const agentsDir = resolve9(account.accountDir, "agents");
11970
+ const agentsDir = resolve10(account.accountDir, "agents");
11849
11971
  if (!existsSync12(agentsDir)) return c.json({ agents: [] });
11850
11972
  const agents = [];
11851
11973
  try {
@@ -11853,7 +11975,7 @@ app10.get("/", (c) => {
11853
11975
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
11854
11976
  if (!entry.isDirectory()) continue;
11855
11977
  if (entry.name === "admin") continue;
11856
- const configPath2 = resolve9(agentsDir, entry.name, "config.json");
11978
+ const configPath2 = resolve10(agentsDir, entry.name, "config.json");
11857
11979
  if (!existsSync12(configPath2)) continue;
11858
11980
  try {
11859
11981
  const config = JSON.parse(readFileSync11(configPath2, "utf-8"));
@@ -11882,7 +12004,7 @@ app10.delete("/:slug", async (c) => {
11882
12004
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
11883
12005
  return c.json({ error: "Invalid agent slug" }, 400);
11884
12006
  }
11885
- const agentDir = resolve9(account.accountDir, "agents", slug);
12007
+ const agentDir = resolve10(account.accountDir, "agents", slug);
11886
12008
  if (!existsSync12(agentDir)) {
11887
12009
  return c.json({ error: "Agent not found" }, 404);
11888
12010
  }
@@ -11912,7 +12034,7 @@ app10.post("/:slug/project", async (c) => {
11912
12034
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
11913
12035
  return c.json({ error: "Invalid agent slug" }, 400);
11914
12036
  }
11915
- const agentDir = resolve9(account.accountDir, "agents", slug);
12037
+ const agentDir = resolve10(account.accountDir, "agents", slug);
11916
12038
  if (!existsSync12(agentDir)) {
11917
12039
  return c.json({ error: "Agent not found on disk" }, 404);
11918
12040
  }
@@ -12617,7 +12739,7 @@ var sessions_default = app11;
12617
12739
 
12618
12740
  // app/lib/claude-agent/spawn-context.ts
12619
12741
  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";
12742
+ import { dirname as dirname2, resolve as resolve11, join as join10 } from "path";
12621
12743
  async function resolveOwnerProfileBlock(accountId, userId) {
12622
12744
  if (!userId) return { ok: false, reason: "missing-user-id" };
12623
12745
  try {
@@ -12702,7 +12824,7 @@ function parseSkillPathsFromFrontmatter(fm) {
12702
12824
  }
12703
12825
  function listPluginDirs() {
12704
12826
  const out = /* @__PURE__ */ new Map();
12705
- const platformPlugins = resolve10(PLATFORM_ROOT, "plugins");
12827
+ const platformPlugins = resolve11(PLATFORM_ROOT, "plugins");
12706
12828
  if (existsSync14(platformPlugins)) {
12707
12829
  for (const name of readdirSync7(platformPlugins)) {
12708
12830
  const dir = join10(platformPlugins, name);
@@ -12712,7 +12834,7 @@ function listPluginDirs() {
12712
12834
  }
12713
12835
  }
12714
12836
  }
12715
- const premiumRoot = resolve10(dirname2(PLATFORM_ROOT), "premium-plugins");
12837
+ const premiumRoot = resolve11(dirname2(PLATFORM_ROOT), "premium-plugins");
12716
12838
  if (existsSync14(premiumRoot)) {
12717
12839
  for (const bundle of readdirSync7(premiumRoot)) {
12718
12840
  const bundlePlugins = join10(premiumRoot, bundle, "plugins");
@@ -12732,7 +12854,7 @@ function listPluginDirs() {
12732
12854
  return out;
12733
12855
  }
12734
12856
  function readEnabledPlugins(accountId) {
12735
- const accountFile = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12857
+ const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12736
12858
  if (!existsSync14(accountFile)) return /* @__PURE__ */ new Set();
12737
12859
  try {
12738
12860
  const parsed = JSON.parse(readFileSync12(accountFile, "utf-8"));
@@ -12805,7 +12927,7 @@ ${skillFm}
12805
12927
  return out;
12806
12928
  }
12807
12929
  function computeSpecialistDomains(accountId) {
12808
- const specialistsDir = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
12930
+ const specialistsDir = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
12809
12931
  if (!existsSync14(specialistsDir)) return [];
12810
12932
  let entries;
12811
12933
  try {
@@ -12851,7 +12973,7 @@ ${fm}
12851
12973
  return out;
12852
12974
  }
12853
12975
  function computeDormantPlugins(accountId) {
12854
- const accountFile = resolve10(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12976
+ const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
12855
12977
  if (!existsSync14(accountFile)) return [];
12856
12978
  let enabled;
12857
12979
  try {
@@ -12866,7 +12988,7 @@ function computeDormantPlugins(accountId) {
12866
12988
  );
12867
12989
  return [];
12868
12990
  }
12869
- const pluginsDir = resolve10(PLATFORM_ROOT, "plugins");
12991
+ const pluginsDir = resolve11(PLATFORM_ROOT, "plugins");
12870
12992
  if (!existsSync14(pluginsDir)) return [];
12871
12993
  let entries;
12872
12994
  try {
@@ -12877,7 +12999,7 @@ function computeDormantPlugins(accountId) {
12877
12999
  const out = [];
12878
13000
  for (const name of entries) {
12879
13001
  if (enabled.has(name)) continue;
12880
- const manifestPath = resolve10(pluginsDir, name, "PLUGIN.md");
13002
+ const manifestPath = resolve11(pluginsDir, name, "PLUGIN.md");
12881
13003
  if (!existsSync14(manifestPath)) continue;
12882
13004
  let manifest;
12883
13005
  try {
@@ -12896,7 +13018,7 @@ function computeDormantPlugins(accountId) {
12896
13018
 
12897
13019
  // server/routes/admin/claude-sessions.ts
12898
13020
  import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
12899
- import { resolve as resolve11 } from "path";
13021
+ import { resolve as resolve12 } from "path";
12900
13022
  function readTunnelState(brandConfigDir) {
12901
13023
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
12902
13024
  if (!existsSync15(statePath)) return null;
@@ -12912,10 +13034,10 @@ function readTunnelState(brandConfigDir) {
12912
13034
  }
12913
13035
  }
12914
13036
  function resolveTunnelUrl() {
12915
- const platformRoot = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve11(process.cwd(), "..");
13037
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
12916
13038
  let brand;
12917
13039
  try {
12918
- brand = JSON.parse(readFileSync13(resolve11(platformRoot, "config", "brand.json"), "utf-8"));
13040
+ brand = JSON.parse(readFileSync13(resolve12(platformRoot2, "config", "brand.json"), "utf-8"));
12919
13041
  } catch {
12920
13042
  return null;
12921
13043
  }
@@ -12926,7 +13048,7 @@ function resolveTunnelUrl() {
12926
13048
  if (!state) return null;
12927
13049
  return `https://${hostname2}.${state.domain}`;
12928
13050
  }
12929
- var TAG18 = "[claude-session-manager:wrapper]";
13051
+ var TAG20 = "[claude-session-manager:wrapper]";
12930
13052
  async function refuseIfClaudeAuthDead(c, route, sessionId) {
12931
13053
  const auth = await ensureAuth();
12932
13054
  if (auth.status !== "dead" && auth.status !== "missing") return null;
@@ -12948,12 +13070,12 @@ async function performSpawnWithInitialMessage(args) {
12948
13070
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
12949
13071
  const ownerMs = Date.now() - ownerStart;
12950
13072
  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}`);
13073
+ console.log(`${TAG20} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
12952
13074
  const dormantPlugins = computeDormantPlugins(args.senderId);
12953
13075
  const activePlugins = computeActivePlugins(args.senderId);
12954
13076
  const specialistDomains = computeSpecialistDomains(args.senderId);
12955
13077
  const tunnelUrl = resolveTunnelUrl();
12956
- console.log(`${TAG18} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
13078
+ console.log(`${TAG20} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
12957
13079
  const upstreamPayload = JSON.stringify({
12958
13080
  senderId: args.senderId,
12959
13081
  // Task 205 — pass userId through to the manager so it lands as
@@ -12980,24 +13102,24 @@ async function performSpawnWithInitialMessage(args) {
12980
13102
  // unshapely values.
12981
13103
  conversationNodeId: args.conversationNodeId
12982
13104
  });
12983
- console.log(`${TAG18} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
13105
+ console.log(`${TAG20} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
12984
13106
  const forwardStart = Date.now();
12985
13107
  const upstream = await fetch(`${managerBase3()}/public-spawn`, {
12986
13108
  method: "POST",
12987
13109
  headers: { "content-type": "application/json" },
12988
13110
  body: upstreamPayload
12989
13111
  }).catch((err) => {
12990
- console.error(`${TAG18} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
13112
+ console.error(`${TAG20} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
12991
13113
  return null;
12992
13114
  });
12993
13115
  if (!upstream) return {
12994
13116
  response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
12995
13117
  claudeSessionId: null
12996
13118
  };
12997
- console.log(`${TAG18} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
13119
+ console.log(`${TAG20} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
12998
13120
  if (args.initialMessage) {
12999
13121
  const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
13000
- console.log(`${TAG18} initial-message-inlined bytes=${inputBytes}`);
13122
+ console.log(`${TAG20} initial-message-inlined bytes=${inputBytes}`);
13001
13123
  }
13002
13124
  const bodyText = await upstream.text().catch(() => "");
13003
13125
  let claudeSessionId = null;
@@ -13032,7 +13154,7 @@ app12.post("/", async (c) => {
13032
13154
  if (refusal) return refusal;
13033
13155
  const senderId = getAccountIdForSession(cacheKey) ?? "";
13034
13156
  if (!senderId) {
13035
- console.error(`${TAG18} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
13157
+ console.error(`${TAG20} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
13036
13158
  return c.json({ error: "admin-account-not-resolved" }, 500);
13037
13159
  }
13038
13160
  const userId = getUserIdForSession(cacheKey) ?? void 0;
@@ -13041,7 +13163,7 @@ app12.post("/", async (c) => {
13041
13163
  const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
13042
13164
  const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
13043
13165
  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"}`);
13166
+ 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
13167
  const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
13046
13168
  const { response, claudeSessionId } = await performSpawnWithInitialMessage({
13047
13169
  senderId,
@@ -13060,13 +13182,13 @@ app12.post("/", async (c) => {
13060
13182
  claudeSessionId,
13061
13183
  senderId
13062
13184
  );
13063
- console.log(`${TAG18} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
13185
+ console.log(`${TAG20} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
13064
13186
  return response;
13065
13187
  });
13066
13188
  var claude_sessions_default = app12;
13067
13189
 
13068
13190
  // server/routes/admin/log-ingest.ts
13069
- var TAG19 = "[log-ingest]";
13191
+ var TAG21 = "[log-ingest]";
13070
13192
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
13071
13193
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
13072
13194
  var MAX_LINE_BYTES = 4096;
@@ -13077,7 +13199,7 @@ function isLoopbackAddr(addr) {
13077
13199
  app13.post("/", async (c) => {
13078
13200
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13079
13201
  if (!isLoopbackAddr(remoteAddr)) {
13080
- console.error(`${TAG19} reject reason=non-loopback remoteAddr=${remoteAddr}`);
13202
+ console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
13081
13203
  return c.json({ error: "log-ingest-loopback-only" }, 403);
13082
13204
  }
13083
13205
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -13086,7 +13208,7 @@ app13.post("/", async (c) => {
13086
13208
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
13087
13209
  const offender = tokens.find((t) => !isLoopbackAddr(t));
13088
13210
  if (offender !== void 0) {
13089
- console.error(`${TAG19} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
13211
+ console.error(`${TAG21} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
13090
13212
  return c.json({ error: "log-ingest-loopback-only" }, 403);
13091
13213
  }
13092
13214
  }
@@ -13128,18 +13250,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
13128
13250
  ]);
13129
13251
  var app14 = new Hono();
13130
13252
  app14.post("/", async (c) => {
13131
- const TAG29 = "[admin:events]";
13253
+ const TAG31 = "[admin:events]";
13132
13254
  let body;
13133
13255
  try {
13134
13256
  body = await c.req.json();
13135
13257
  } catch (err) {
13136
13258
  const detail = err instanceof Error ? err.message : String(err);
13137
- console.error(`${TAG29} reject reason=body-not-json detail=${detail}`);
13259
+ console.error(`${TAG31} reject reason=body-not-json detail=${detail}`);
13138
13260
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
13139
13261
  }
13140
13262
  const event = typeof body.event === "string" ? body.event : "";
13141
13263
  if (!ALLOWED_EVENTS.has(event)) {
13142
- console.error(`${TAG29} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
13264
+ console.error(`${TAG31} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
13143
13265
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
13144
13266
  }
13145
13267
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
@@ -13164,15 +13286,15 @@ var events_default = app14;
13164
13286
  import { createReadStream as createReadStream2 } from "fs";
13165
13287
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
13166
13288
  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";
13289
+ import { basename as basename4, dirname as dirname3, join as join12, resolve as resolve15, sep as sep4 } from "path";
13168
13290
  import { Readable as Readable2 } from "stream";
13169
13291
 
13170
13292
  // app/lib/data-path.ts
13171
13293
  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;
13294
+ import { resolve as resolve13, normalize, sep as sep2, relative } from "path";
13295
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "../platform");
13296
+ var DATA_ROOT = resolve13(PLATFORM_ROOT5, "..", "data");
13297
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve13(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
13176
13298
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
13177
13299
  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
13300
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -13185,7 +13307,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
13185
13307
  }
13186
13308
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
13187
13309
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
13188
- const absolute = resolve12(rootAbs, cleaned);
13310
+ const absolute = resolve13(rootAbs, cleaned);
13189
13311
  let rootReal;
13190
13312
  try {
13191
13313
  rootReal = realpathSync3(rootAbs);
@@ -13544,7 +13666,7 @@ async function cascadeDeleteDocument(params) {
13544
13666
 
13545
13667
  // app/lib/file-index.ts
13546
13668
  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";
13669
+ import { resolve as resolve14, relative as relative2, join as join11, basename as basename3, extname as extname2, sep as sep3 } from "path";
13548
13670
  import { tmpdir as tmpdir2 } from "os";
13549
13671
  import { execFile as execFile2 } from "child_process";
13550
13672
  import { promisify as promisify2 } from "util";
@@ -13852,8 +13974,8 @@ async function reconcileFileIndex(accountId, opts) {
13852
13974
  return withSession(opts, async (session) => {
13853
13975
  const walked = [];
13854
13976
  const subtreeRoots = [
13855
- resolve13(dataRoot, "uploads", accountId),
13856
- resolve13(dataRoot, "accounts", accountId)
13977
+ resolve14(dataRoot, "uploads", accountId),
13978
+ resolve14(dataRoot, "accounts", accountId)
13857
13979
  ];
13858
13980
  let clean = true;
13859
13981
  for (const root of subtreeRoots) {
@@ -13934,7 +14056,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
13934
14056
  async function indexFile(accountId, relativePath, opts) {
13935
14057
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
13936
14058
  const embed2 = opts?.embed ?? embed;
13937
- const absolute = resolve13(dataRoot, relativePath);
14059
+ const absolute = resolve14(dataRoot, relativePath);
13938
14060
  await withSession(opts, async (session) => {
13939
14061
  const st = await fsp.stat(absolute);
13940
14062
  const wf = {
@@ -13979,7 +14101,7 @@ async function readMeta(absDir, baseName) {
13979
14101
  }
13980
14102
  async function readAccountNames() {
13981
14103
  const map = /* @__PURE__ */ new Map();
13982
- const accountsDir = resolve14(DATA_ROOT, "accounts");
14104
+ const accountsDir = resolve15(DATA_ROOT, "accounts");
13983
14105
  let names;
13984
14106
  try {
13985
14107
  names = await readdir3(accountsDir);
@@ -13988,7 +14110,7 @@ async function readAccountNames() {
13988
14110
  }
13989
14111
  for (const name of names) {
13990
14112
  if (!UUID_RE3.test(name)) continue;
13991
- const configPath2 = resolve14(accountsDir, name, "account.json");
14113
+ const configPath2 = resolve15(accountsDir, name, "account.json");
13992
14114
  try {
13993
14115
  const raw = await readFile4(configPath2, "utf8");
13994
14116
  const parsed = JSON.parse(raw);
@@ -14229,8 +14351,8 @@ app15.post("/upload", requireAdminSession, async (c) => {
14229
14351
  }
14230
14352
  const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
14231
14353
  const finalName = `${Date.now()}-${safeName}`;
14232
- const destDir = resolve14(DATA_ROOT, "uploads", accountId);
14233
- const destPath = resolve14(destDir, finalName);
14354
+ const destDir = resolve15(DATA_ROOT, "uploads", accountId);
14355
+ const destPath = resolve15(destDir, finalName);
14234
14356
  try {
14235
14357
  await mkdir3(destDir, { recursive: true });
14236
14358
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -16337,7 +16459,7 @@ var graph_default_view_default = app21;
16337
16459
 
16338
16460
  // server/routes/admin/sidebar-artefacts.ts
16339
16461
  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";
16462
+ import { resolve as resolve16, relative as relative3, isAbsolute, sep as sep5, basename as basename5 } from "path";
16341
16463
  import { existsSync as existsSync16 } from "fs";
16342
16464
  var LIMIT = 50;
16343
16465
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -16357,7 +16479,7 @@ app22.get("/", requireAdminSession, async (c) => {
16357
16479
  if (outputs === null) {
16358
16480
  return c.json({ error: "Failed to load artefacts" }, 500);
16359
16481
  }
16360
- const accountDir = resolve15(ACCOUNTS_DIR, accountId);
16482
+ const accountDir = resolve16(ACCOUNTS_DIR, accountId);
16361
16483
  const agents = await fetchAgentTemplateRows(accountDir);
16362
16484
  const artefacts = [...outputs, ...agents].sort(
16363
16485
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -16408,8 +16530,8 @@ async function fetchOutputArtefacts(accountId) {
16408
16530
  async function fetchAgentTemplateRows(accountDir) {
16409
16531
  const rows = [];
16410
16532
  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);
16533
+ const overridePath = resolve16(accountDir, "agents", "admin", filename);
16534
+ const bundledPath = resolve16(PLATFORM_ROOT, "templates", "agents", "admin", filename);
16413
16535
  const labelStem = filename.replace(/\.md$/, "");
16414
16536
  const row = await readAgentTemplateRow({
16415
16537
  id: `agent-template:admin:${filename}`,
@@ -16422,12 +16544,12 @@ async function fetchAgentTemplateRows(accountDir) {
16422
16544
  });
16423
16545
  if (row) rows.push(row);
16424
16546
  }
16425
- const overrideDir = resolve15(accountDir, "specialists", "agents");
16426
- const bundledDir = resolve15(PLATFORM_ROOT, "templates", "specialists", "agents");
16547
+ const overrideDir = resolve16(accountDir, "specialists", "agents");
16548
+ const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
16427
16549
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
16428
16550
  for (const filename of specialistNames) {
16429
- const overridePath = resolve15(overrideDir, filename);
16430
- const bundledPath = resolve15(bundledDir, filename);
16551
+ const overridePath = resolve16(overrideDir, filename);
16552
+ const bundledPath = resolve16(bundledDir, filename);
16431
16553
  const row = await readAgentTemplateRow({
16432
16554
  id: `agent-template:specialist:${filename}`,
16433
16555
  displayName: filename.replace(/\.md$/, ""),
@@ -16513,7 +16635,7 @@ var sidebar_artefacts_default = app22;
16513
16635
 
16514
16636
  // server/routes/admin/sidebar-sessions.ts
16515
16637
  import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
16516
- import { join as join13, resolve as resolve16 } from "path";
16638
+ import { join as join13, resolve as resolve17 } from "path";
16517
16639
  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
16640
  var PID_FILE_RE = /^([0-9]+)\.json$/;
16519
16641
  var TITLE_MAX = 80;
@@ -16694,7 +16816,7 @@ app23.get("/", requireAdminSession, async (c) => {
16694
16816
  const projectsRoot = join13(configDir2, "projects");
16695
16817
  const jsonls = enumerateJsonls(projectsRoot);
16696
16818
  const pidsBySession = sessionIdToPidMap(configDir2);
16697
- const accountDir = accountId ? resolve16(ACCOUNTS_DIR, accountId) : null;
16819
+ const accountDir = accountId ? resolve17(ACCOUNTS_DIR, accountId) : null;
16698
16820
  const userTitles = loadUserTitles(accountDir);
16699
16821
  const rows = [];
16700
16822
  const seenIds = /* @__PURE__ */ new Set();
@@ -16748,7 +16870,7 @@ var sidebar_sessions_default = app23;
16748
16870
 
16749
16871
  // server/routes/admin/session-delete.ts
16750
16872
  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";
16873
+ import { join as join14, resolve as resolve18 } from "path";
16752
16874
  var app24 = new Hono();
16753
16875
  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
16876
  var PID_FILE_RE2 = /^([0-9]+)\.json$/;
@@ -16797,7 +16919,7 @@ function isPidAlive(pid) {
16797
16919
  }
16798
16920
  }
16799
16921
  function sleep2(ms) {
16800
- return new Promise((resolve26) => setTimeout(resolve26, ms));
16922
+ return new Promise((resolve27) => setTimeout(resolve27, ms));
16801
16923
  }
16802
16924
  function sendSignal(pid, signal) {
16803
16925
  try {
@@ -16865,8 +16987,8 @@ app24.post("/", requireAdminSession, async (c) => {
16865
16987
  if (!configDir2) {
16866
16988
  return c.json({ error: "CLAUDE_CONFIG_DIR not set" }, 500);
16867
16989
  }
16868
- const projectsRoot = resolve17(join14(configDir2, "projects")) + "/";
16869
- const resolvedProject = resolve17(projectDir) + "/";
16990
+ const projectsRoot = resolve18(join14(configDir2, "projects")) + "/";
16991
+ const resolvedProject = resolve18(projectDir) + "/";
16870
16992
  if (!resolvedProject.startsWith(projectsRoot)) {
16871
16993
  console.error(`[sessions-delete] reject reason=projectDir-outside-tree projectDir=${projectDir}`);
16872
16994
  return c.json({ error: "projectDir is not under CLAUDE_CONFIG_DIR/projects/" }, 400);
@@ -17097,8 +17219,8 @@ var system_stats_default = app26;
17097
17219
 
17098
17220
  // server/routes/admin/health.ts
17099
17221
  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(), "..");
17222
+ import { resolve as resolve19, join as join15 } from "path";
17223
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
17102
17224
  var brandHostname = "maxy";
17103
17225
  var brandJsonPath = join15(PLATFORM_ROOT6, "config", "brand.json");
17104
17226
  if (existsSync18(brandJsonPath)) {
@@ -17108,7 +17230,7 @@ if (existsSync18(brandJsonPath)) {
17108
17230
  } catch {
17109
17231
  }
17110
17232
  }
17111
- var VERSION_FILE = resolve18(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
17233
+ var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
17112
17234
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
17113
17235
  var PROBE_TIMEOUT_MS = 1e3;
17114
17236
  function readVersion() {
@@ -17165,7 +17287,7 @@ var health_default2 = app27;
17165
17287
 
17166
17288
  // server/routes/admin/linkedin-ingest.ts
17167
17289
  import { randomUUID as randomUUID9 } from "crypto";
17168
- var TAG20 = "[linkedin-ingest-route]";
17290
+ var TAG22 = "[linkedin-ingest-route]";
17169
17291
  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
17292
  var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
17171
17293
  var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
@@ -17269,29 +17391,29 @@ app28.post("/", requireAdminSession, async (c) => {
17269
17391
  try {
17270
17392
  body = await c.req.json();
17271
17393
  } catch {
17272
- console.error(TAG20 + " rejected status=400 reason=schema:body-not-json");
17394
+ console.error(TAG22 + " rejected status=400 reason=schema:body-not-json");
17273
17395
  return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
17274
17396
  }
17275
17397
  const v = validate(body);
17276
17398
  if (!v.ok) {
17277
- console.error(TAG20 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
17399
+ console.error(TAG22 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
17278
17400
  return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
17279
17401
  }
17280
17402
  const envelope = v.envelope;
17281
17403
  const cacheKey = c.var.cacheKey ?? "";
17282
17404
  const senderId = getAccountIdForSession(cacheKey) ?? "";
17283
17405
  if (!senderId) {
17284
- console.error(TAG20 + " rejected status=500 reason=admin-account-not-resolved");
17406
+ console.error(TAG22 + " rejected status=500 reason=admin-account-not-resolved");
17285
17407
  return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
17286
17408
  }
17287
17409
  const payloadBytes = JSON.stringify(envelope).length;
17288
17410
  console.log(
17289
- TAG20 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
17411
+ TAG22 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
17290
17412
  );
17291
17413
  const initialMessage = buildInitialMessage(envelope);
17292
17414
  const spawnStart = Date.now();
17293
17415
  const sessionId = randomUUID9();
17294
- console.log(TAG20 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
17416
+ console.log(TAG22 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
17295
17417
  const spawned = await managerRcSpawn({
17296
17418
  sessionId,
17297
17419
  initialMessage,
@@ -17300,12 +17422,12 @@ app28.post("/", requireAdminSession, async (c) => {
17300
17422
  });
17301
17423
  if ("error" in spawned) {
17302
17424
  console.error(
17303
- TAG20 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
17425
+ TAG22 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
17304
17426
  );
17305
17427
  return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
17306
17428
  }
17307
17429
  console.log(
17308
- TAG20 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
17430
+ TAG22 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
17309
17431
  );
17310
17432
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
17311
17433
  });
@@ -17313,7 +17435,7 @@ var linkedin_ingest_default = app28;
17313
17435
 
17314
17436
  // server/routes/admin/post-turn-context.ts
17315
17437
  import neo4j2 from "neo4j-driver";
17316
- var TAG21 = "[post-turn-context]";
17438
+ var TAG23 = "[post-turn-context]";
17317
17439
  var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
17318
17440
  "embedding",
17319
17441
  "passwordHash",
@@ -17355,7 +17477,7 @@ var app29 = new Hono();
17355
17477
  app29.get("/", async (c) => {
17356
17478
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17357
17479
  if (!isLoopbackAddr2(remoteAddr)) {
17358
- console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17480
+ console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17359
17481
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
17360
17482
  }
17361
17483
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17364,7 +17486,7 @@ app29.get("/", async (c) => {
17364
17486
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17365
17487
  const offender = tokens.find((t) => !isLoopbackAddr2(t));
17366
17488
  if (offender !== void 0) {
17367
- console.error(`${TAG21} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17489
+ console.error(`${TAG23} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17368
17490
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
17369
17491
  }
17370
17492
  }
@@ -17396,7 +17518,7 @@ app29.get("/", async (c) => {
17396
17518
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
17397
17519
  const total = Date.now() - started;
17398
17520
  console.log(
17399
- `${TAG21} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
17521
+ `${TAG23} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
17400
17522
  );
17401
17523
  return c.json({
17402
17524
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
@@ -17405,7 +17527,7 @@ app29.get("/", async (c) => {
17405
17527
  const elapsed = Date.now() - started;
17406
17528
  const message = err instanceof Error ? err.message : String(err);
17407
17529
  console.error(
17408
- `${TAG21} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
17530
+ `${TAG23} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
17409
17531
  );
17410
17532
  return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
17411
17533
  } finally {
@@ -17416,7 +17538,7 @@ var post_turn_context_default = app29;
17416
17538
 
17417
17539
  // server/routes/admin/public-session-context.ts
17418
17540
  import neo4j3 from "neo4j-driver";
17419
- var TAG22 = "[public-session-context]";
17541
+ var TAG24 = "[public-session-context]";
17420
17542
  var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
17421
17543
  "embedding",
17422
17544
  "passwordHash",
@@ -17458,7 +17580,7 @@ var app30 = new Hono();
17458
17580
  app30.get("/", async (c) => {
17459
17581
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17460
17582
  if (!isLoopbackAddr3(remoteAddr)) {
17461
- console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17583
+ console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17462
17584
  return c.json({ error: "public-session-context-loopback-only" }, 403);
17463
17585
  }
17464
17586
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17467,7 +17589,7 @@ app30.get("/", async (c) => {
17467
17589
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17468
17590
  const offender = tokens.find((t) => !isLoopbackAddr3(t));
17469
17591
  if (offender !== void 0) {
17470
- console.error(`${TAG22} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17592
+ console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17471
17593
  return c.json({ error: "public-session-context-loopback-only" }, 403);
17472
17594
  }
17473
17595
  }
@@ -17498,7 +17620,7 @@ app30.get("/", async (c) => {
17498
17620
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
17499
17621
  const total = Date.now() - started;
17500
17622
  console.log(
17501
- `${TAG22} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
17623
+ `${TAG24} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
17502
17624
  );
17503
17625
  return c.json({
17504
17626
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
@@ -17507,7 +17629,7 @@ app30.get("/", async (c) => {
17507
17629
  const elapsed = Date.now() - started;
17508
17630
  const message = err instanceof Error ? err.message : String(err);
17509
17631
  console.error(
17510
- `${TAG22} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
17632
+ `${TAG24} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
17511
17633
  );
17512
17634
  return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
17513
17635
  } finally {
@@ -17517,7 +17639,7 @@ app30.get("/", async (c) => {
17517
17639
  var public_session_context_default = app30;
17518
17640
 
17519
17641
  // server/routes/admin/public-session-exit.ts
17520
- var TAG23 = "[public-session-exit-route]";
17642
+ var TAG25 = "[public-session-exit-route]";
17521
17643
  function isLoopbackAddr4(addr) {
17522
17644
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
17523
17645
  }
@@ -17525,7 +17647,7 @@ var app31 = new Hono();
17525
17647
  app31.post("/", async (c) => {
17526
17648
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17527
17649
  if (!isLoopbackAddr4(remoteAddr)) {
17528
- console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17650
+ console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17529
17651
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
17530
17652
  }
17531
17653
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17534,7 +17656,7 @@ app31.post("/", async (c) => {
17534
17656
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17535
17657
  const offender = tokens.find((t) => !isLoopbackAddr4(t));
17536
17658
  if (offender !== void 0) {
17537
- console.error(`${TAG23} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17659
+ console.error(`${TAG25} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17538
17660
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
17539
17661
  }
17540
17662
  }
@@ -17552,7 +17674,7 @@ app31.post("/", async (c) => {
17552
17674
  var public_session_exit_default = app31;
17553
17675
 
17554
17676
  // server/routes/admin/access-session-evict.ts
17555
- var TAG24 = "[access-session-evict]";
17677
+ var TAG26 = "[access-session-evict]";
17556
17678
  function isLoopbackAddr5(addr) {
17557
17679
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
17558
17680
  }
@@ -17560,7 +17682,7 @@ var app32 = new Hono();
17560
17682
  app32.post("/", async (c) => {
17561
17683
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17562
17684
  if (!isLoopbackAddr5(remoteAddr)) {
17563
- console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17685
+ console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17564
17686
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
17565
17687
  }
17566
17688
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17569,7 +17691,7 @@ app32.post("/", async (c) => {
17569
17691
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17570
17692
  const offender = tokens.find((t) => !isLoopbackAddr5(t));
17571
17693
  if (offender !== void 0) {
17572
- console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17694
+ console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17573
17695
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
17574
17696
  }
17575
17697
  }
@@ -17582,7 +17704,7 @@ app32.post("/", async (c) => {
17582
17704
  const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
17583
17705
  if (!grantId) return c.json({ error: "grantId required" }, 400);
17584
17706
  const dropped = evictAccessSessionsByGrant(grantId);
17585
- console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
17707
+ console.log(`${TAG26} grantId=${grantId} dropped=${dropped}`);
17586
17708
  return c.json({ ok: true, dropped });
17587
17709
  });
17588
17710
  var access_session_evict_default = app32;
@@ -17590,7 +17712,7 @@ var access_session_evict_default = app32;
17590
17712
  // server/routes/admin/identity.ts
17591
17713
  var import_dist4 = __toESM(require_dist3(), 1);
17592
17714
  var app33 = new Hono();
17593
- var TAG25 = "[admin-identity]";
17715
+ var TAG27 = "[admin-identity]";
17594
17716
  function managerBase5() {
17595
17717
  const port2 = (0, import_dist4.requirePortEnv)("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-identity" });
17596
17718
  return `http://127.0.0.1:${port2}`;
@@ -17621,20 +17743,20 @@ app33.post("/validate", async (c) => {
17621
17743
  const verdict = validatePin(pin, USERS_FILE);
17622
17744
  if (verdict.kind !== "match") {
17623
17745
  if (verdict.kind === "miss") fireStop();
17624
- console.log(`${TAG25} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
17746
+ console.log(`${TAG27} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
17625
17747
  return c.json({ kind: verdict.kind });
17626
17748
  }
17627
17749
  const { userId } = verdict;
17628
17750
  const accounts = resolveUserAccounts(userId);
17629
17751
  if (accounts.length === 0) {
17630
17752
  fireStop();
17631
- console.log(`${TAG25} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
17753
+ console.log(`${TAG27} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
17632
17754
  return c.json({ kind: "miss" });
17633
17755
  }
17634
17756
  const accountId = accounts[0].accountId;
17635
17757
  const { userName } = await resolveUserIdentity(accountId, userId);
17636
17758
  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}`}`);
17759
+ console.log(`${TAG27} op=endpoint-validate result=match userId=${userId.slice(0, 8)} aboutOwner=${aboutOwner.ok ? "ok" : `unresolved:${aboutOwner.reason}`}`);
17638
17760
  return c.json({ kind: "match", userId, userName, aboutOwner });
17639
17761
  });
17640
17762
  var identity_default = app33;
@@ -17674,13 +17796,13 @@ var admin_default = app34;
17674
17796
  // app/lib/access-gate.ts
17675
17797
  import neo4j4 from "neo4j-driver";
17676
17798
  import { readFileSync as readFileSync17 } from "fs";
17677
- import { resolve as resolve19 } from "path";
17799
+ import { resolve as resolve20 } from "path";
17678
17800
  import { randomUUID as randomUUID10 } from "crypto";
17679
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
17801
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
17680
17802
  var driver = null;
17681
17803
  function readPassword() {
17682
17804
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
17683
- const passwordFile = resolve19(PLATFORM_ROOT7, "config/.neo4j-password");
17805
+ const passwordFile = resolve20(PLATFORM_ROOT7, "config/.neo4j-password");
17684
17806
  try {
17685
17807
  return readFileSync17(passwordFile, "utf-8").trim();
17686
17808
  } catch {
@@ -17880,7 +18002,7 @@ async function generateNewMagicToken(grantId) {
17880
18002
  }
17881
18003
 
17882
18004
  // server/routes/access/verify-token.ts
17883
- var TAG26 = "[access-verify]";
18005
+ var TAG28 = "[access-verify]";
17884
18006
  var MINT_TAG = "[access-session-mint]";
17885
18007
  var COOKIE_NAME = "__access_session";
17886
18008
  var app35 = new Hono();
@@ -17899,39 +18021,39 @@ app35.post("/", async (c) => {
17899
18021
  }
17900
18022
  const rateMsg = checkAccessRateLimit(ip, agentSlug);
17901
18023
  if (rateMsg) {
17902
- console.error(`${TAG26} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
18024
+ console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
17903
18025
  return c.json({ error: rateMsg }, 429);
17904
18026
  }
17905
18027
  const grant = await findGrantByMagicToken(token);
17906
18028
  if (!grant) {
17907
18029
  recordAccessFailedAttempt(ip, agentSlug);
17908
- console.error(`${TAG26} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
18030
+ console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
17909
18031
  return c.json({ error: "invalid-or-expired-link" }, 401);
17910
18032
  }
17911
18033
  if (grant.agentSlug !== agentSlug) {
17912
18034
  recordAccessFailedAttempt(ip, agentSlug);
17913
18035
  console.error(
17914
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
18036
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
17915
18037
  );
17916
18038
  return c.json({ error: "invalid-or-expired-link" }, 401);
17917
18039
  }
17918
18040
  if (grant.status === "expired" || grant.status === "revoked") {
17919
18041
  recordAccessFailedAttempt(ip, agentSlug);
17920
18042
  console.error(
17921
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
18043
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
17922
18044
  );
17923
18045
  return c.json({ error: "access-no-longer-valid" }, 401);
17924
18046
  }
17925
18047
  if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
17926
18048
  recordAccessFailedAttempt(ip, agentSlug);
17927
18049
  console.error(
17928
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
18050
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
17929
18051
  );
17930
18052
  return c.json({ error: "access-no-longer-valid" }, 401);
17931
18053
  }
17932
18054
  if (!grant.sliceToken) {
17933
18055
  console.error(
17934
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
18056
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
17935
18057
  );
17936
18058
  return c.json({ error: "grant-misconfigured" }, 500);
17937
18059
  }
@@ -17947,12 +18069,12 @@ app35.post("/", async (c) => {
17947
18069
  await consumeMagicTokenAndActivate(grant.grantId);
17948
18070
  } catch (err) {
17949
18071
  console.error(
17950
- `${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
18072
+ `${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
17951
18073
  );
17952
18074
  return c.json({ error: "verification-failed" }, 500);
17953
18075
  }
17954
18076
  clearAccessRateLimit(ip, agentSlug);
17955
- console.log(`${TAG26} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
18077
+ console.log(`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
17956
18078
  console.log(
17957
18079
  `${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
17958
18080
  );
@@ -17970,9 +18092,9 @@ var verify_token_default = app35;
17970
18092
 
17971
18093
  // app/lib/access-email.ts
17972
18094
  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(
18095
+ import { resolve as resolve21 } from "path";
18096
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
18097
+ var SEND_SCRIPT = resolve21(
17976
18098
  PLATFORM_ROOT8,
17977
18099
  "plugins",
17978
18100
  "email",
@@ -18028,7 +18150,7 @@ async function sendMagicLinkEmail(payload) {
18028
18150
  }
18029
18151
 
18030
18152
  // server/routes/access/request-magic-link.ts
18031
- var TAG27 = "[access-request-link]";
18153
+ var TAG29 = "[access-request-link]";
18032
18154
  var app36 = new Hono();
18033
18155
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
18034
18156
  app36.post("/", async (c) => {
@@ -18045,18 +18167,18 @@ app36.post("/", async (c) => {
18045
18167
  }
18046
18168
  const rateMsg = checkRequestLinkRateLimit(contactValue);
18047
18169
  if (rateMsg) {
18048
- console.error(`${TAG27} contactValue=${maskContact(contactValue)} result=rate-limited`);
18170
+ console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=rate-limited`);
18049
18171
  return c.json({ error: rateMsg }, 429);
18050
18172
  }
18051
18173
  recordRequestLinkAttempt(contactValue);
18052
18174
  const accountId = process.env.ACCOUNT_ID ?? "";
18053
18175
  if (!accountId) {
18054
- console.error(`${TAG27} contactValue=${maskContact(contactValue)} result=no-account-id`);
18176
+ console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=no-account-id`);
18055
18177
  return c.json({ message: VISITOR_MESSAGE }, 200);
18056
18178
  }
18057
18179
  const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
18058
18180
  if (!grant) {
18059
- console.log(`${TAG27} contactValue=${maskContact(contactValue)} result=notfound`);
18181
+ console.log(`${TAG29} contactValue=${maskContact(contactValue)} result=notfound`);
18060
18182
  return c.json({ message: VISITOR_MESSAGE }, 200);
18061
18183
  }
18062
18184
  let token;
@@ -18064,7 +18186,7 @@ app36.post("/", async (c) => {
18064
18186
  token = await generateNewMagicToken(grant.grantId);
18065
18187
  } catch (err) {
18066
18188
  console.error(
18067
- `${TAG27} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
18189
+ `${TAG29} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
18068
18190
  );
18069
18191
  return c.json({ message: VISITOR_MESSAGE }, 200);
18070
18192
  }
@@ -18096,12 +18218,12 @@ app36.post("/", async (c) => {
18096
18218
  });
18097
18219
  if (!sendResult.ok) {
18098
18220
  console.error(
18099
- `${TAG27} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
18221
+ `${TAG29} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
18100
18222
  );
18101
18223
  return c.json({ message: VISITOR_MESSAGE }, 200);
18102
18224
  }
18103
18225
  console.log(
18104
- `${TAG27} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
18226
+ `${TAG29} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
18105
18227
  );
18106
18228
  return c.json({ message: VISITOR_MESSAGE }, 200);
18107
18229
  });
@@ -18115,7 +18237,7 @@ var access_default = app37;
18115
18237
 
18116
18238
  // server/routes/sites.ts
18117
18239
  import { existsSync as existsSync19, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
18118
- import { resolve as resolve21 } from "path";
18240
+ import { resolve as resolve22 } from "path";
18119
18241
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
18120
18242
  var MIME = {
18121
18243
  ".html": "text/html; charset=utf-8",
@@ -18172,8 +18294,8 @@ app38.get("/:rel{.*}", (c) => {
18172
18294
  }
18173
18295
  segments.push(seg);
18174
18296
  }
18175
- const rootDir = resolve21(account.accountDir, "sites");
18176
- let filePath = segments.length === 0 ? rootDir : resolve21(rootDir, ...segments);
18297
+ const rootDir = resolve22(account.accountDir, "sites");
18298
+ let filePath = segments.length === 0 ? rootDir : resolve22(rootDir, ...segments);
18177
18299
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
18178
18300
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
18179
18301
  return c.text("Forbidden", 403);
@@ -18193,7 +18315,7 @@ app38.get("/:rel{.*}", (c) => {
18193
18315
  return c.redirect(target, 301);
18194
18316
  }
18195
18317
  if (stat7?.isDirectory()) {
18196
- filePath = resolve21(filePath, "index.html");
18318
+ filePath = resolve22(filePath, "index.html");
18197
18319
  }
18198
18320
  if (!filePath.startsWith(rootDir + "/")) {
18199
18321
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -18337,9 +18459,9 @@ var cachedAttempted = false;
18337
18459
  function readBrandConfig() {
18338
18460
  if (cachedAttempted) return cached2;
18339
18461
  cachedAttempted = true;
18340
- const platformRoot = process.env.MAXY_PLATFORM_ROOT;
18341
- if (!platformRoot) return null;
18342
- const brandPath = join16(platformRoot, "config", "brand.json");
18462
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
18463
+ if (!platformRoot2) return null;
18464
+ const brandPath = join16(platformRoot2, "config", "brand.json");
18343
18465
  if (!existsSync20(brandPath)) return null;
18344
18466
  try {
18345
18467
  cached2 = JSON.parse(readFileSync20(brandPath, "utf-8"));
@@ -18830,14 +18952,14 @@ async function writeEvent(opts) {
18830
18952
  var visitor_event_default = app41;
18831
18953
 
18832
18954
  // server/routes/session.ts
18833
- import { resolve as resolve22 } from "path";
18955
+ import { resolve as resolve23 } from "path";
18834
18956
  import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
18835
18957
  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
18958
  function writeBrandingCache(accountId, agentSlug, branding) {
18837
18959
  try {
18838
- const cacheDir = resolve22(MAXY_DIR, "branding-cache", accountId);
18960
+ const cacheDir = resolve23(MAXY_DIR, "branding-cache", accountId);
18839
18961
  mkdirSync5(cacheDir, { recursive: true });
18840
- writeFileSync7(resolve22(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
18962
+ writeFileSync7(resolve23(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
18841
18963
  } catch (err) {
18842
18964
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
18843
18965
  }
@@ -18916,8 +19038,8 @@ app42.post("/", async (c) => {
18916
19038
  }
18917
19039
  let agentConfig = null;
18918
19040
  if (account) {
18919
- const agentDir = resolve22(account.accountDir, "agents", agentSlug);
18920
- if (!existsSync21(agentDir) || !existsSync21(resolve22(agentDir, "config.json"))) {
19041
+ const agentDir = resolve23(account.accountDir, "agents", agentSlug);
19042
+ if (!existsSync21(agentDir) || !existsSync21(resolve23(agentDir, "config.json"))) {
18921
19043
  return c.json({ error: "Agent not found" }, 404);
18922
19044
  }
18923
19045
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -19154,7 +19276,7 @@ function startGraphHealthTimer() {
19154
19276
 
19155
19277
  // app/lib/file-watcher.ts
19156
19278
  import * as fsp2 from "fs/promises";
19157
- import { resolve as resolve23, sep as sep6 } from "path";
19279
+ import { resolve as resolve24, sep as sep6 } from "path";
19158
19280
  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
19281
  var DEFAULT_COALESCE_MS = 500;
19160
19282
  var ROOTS = ["uploads", "accounts"];
@@ -19173,7 +19295,7 @@ async function startFileWatcher(opts = {}) {
19173
19295
  const dropFn = opts.drop ?? dropFileIndex;
19174
19296
  for (const r of ROOTS) {
19175
19297
  try {
19176
- await fsp2.mkdir(resolve23(dataRoot, r), { recursive: true });
19298
+ await fsp2.mkdir(resolve24(dataRoot, r), { recursive: true });
19177
19299
  } catch (err) {
19178
19300
  console.error(
19179
19301
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -19194,7 +19316,7 @@ async function startFileWatcher(opts = {}) {
19194
19316
  timers.set(relativePath, t);
19195
19317
  }
19196
19318
  async function runHook(relativePath, accountId) {
19197
- const absolute = resolve23(dataRoot, relativePath);
19319
+ const absolute = resolve24(dataRoot, relativePath);
19198
19320
  let exists = false;
19199
19321
  try {
19200
19322
  const st = await fsp2.stat(absolute);
@@ -19218,7 +19340,7 @@ async function startFileWatcher(opts = {}) {
19218
19340
  }
19219
19341
  }
19220
19342
  async function watchRoot(rootName) {
19221
- const absRoot = resolve23(dataRoot, rootName);
19343
+ const absRoot = resolve24(dataRoot, rootName);
19222
19344
  try {
19223
19345
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
19224
19346
  for await (const event of iter) {
@@ -19256,7 +19378,7 @@ async function startFileWatcher(opts = {}) {
19256
19378
  }
19257
19379
 
19258
19380
  // app/lib/whatsapp/inbound/claude-bridge.ts
19259
- var TAG28 = "[whatsapp-adaptor]";
19381
+ var TAG30 = "[whatsapp-adaptor]";
19260
19382
  function whatsappTurnTimeoutMs() {
19261
19383
  return Number(process.env.WHATSAPP_PTY_TURN_TIMEOUT_MS ?? String(5 * 6e4));
19262
19384
  }
@@ -19278,7 +19400,7 @@ async function dispatchToClaude(input) {
19278
19400
  await input.reply(result.turnText);
19279
19401
  } catch (err) {
19280
19402
  const m = err instanceof Error ? err.message : String(err);
19281
- console.error(`${TAG28} reject reason=reply-failed senderId=${input.senderId} message=${m}`);
19403
+ console.error(`${TAG30} reject reason=reply-failed senderId=${input.senderId} message=${m}`);
19282
19404
  }
19283
19405
  }
19284
19406
  function startReaper2() {
@@ -19316,7 +19438,7 @@ function broadcastAdminShutdown(reason) {
19316
19438
  // ../lib/entitlement/src/index.ts
19317
19439
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
19318
19440
  import { existsSync as existsSync22, readFileSync as readFileSync21, statSync as statSync9 } from "fs";
19319
- import { resolve as resolve24 } from "path";
19441
+ import { resolve as resolve25 } from "path";
19320
19442
 
19321
19443
  // ../lib/entitlement/src/canonicalize.ts
19322
19444
  function canonicalize(value) {
@@ -19351,7 +19473,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
19351
19473
  var GRACE_DAYS = 7;
19352
19474
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
19353
19475
  function pubkeyPath(brand) {
19354
- return resolve24(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
19476
+ return resolve25(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
19355
19477
  }
19356
19478
  var memo = null;
19357
19479
  function memoKey(mtimeMs, account) {
@@ -19363,7 +19485,7 @@ function resolveEntitlement(brand, account) {
19363
19485
  if (brand.commercialMode !== true) {
19364
19486
  return logResolved(implicitTrust(account), null);
19365
19487
  }
19366
- const entitlementPath = resolve24(brand.configDir, "entitlement.json");
19488
+ const entitlementPath = resolve25(brand.configDir, "entitlement.json");
19367
19489
  if (!existsSync22(entitlementPath)) {
19368
19490
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
19369
19491
  }
@@ -19925,8 +20047,8 @@ app43.get("/agent-assets/:slug/:filename", (c) => {
19925
20047
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
19926
20048
  return c.text("Not found", 404);
19927
20049
  }
19928
- const filePath = resolve25(account.accountDir, "agents", slug, "assets", filename);
19929
- const expectedDir = resolve25(account.accountDir, "agents", slug, "assets");
20050
+ const filePath = resolve26(account.accountDir, "agents", slug, "assets", filename);
20051
+ const expectedDir = resolve26(account.accountDir, "agents", slug, "assets");
19930
20052
  if (!filePath.startsWith(expectedDir + "/")) {
19931
20053
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
19932
20054
  return c.text("Forbidden", 403);
@@ -19955,8 +20077,8 @@ app43.get("/generated/:filename", (c) => {
19955
20077
  console.error(`[generated] serve file=${filename} status=404`);
19956
20078
  return c.text("Not found", 404);
19957
20079
  }
19958
- const filePath = resolve25(account.accountDir, "generated", filename);
19959
- const expectedDir = resolve25(account.accountDir, "generated");
20080
+ const filePath = resolve26(account.accountDir, "generated", filename);
20081
+ const expectedDir = resolve26(account.accountDir, "generated");
19960
20082
  if (!filePath.startsWith(expectedDir + "/")) {
19961
20083
  console.error(`[generated] serve file=${filename} status=403`);
19962
20084
  return c.text("Forbidden", 403);
@@ -20043,7 +20165,7 @@ var clientErrorReporterScript = `<script>
20043
20165
  function cachedHtml(file) {
20044
20166
  let html = htmlCache.get(file);
20045
20167
  if (!html) {
20046
- html = readFileSync22(resolve25(process.cwd(), "public", file), "utf-8");
20168
+ html = readFileSync22(resolve26(process.cwd(), "public", file), "utf-8");
20047
20169
  const productNameEsc = escapeHtml(BRAND.productName);
20048
20170
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
20049
20171
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -20161,7 +20283,7 @@ app43.use("/vnc-popout.html", logViewerFetch);
20161
20283
  app43.get("/vnc-popout.html", (c) => {
20162
20284
  let html = htmlCache.get("vnc-popout.html");
20163
20285
  if (!html) {
20164
- html = readFileSync22(resolve25(process.cwd(), "public", "vnc-popout.html"), "utf-8");
20286
+ html = readFileSync22(resolve26(process.cwd(), "public", "vnc-popout.html"), "utf-8");
20165
20287
  const name = escapeHtml(BRAND.productName);
20166
20288
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
20167
20289
  html = html.replace("</head>", ` ${brandScript}
@@ -20405,7 +20527,7 @@ if (bootAccountConfig?.whatsapp) {
20405
20527
  }
20406
20528
  init({
20407
20529
  configDir: configDirForWhatsApp,
20408
- platformRoot: resolve25(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
20530
+ platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
20409
20531
  accountConfig: bootAccountConfig,
20410
20532
  onMessage: async (msg) => {
20411
20533
  if (msg.text && !msg.isOwnerMirror) {