@rubytech/create-maxy-code 0.1.371 → 0.1.373

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 (60) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/models/dist/index.d.ts +1 -1
  3. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/models/dist/index.js +2 -2
  5. package/payload/platform/lib/models/dist/index.js.map +1 -1
  6. package/payload/platform/lib/models/src/index.ts +2 -2
  7. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +5 -3
  8. package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +1 -1
  9. package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -2
  10. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  11. package/payload/platform/plugins/docs/references/platform.md +2 -0
  12. package/payload/platform/plugins/memory/mcp/dist/index.js +2 -1
  13. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  14. package/payload/platform/scripts/check-no-esm-require.mjs +5 -0
  15. package/payload/platform/services/claude-session-manager/dist/http-server.js +1 -1
  16. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  17. package/payload/platform/services/claude-session-manager/dist/index.js +38 -5
  18. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  19. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +19 -0
  20. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -0
  21. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +28 -0
  22. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -0
  23. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +5 -0
  24. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +33 -6
  26. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
  27. package/payload/platform/templates/specialists/agents/data-manager.md +1 -1
  28. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  29. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  30. package/payload/premium-plugins/writer-craft/agents/writer-craft--manuscript-reviewer.md +1 -1
  31. package/payload/server/public/assets/{AdminLoginScreens-zXJJq-wN.js → AdminLoginScreens-CGTA9noi.js} +1 -1
  32. package/payload/server/public/assets/AdminShell-CNwb23_A.js +1 -0
  33. package/payload/server/public/assets/{Checkbox-BO0J7hn7.js → Checkbox-BagcrE4Q.js} +1 -1
  34. package/payload/server/public/assets/OperatorConversations-BX9t3jgm.css +1 -0
  35. package/payload/server/public/assets/{admin-B5blbG0q.js → admin-CodAEpgQ.js} +1 -1
  36. package/payload/server/public/assets/{browser-Cc38Ih6f.js → browser-CRTlI7ck.js} +1 -1
  37. package/payload/server/public/assets/{calendar-ZY9A8F44.js → calendar-BBEivUAw.js} +1 -1
  38. package/payload/server/public/assets/chat-r1qKuzHk.js +1 -0
  39. package/payload/server/public/assets/{data-DuoDaO1z.js → data-BkY0bFYS.js} +1 -1
  40. package/payload/server/public/assets/{graph-CSOYoN0i.js → graph-HoHcI7qv.js} +1 -1
  41. package/payload/server/public/assets/{graph-labels-DdiX7_Ot.js → graph-labels-BJfK0tbH.js} +1 -1
  42. package/payload/server/public/assets/{operator-Cvci_FDA.js → operator-5wtImBoF.js} +1 -1
  43. package/payload/server/public/assets/page-CzTgPTp3.js +32 -0
  44. package/payload/server/public/assets/public-CUopv7Ro.js +1 -0
  45. package/payload/server/public/assets/{rotate-ccw-Dahm1S_V.js → rotate-ccw-DttFB1nY.js} +1 -1
  46. package/payload/server/public/browser.html +4 -4
  47. package/payload/server/public/calendar.html +4 -4
  48. package/payload/server/public/chat.html +6 -6
  49. package/payload/server/public/data.html +4 -4
  50. package/payload/server/public/graph.html +7 -7
  51. package/payload/server/public/index.html +6 -6
  52. package/payload/server/public/operator.html +8 -8
  53. package/payload/server/public/public.html +6 -6
  54. package/payload/server/server.js +253 -197
  55. package/payload/server/public/assets/AdminShell-BA24dbW1.js +0 -1
  56. package/payload/server/public/assets/OperatorConversations-BA1bRX1_.css +0 -1
  57. package/payload/server/public/assets/chat-zZuu4bcb.js +0 -1
  58. package/payload/server/public/assets/page-6HQSRX5P.js +0 -32
  59. package/payload/server/public/assets/public-DG-f7MFU.js +0 -1
  60. /package/payload/server/public/assets/{OperatorConversations-Cf-ejiJO.js → OperatorConversations-CivR0bnD.js} +0 -0
@@ -1306,7 +1306,7 @@ var serveStatic = (options = { root: "" }) => {
1306
1306
  // server/index.ts
1307
1307
  import { readFileSync as readFileSync33, existsSync as existsSync32, watchFile } from "fs";
1308
1308
  import { spawn as spawn3 } from "child_process";
1309
- import { resolve as resolve32, join as join32, basename as basename10 } from "path";
1309
+ import { resolve as resolve32, join as join33, basename as basename12 } from "path";
1310
1310
  import { homedir as homedir3 } from "os";
1311
1311
  import { monitorEventLoopDelay } from "perf_hooks";
1312
1312
 
@@ -3736,6 +3736,14 @@ var TAG12 = "[stt]";
3736
3736
  var WHISPER_BINARY = process.env.WHISPER_BINARY ?? "/opt/whisper.cpp/build/bin/whisper-cli";
3737
3737
  var WHISPER_MODEL = process.env.WHISPER_MODEL ?? "/opt/whisper.cpp/models/ggml-base.bin";
3738
3738
  var WHISPER_TIMEOUT_MS = 20 * 60 * 1e3;
3739
+ var SPECIAL_TOKEN_RE = /\[_[A-Z]+(?:_\d+)?_?\]/g;
3740
+ function stripSpecialTokens(input) {
3741
+ const matches = input.match(SPECIAL_TOKEN_RE);
3742
+ const count = matches ? matches.length : 0;
3743
+ if (!count) return { text: input, count: 0 };
3744
+ const text = input.replace(SPECIAL_TOKEN_RE, "").replace(/[ \t]{2,}/g, " ").trim();
3745
+ return { text, count };
3746
+ }
3739
3747
  async function transcribe(audioPath, mimetype) {
3740
3748
  const startMs = Date.now();
3741
3749
  let audioBytes = 0;
@@ -3777,12 +3785,10 @@ async function transcribe(audioPath, mimetype) {
3777
3785
  wavPath,
3778
3786
  "--no-timestamps",
3779
3787
  "-l",
3780
- "auto",
3781
- "--print-special",
3782
- "false"
3788
+ "auto"
3783
3789
  ], { timeout: WHISPER_TIMEOUT_MS, maxBuffer: 10 * 1024 * 1024 });
3784
- const text = stdout.trim();
3785
3790
  const durationMs = Date.now() - startMs;
3791
+ const { text, count: stripped } = stripSpecialTokens(stdout.trim());
3786
3792
  if (!text) {
3787
3793
  console.error(`${TAG12} failed: whisper returned empty output duration_ms=${durationMs}`);
3788
3794
  return void 0;
@@ -3791,7 +3797,7 @@ async function transcribe(audioPath, mimetype) {
3791
3797
  const language = langMatch?.[1] ?? "unknown";
3792
3798
  const words = text.split(/\s+/).filter(Boolean).length;
3793
3799
  console.error(
3794
- `${TAG12} done provider=whisper-local duration_ms=${durationMs} words=${words} lang=${language}`
3800
+ `${TAG12} done provider=whisper-local duration_ms=${durationMs} words=${words} stripped=${stripped} lang=${language}`
3795
3801
  );
3796
3802
  return { text, language, durationMs };
3797
3803
  } catch (err) {
@@ -4981,7 +4987,7 @@ import { resolve as resolve6, extname } from "path";
4981
4987
 
4982
4988
  // app/lib/data-path.ts
4983
4989
  import { realpathSync } from "fs";
4984
- import { resolve as resolve5, normalize, sep as sep2, relative } from "path";
4990
+ import { resolve as resolve5, normalize, sep as sep2, relative, basename, join as join5 } from "path";
4985
4991
  var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT ?? resolve5(process.cwd(), "../platform");
4986
4992
  var DATA_ROOT = resolve5(PLATFORM_ROOT4, "..", "data");
4987
4993
  var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve5(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
@@ -5044,6 +5050,16 @@ function resolveClaudeUploadsPath(raw) {
5044
5050
  }
5045
5051
  return resolveUnderRoot(raw, CLAUDE_UPLOADS_ROOT, "CLAUDE_UPLOADS_ROOT");
5046
5052
  }
5053
+ function scratchpadTmpBase() {
5054
+ return process.env.MAXY_SCRATCHPAD_BASE ?? "/tmp";
5055
+ }
5056
+ function sessionScratchpadRoot(projectDir, sessionId) {
5057
+ const uid = typeof process.geteuid === "function" ? process.geteuid() : 0;
5058
+ return join5(scratchpadTmpBase(), `claude-${uid}`, basename(projectDir), sessionId, "scratchpad");
5059
+ }
5060
+ function resolveScratchpadPath(raw, scratchpadRootAbs) {
5061
+ return resolveUnderRoot(raw, scratchpadRootAbs, "scratchpad");
5062
+ }
5047
5063
 
5048
5064
  // app/lib/attachments.ts
5049
5065
  function uploadsDirFor(accountId, subPath, attachmentId) {
@@ -5186,7 +5202,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
5186
5202
  // app/lib/stt/voice-note.ts
5187
5203
  import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
5188
5204
  import { tmpdir } from "os";
5189
- import { join as join5 } from "path";
5205
+ import { join as join6 } from "path";
5190
5206
 
5191
5207
  // app/lib/stt/audio-mime.ts
5192
5208
  var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
@@ -5240,9 +5256,9 @@ async function transcribeVoiceNote(file, source) {
5240
5256
  let tempDir;
5241
5257
  let tempPath;
5242
5258
  try {
5243
- tempDir = await mkdtemp(join5(tmpdir(), "voice-"));
5259
+ tempDir = await mkdtemp(join6(tmpdir(), "voice-"));
5244
5260
  const ext = audioExtension(mimeType);
5245
- tempPath = join5(tempDir, `recording${ext}`);
5261
+ tempPath = join6(tempDir, `recording${ext}`);
5246
5262
  const buffer = Buffer.from(await file.arrayBuffer());
5247
5263
  await writeFile3(tempPath, buffer);
5248
5264
  } catch (err) {
@@ -5640,7 +5656,7 @@ ${result.result.text}` : result.result.text;
5640
5656
  }
5641
5657
 
5642
5658
  // server/routes/whatsapp.ts
5643
- import { join as join8, resolve as resolve9 } from "path";
5659
+ import { join as join9, resolve as resolve9 } from "path";
5644
5660
  import { readdirSync as readdirSync3, readFileSync as readFileSync9, existsSync as existsSync5 } from "fs";
5645
5661
 
5646
5662
  // app/lib/whatsapp/login.ts
@@ -5648,7 +5664,7 @@ import { randomUUID as randomUUID6 } from "crypto";
5648
5664
 
5649
5665
  // app/lib/whatsapp/config-persist.ts
5650
5666
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
5651
- import { resolve as resolve7, join as join6 } from "path";
5667
+ import { resolve as resolve7, join as join7 } from "path";
5652
5668
  var TAG16 = "[whatsapp:config]";
5653
5669
  function configPath(accountDir) {
5654
5670
  return resolve7(accountDir, "account.json");
@@ -5800,7 +5816,7 @@ function setPublicAgent(accountDir, slug) {
5800
5816
  if (!trimmed) {
5801
5817
  return { ok: false, error: "Agent slug cannot be empty." };
5802
5818
  }
5803
- const agentConfigPath = join6(accountDir, "agents", trimmed, "config.json");
5819
+ const agentConfigPath = join7(accountDir, "agents", trimmed, "config.json");
5804
5820
  if (!existsSync4(agentConfigPath)) {
5805
5821
  return { ok: false, error: `Agent "${trimmed}" not found \u2014 no config.json at ${agentConfigPath}. Check the agent slug and try again.` };
5806
5822
  }
@@ -6184,7 +6200,7 @@ async function waitForLogin(opts) {
6184
6200
  // app/lib/whatsapp/outbound/send-document.ts
6185
6201
  import { realpathSync as realpathSync3 } from "fs";
6186
6202
  import { readFile, stat as stat2 } from "fs/promises";
6187
- import { resolve as resolve8, basename } from "path";
6203
+ import { resolve as resolve8, basename as basename2 } from "path";
6188
6204
  var TAG18 = "[whatsapp:outbound]";
6189
6205
  var WHATSAPP_DOCUMENT_MAX_BYTES = 100 * 1024 * 1024;
6190
6206
  var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
@@ -6239,7 +6255,7 @@ async function sendWhatsAppDocument(input) {
6239
6255
  error: `File exceeds 100 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
6240
6256
  };
6241
6257
  }
6242
- const filename = basename(resolvedPath);
6258
+ const filename = basename2(resolvedPath);
6243
6259
  const jid = normalizeJid2(to);
6244
6260
  const sock = getSocket(accountId);
6245
6261
  if (!sock) {
@@ -6374,11 +6390,11 @@ function serializeWhatsAppSchema() {
6374
6390
 
6375
6391
  // app/lib/whatsapp/status-reconcile.ts
6376
6392
  import { readdirSync as readdirSync2 } from "fs";
6377
- import { join as join7 } from "path";
6393
+ import { join as join8 } from "path";
6378
6394
  var TAG19 = "[whatsapp:reconcile]";
6379
6395
  function listCredsAccountIds(credsRoot) {
6380
6396
  try {
6381
- return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join7(credsRoot, e.name))).map((e) => e.name);
6397
+ return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join8(credsRoot, e.name))).map((e) => e.name);
6382
6398
  } catch {
6383
6399
  return [];
6384
6400
  }
@@ -6393,7 +6409,7 @@ function reconcileCredsOnDisk(opts) {
6393
6409
  const entries = [];
6394
6410
  for (const accountId of listCredsAccountIds(credsRoot)) {
6395
6411
  if (liveAccountIds.has(accountId)) continue;
6396
- const authDir = join7(credsRoot, accountId);
6412
+ const authDir = join8(credsRoot, accountId);
6397
6413
  const selfPhone = readSelfId(authDir).e164 ?? void 0;
6398
6414
  const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
6399
6415
  console.error(
@@ -6420,7 +6436,7 @@ app2.get("/status", (c) => {
6420
6436
  try {
6421
6437
  const live = getStatus();
6422
6438
  const liveIds = new Set(live.map((a) => a.accountId));
6423
- const credsRoot = join8(MAXY_DIR, "credentials", "whatsapp");
6439
+ const credsRoot = join9(MAXY_DIR, "credentials", "whatsapp");
6424
6440
  const accountDir = resolveAccount()?.accountDir ?? null;
6425
6441
  const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
6426
6442
  const accounts = [...live, ...reconciled];
@@ -6441,7 +6457,7 @@ app2.post("/login/start", async (c) => {
6441
6457
  if (!phone) {
6442
6458
  return c.json({ error: 'Missing required field "phone" (E.164, e.g. +441234567890).' }, 400);
6443
6459
  }
6444
- const authDir = join8(MAXY_DIR, "credentials", "whatsapp", accountId);
6460
+ const authDir = join9(MAXY_DIR, "credentials", "whatsapp", accountId);
6445
6461
  const accountDir = resolveAccount()?.accountDir ?? null;
6446
6462
  const result = await startLogin({ accountId, authDir, phone, accountDir, force });
6447
6463
  console.error(`${TAG20} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
@@ -6855,12 +6871,12 @@ app2.get("/group-info", async (c) => {
6855
6871
  var whatsapp_default = app2;
6856
6872
 
6857
6873
  // server/routes/whatsapp-reader.ts
6858
- import { readFileSync as readFileSync13, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync7 } from "fs";
6859
- import { basename as basename2, dirname, isAbsolute, join as join12, relative as relative2, resolve as resolve11, sep as sep3 } from "path";
6874
+ import { readFileSync as readFileSync13, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync7, realpathSync as realpathSync4 } from "fs";
6875
+ import { basename as basename4, dirname as dirname2, isAbsolute, join as join13, relative as relative2, resolve as resolve11, sep as sep3 } from "path";
6860
6876
 
6861
6877
  // server/routes/admin/sidebar-sessions.ts
6862
6878
  import { readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync2 } from "fs";
6863
- import { join as join9, resolve as resolve10 } from "path";
6879
+ import { basename as basename3, dirname, join as join10, resolve as resolve10 } from "path";
6864
6880
 
6865
6881
  // app/lib/whatsapp-reader/select-sessions.ts
6866
6882
  function isReaderChannelSession(role, channel) {
@@ -6909,6 +6925,14 @@ var app3 = new Hono();
6909
6925
  function claudeConfigDir() {
6910
6926
  return process.env.CLAUDE_CONFIG_DIR ?? null;
6911
6927
  }
6928
+ function findSessionProjectDir(sessionId) {
6929
+ const cfg = claudeConfigDir();
6930
+ if (!cfg) return null;
6931
+ for (const { path: path2 } of enumerateJsonls(join10(cfg, "projects"))) {
6932
+ if (basename3(path2) === `${sessionId}.jsonl`) return dirname(path2);
6933
+ }
6934
+ return null;
6935
+ }
6912
6936
  function enumerateJsonls(projectsRoot) {
6913
6937
  const out = [];
6914
6938
  let slugs;
@@ -6919,7 +6943,7 @@ function enumerateJsonls(projectsRoot) {
6919
6943
  throw err;
6920
6944
  }
6921
6945
  for (const slug of slugs) {
6922
- const slugDir = join9(projectsRoot, slug);
6946
+ const slugDir = join10(projectsRoot, slug);
6923
6947
  let entries;
6924
6948
  try {
6925
6949
  entries = readdirSync4(slugDir, { withFileTypes: true });
@@ -6930,9 +6954,9 @@ function enumerateJsonls(projectsRoot) {
6930
6954
  }
6931
6955
  for (const entry of entries) {
6932
6956
  if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
6933
- out.push({ path: join9(slugDir, entry.name), isSubagent: false, archived: false });
6957
+ out.push({ path: join10(slugDir, entry.name), isSubagent: false, archived: false });
6934
6958
  } else if (entry.isDirectory() && entry.name === "subagents") {
6935
- const subDir = join9(slugDir, entry.name);
6959
+ const subDir = join10(slugDir, entry.name);
6936
6960
  let subEntries;
6937
6961
  try {
6938
6962
  subEntries = readdirSync4(subDir, { withFileTypes: true });
@@ -6943,11 +6967,11 @@ function enumerateJsonls(projectsRoot) {
6943
6967
  }
6944
6968
  for (const sub of subEntries) {
6945
6969
  if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
6946
- out.push({ path: join9(subDir, sub.name), isSubagent: true, archived: false });
6970
+ out.push({ path: join10(subDir, sub.name), isSubagent: true, archived: false });
6947
6971
  }
6948
6972
  }
6949
6973
  } else if (entry.isDirectory() && entry.name === "archive") {
6950
- const archiveDir = join9(slugDir, entry.name);
6974
+ const archiveDir = join10(slugDir, entry.name);
6951
6975
  let archiveEntries;
6952
6976
  try {
6953
6977
  archiveEntries = readdirSync4(archiveDir, { withFileTypes: true });
@@ -6958,7 +6982,7 @@ function enumerateJsonls(projectsRoot) {
6958
6982
  }
6959
6983
  for (const arc of archiveEntries) {
6960
6984
  if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
6961
- out.push({ path: join9(archiveDir, arc.name), isSubagent: false, archived: true });
6985
+ out.push({ path: join10(archiveDir, arc.name), isSubagent: false, archived: true });
6962
6986
  }
6963
6987
  }
6964
6988
  }
@@ -6991,7 +7015,7 @@ async function fetchLiveSessions() {
6991
7015
  function loadUserTitles(accountDir) {
6992
7016
  const out = /* @__PURE__ */ new Map();
6993
7017
  if (!accountDir) return out;
6994
- const path2 = join9(accountDir, "session-titles.json");
7018
+ const path2 = join10(accountDir, "session-titles.json");
6995
7019
  let raw;
6996
7020
  try {
6997
7021
  raw = readFileSync10(path2, "utf8");
@@ -7131,7 +7155,7 @@ app3.get("/", requireAdminSession, async (c) => {
7131
7155
  console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
7132
7156
  return c.json({ sessions: [], accountId, accounts });
7133
7157
  }
7134
- const projectsRoot = join9(configDir2, "projects");
7158
+ const projectsRoot = join10(configDir2, "projects");
7135
7159
  const jsonls = enumerateJsonls(projectsRoot);
7136
7160
  const liveSessions = await fetchLiveSessions();
7137
7161
  const accountDir = accountId ? resolve10(ACCOUNTS_DIR, accountId) : null;
@@ -7167,7 +7191,7 @@ app3.get("/", requireAdminSession, async (c) => {
7167
7191
  const pid = live ? liveSessions.get(sessionId) ?? null : null;
7168
7192
  const resolved = resolveTitle(body, sessionId, userTitles);
7169
7193
  titleSourceCounts[resolved.source] += 1;
7170
- const metaPath = join9(projectDir, `${sessionId}.meta.json`);
7194
+ const metaPath = join10(projectDir, `${sessionId}.meta.json`);
7171
7195
  const { bridgeIds, role, channel: sidecarChannel, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
7172
7196
  if (isReaderChannelSession(role, sidecarChannel)) {
7173
7197
  excludedChannelCount += 1;
@@ -7234,7 +7258,7 @@ var sidebar_sessions_default = app3;
7234
7258
  // app/lib/admin-identity/pin-validator.ts
7235
7259
  import { createHash } from "crypto";
7236
7260
  import { existsSync as existsSync6, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
7237
- import { join as join10 } from "path";
7261
+ import { join as join11 } from "path";
7238
7262
  function hashPin(pin) {
7239
7263
  return createHash("sha256").update(pin).digest("hex");
7240
7264
  }
@@ -7299,7 +7323,7 @@ function resolveOperatorDisplay(userIdRes, nameRes) {
7299
7323
  // app/lib/agent-errors.ts
7300
7324
  function classifyAgentError(err) {
7301
7325
  const msg = err instanceof Error ? err.message : String(err);
7302
- if (/\b(401|authentication_error|OAuth token has expired)\b/i.test(msg)) return "auth_expired";
7326
+ if (/\b(401|authentication_error)\b/i.test(msg)) return "auth_expired";
7303
7327
  if (/\b(529|overloaded)\b/i.test(msg)) return "claude_overloaded";
7304
7328
  if (/\b(404|model_not_found)\b/i.test(msg) || /issue with the selected model|may not have access to it/i.test(msg))
7305
7329
  return "model_unavailable";
@@ -7316,6 +7340,7 @@ var CHANNEL_REPLY_DOCUMENT_TOOL = "mcp__channel__reply-document";
7316
7340
  var SEND_USER_FILE_TOOL = "SendUserFile";
7317
7341
  var CLI_MARKER_PREFIXES2 = ["<local-command-", "<command-name>", "<command-message>"];
7318
7342
  var HARNESS_LIFECYCLE_PREFIXES = ["<task-notification>"];
7343
+ var CC_IMAGE_VISION_HINT = /^\[Image:[^\]]*Multiply coordinates by [\d.]+ to map to original image\.\]$/;
7319
7344
  var COMPACT_SUMMARY_PREFIX = "This session is being continued from a previous conversation that ran out of context.";
7320
7345
  function isCompactSummaryRow(row, content) {
7321
7346
  return row.isCompactSummary === true || content !== null && content.startsWith(COMPACT_SUMMARY_PREFIX);
@@ -7507,6 +7532,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
7507
7532
  if (text === null) continue;
7508
7533
  if (CLI_MARKER_PREFIXES2.some((p) => text.startsWith(p))) continue;
7509
7534
  if (HARNESS_LIFECYCLE_PREFIXES.some((p) => text.startsWith(p))) continue;
7535
+ if (CC_IMAGE_VISION_HINT.test(text)) continue;
7510
7536
  const isChannel = row.isMeta === true && typeof row.origin === "object" && row.origin !== null && row.origin.kind === "channel" || // Native Claude Code channels (maxy-lite) journal the delivery twin as a PLAIN
7511
7537
  // `type:"user"` row whose content is the `<channel source="…">` wrapper, with no
7512
7538
  // `isMeta`/`origin` stamp. Detect it by the wrapper so it is treated as the
@@ -7526,7 +7552,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
7526
7552
 
7527
7553
  // app/lib/whatsapp-reader/enrich-attachments.ts
7528
7554
  import { readFileSync as readFileSync12, readdirSync as readdirSync6 } from "fs";
7529
- import { join as join11 } from "path";
7555
+ import { join as join12 } from "path";
7530
7556
  var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
7531
7557
  function adminAttachmentIds(text) {
7532
7558
  const ids = [];
@@ -7539,7 +7565,7 @@ function adminAttachmentIds(text) {
7539
7565
  function adminAttachmentsFromText(text, uploadsBase) {
7540
7566
  const out = [];
7541
7567
  for (const id of adminAttachmentIds(text)) {
7542
- const meta = readAttachmentMeta(join11(uploadsBase, id));
7568
+ const meta = readAttachmentMeta(join12(uploadsBase, id));
7543
7569
  if (meta) out.push(meta);
7544
7570
  }
7545
7571
  return out;
@@ -7547,7 +7573,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
7547
7573
  function readSidecar(dir, attachmentId) {
7548
7574
  let parsed;
7549
7575
  try {
7550
- parsed = JSON.parse(readFileSync12(join11(dir, `${attachmentId}.meta.json`), "utf8"));
7576
+ parsed = JSON.parse(readFileSync12(join12(dir, `${attachmentId}.meta.json`), "utf8"));
7551
7577
  } catch {
7552
7578
  return null;
7553
7579
  }
@@ -7576,7 +7602,7 @@ function listSessionAttachmentsInDir(dir) {
7576
7602
  }
7577
7603
  const sidecars = [];
7578
7604
  for (const name of entries) {
7579
- const sidecar = readSidecar(join11(dir, name), name);
7605
+ const sidecar = readSidecar(join12(dir, name), name);
7580
7606
  if (sidecar) sidecars.push(sidecar);
7581
7607
  }
7582
7608
  sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
@@ -7621,13 +7647,13 @@ var app4 = new Hono();
7621
7647
  app4.get("/conversations", requireAdminSession, async (c) => {
7622
7648
  const cfg = claudeConfigDir();
7623
7649
  if (!cfg) return c.json({ conversations: [] });
7624
- const projectsRoot = join12(cfg, "projects");
7650
+ const projectsRoot = join13(cfg, "projects");
7625
7651
  const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
7626
7652
  const rows = [];
7627
7653
  for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
7628
- const sessionId = basename2(path2).replace(/\.jsonl$/, "");
7629
- const projectDir = dirname(path2);
7630
- const meta = readSidecarMeta(join12(projectDir, `${sessionId}.meta.json`));
7654
+ const sessionId = basename4(path2).replace(/\.jsonl$/, "");
7655
+ const projectDir = dirname2(path2);
7656
+ const meta = readSidecarMeta(join13(projectDir, `${sessionId}.meta.json`));
7631
7657
  if (!isReaderChannelSession(meta.role, meta.channel)) continue;
7632
7658
  let body = "";
7633
7659
  try {
@@ -7715,11 +7741,30 @@ function resumeOffset(lastEventId, fileEnd) {
7715
7741
  if (!Number.isFinite(n) || n < 0) return 0;
7716
7742
  return Math.min(n, fileEnd);
7717
7743
  }
7718
- function enrichDownloads(turn) {
7744
+ function enrichDownloads(turn, scratchpadRoot) {
7719
7745
  if (turn.kind !== "agent-file") return turn;
7746
+ let scratchpadReal = null;
7747
+ try {
7748
+ scratchpadReal = realpathSync4(scratchpadRoot);
7749
+ } catch {
7750
+ scratchpadReal = null;
7751
+ }
7720
7752
  const downloads = turn.files.map((f) => {
7721
- const rel = relative2(DATA_ROOT, f);
7722
- return !rel || rel.startsWith("..") || isAbsolute(rel) ? null : rel;
7753
+ const dataRel = relative2(DATA_ROOT, f);
7754
+ if (dataRel && !dataRel.startsWith("..") && !isAbsolute(dataRel)) {
7755
+ return { root: "data", path: dataRel };
7756
+ }
7757
+ if (scratchpadReal) {
7758
+ try {
7759
+ const fileReal = realpathSync4(f);
7760
+ if (fileReal === scratchpadReal || fileReal.startsWith(scratchpadReal + sep3)) {
7761
+ return { root: "scratchpad", path: relative2(scratchpadReal, fileReal) };
7762
+ }
7763
+ } catch {
7764
+ }
7765
+ }
7766
+ console.error(`[data] op=agent-file-unmapped path="${f}"`);
7767
+ return null;
7723
7768
  });
7724
7769
  return { ...turn, downloads };
7725
7770
  }
@@ -7764,7 +7809,7 @@ function openTaskKey(turns) {
7764
7809
  }
7765
7810
  function readSubagentMeta(dir, hex) {
7766
7811
  try {
7767
- const m = JSON.parse(readFileSync13(join12(dir, `agent-${hex}.meta.json`), "utf8"));
7812
+ const m = JSON.parse(readFileSync13(join13(dir, `agent-${hex}.meta.json`), "utf8"));
7768
7813
  if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
7769
7814
  return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
7770
7815
  }
@@ -7796,7 +7841,7 @@ function runActivityTick(c) {
7796
7841
  let size = 0;
7797
7842
  let mtimeMs = 0;
7798
7843
  try {
7799
- const st = statSync4(join12(c.subagentsDir, name));
7844
+ const st = statSync4(join13(c.subagentsDir, name));
7800
7845
  size = st.size;
7801
7846
  mtimeMs = st.mtimeMs;
7802
7847
  } catch {
@@ -7841,14 +7886,15 @@ app4.get("/stream", requireAdminSession, (c) => {
7841
7886
  const sessionId = c.req.query("sessionId") ?? "";
7842
7887
  const projectDir = c.req.query("projectDir") ?? "";
7843
7888
  const cfg = claudeConfigDir();
7844
- const projectsRoot = cfg ? resolve11(join12(cfg, "projects")) : null;
7889
+ const projectsRoot = cfg ? resolve11(join13(cfg, "projects")) : null;
7845
7890
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
7846
7891
  return c.json({ error: "bad session reference" }, 400);
7847
7892
  }
7848
- const jsonlPath = resolve11(join12(projectDir, `${sessionId}.jsonl`));
7893
+ const jsonlPath = resolve11(join13(projectDir, `${sessionId}.jsonl`));
7849
7894
  if (!jsonlPath.startsWith(projectsRoot + sep3)) {
7850
7895
  return c.json({ error: "bad session reference" }, 400);
7851
7896
  }
7897
+ const scratchpadRoot = sessionScratchpadRoot(projectDir, sessionId);
7852
7898
  const encoder = new TextEncoder();
7853
7899
  const send = (controller, turn, id) => controller.enqueue(encoder.encode(`id: ${id}
7854
7900
  data: ${JSON.stringify(turn)}
@@ -7869,7 +7915,7 @@ data: ${JSON.stringify(turn)}
7869
7915
  let offset = resumeOffset(lastEventId, fileEnd0);
7870
7916
  console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
7871
7917
  const sessionKey = c.req.query("session_key") ?? "";
7872
- const subagentsDir = resolve11(join12(projectDir, sessionId, "subagents"));
7918
+ const subagentsDir = resolve11(join13(projectDir, sessionId, "subagents"));
7873
7919
  console.log(
7874
7920
  `[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync7(subagentsDir)}`
7875
7921
  );
@@ -7896,7 +7942,7 @@ data: ${JSON.stringify(obj)}
7896
7942
  offset = nextOffset;
7897
7943
  let n = 0;
7898
7944
  for (const turn of parseTranscript(lines, queuedPendingSuppress)) {
7899
- send(controller, enrichAdminAttachments(enrichDownloads(turn)), offset);
7945
+ send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
7900
7946
  actx.lastParentTurns.push(turn);
7901
7947
  if (turn.kind === "agent-error") {
7902
7948
  console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
@@ -7916,7 +7962,7 @@ data: ${JSON.stringify(obj)}
7916
7962
  offset = end;
7917
7963
  let n = 0;
7918
7964
  for (const turn of parseTranscript(buf.toString("utf8").split("\n"), queuedPendingSuppress)) {
7919
- send(controller, enrichAdminAttachments(enrichDownloads(turn)), offset);
7965
+ send(controller, enrichAdminAttachments(enrichDownloads(turn, scratchpadRoot)), offset);
7920
7966
  actx.lastParentTurns.push(turn);
7921
7967
  if (turn.kind === "agent-error") {
7922
7968
  console.log(`[wa-stream] op=agent-error conn=${connId} sessionId=${sessionId} code=${turn.code} source=jsonl`);
@@ -7990,7 +8036,7 @@ app4.get("/directives", requireAdminSession, (c) => {
7990
8036
  const pid = Number(pidPart);
7991
8037
  let len = 0;
7992
8038
  try {
7993
- len = statSync4(join12(dir, name)).size;
8039
+ len = statSync4(join13(dir, name)).size;
7994
8040
  } catch {
7995
8041
  }
7996
8042
  return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
@@ -8005,7 +8051,7 @@ app4.get("/directive", requireAdminSession, (c) => {
8005
8051
  }
8006
8052
  const dir = directiveStoreDir(sessionId);
8007
8053
  if (!dir) return c.json({ error: "no account" }, 404);
8008
- const path2 = resolve11(join12(dir, name));
8054
+ const path2 = resolve11(join13(dir, name));
8009
8055
  if (!path2.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
8010
8056
  let body;
8011
8057
  try {
@@ -8019,7 +8065,7 @@ var whatsapp_reader_default = app4;
8019
8065
 
8020
8066
  // server/routes/public-reader.ts
8021
8067
  import { statSync as statSync5, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "fs";
8022
- import { basename as basename3, dirname as dirname2, join as join13, resolve as resolve12, sep as sep4 } from "path";
8068
+ import { basename as basename5, dirname as dirname3, join as join14, resolve as resolve12, sep as sep4 } from "path";
8023
8069
 
8024
8070
  // app/lib/whatsapp-reader/delivered-kinds.ts
8025
8071
  var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
@@ -8093,10 +8139,10 @@ function enumeratePublicRows() {
8093
8139
  const cfg = claudeConfigDir();
8094
8140
  if (!cfg) return [];
8095
8141
  const rows = [];
8096
- for (const { path: path2 } of enumerateJsonls(join13(cfg, "projects"))) {
8097
- const sessionId = basename3(path2).replace(/\.jsonl$/, "");
8098
- const projectDir = dirname2(path2);
8099
- const meta = readSidecarMeta(join13(projectDir, `${sessionId}.meta.json`));
8142
+ for (const { path: path2 } of enumerateJsonls(join14(cfg, "projects"))) {
8143
+ const sessionId = basename5(path2).replace(/\.jsonl$/, "");
8144
+ const projectDir = dirname3(path2);
8145
+ const meta = readSidecarMeta(join14(projectDir, `${sessionId}.meta.json`));
8100
8146
  rows.push({
8101
8147
  sessionId,
8102
8148
  projectDir,
@@ -8172,15 +8218,15 @@ app5.get("/stream", (c) => {
8172
8218
  const sessionId = c.req.query("sessionId") ?? "";
8173
8219
  const projectDir = c.req.query("projectDir") ?? "";
8174
8220
  const cfg = claudeConfigDir();
8175
- const projectsRoot = cfg ? resolve12(join13(cfg, "projects")) : null;
8221
+ const projectsRoot = cfg ? resolve12(join14(cfg, "projects")) : null;
8176
8222
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
8177
8223
  return c.json({ error: "bad session reference" }, 400);
8178
8224
  }
8179
- const jsonlPath = resolve12(join13(projectDir, `${sessionId}.jsonl`));
8225
+ const jsonlPath = resolve12(join14(projectDir, `${sessionId}.jsonl`));
8180
8226
  if (!jsonlPath.startsWith(projectsRoot + sep4)) {
8181
8227
  return c.json({ error: "bad session reference" }, 400);
8182
8228
  }
8183
- const meta = readSidecarMeta(join13(projectDir, `${sessionId}.meta.json`));
8229
+ const meta = readSidecarMeta(join14(projectDir, `${sessionId}.meta.json`));
8184
8230
  const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
8185
8231
  const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
8186
8232
  if (!(isPublicWebchat && owns)) {
@@ -8313,17 +8359,17 @@ app5.get("/attachment/:attachmentId", (c) => {
8313
8359
  var public_reader_default = app5;
8314
8360
 
8315
8361
  // server/routes/webchat.ts
8316
- import { basename as basename4, dirname as dirname3 } from "path";
8317
- import { join as join16 } from "path";
8362
+ import { basename as basename6, dirname as dirname4 } from "path";
8363
+ import { join as join17 } from "path";
8318
8364
  import { existsSync as existsSync9, readdirSync as readdirSync10, readFileSync as readFileSync17, renameSync as renameSync3, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
8319
8365
 
8320
8366
  // server/canonical-webchat-override.ts
8321
8367
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync5, renameSync } from "fs";
8322
- import { join as join14 } from "path";
8368
+ import { join as join15 } from "path";
8323
8369
  var FILE = "canonical-webchat-session.json";
8324
8370
  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}$/;
8325
8371
  function canonicalOverridePath(accountDir) {
8326
- return join14(accountDir, FILE);
8372
+ return join15(accountDir, FILE);
8327
8373
  }
8328
8374
  function readRaw(accountDir) {
8329
8375
  try {
@@ -8373,7 +8419,7 @@ function adminSessionIdFor(accountId, senderId, personId) {
8373
8419
 
8374
8420
  // ../lib/models/src/index.ts
8375
8421
  var OPUS_MODEL = "claude-opus-4-8[1m]";
8376
- var SONNET_MODEL = "claude-sonnet-4-6";
8422
+ var SONNET_MODEL = "claude-sonnet-5";
8377
8423
  var HAIKU_MODEL = "claude-haiku-4-5";
8378
8424
  var MODEL_CONTEXT_WINDOW = {
8379
8425
  [OPUS_MODEL]: 1e6,
@@ -8385,7 +8431,7 @@ function contextWindow(model) {
8385
8431
  }
8386
8432
  var MODEL_DISPLAY_NAMES = {
8387
8433
  [OPUS_MODEL]: "Opus 4.8 (1M context)",
8388
- [SONNET_MODEL]: "Sonnet 4.6",
8434
+ [SONNET_MODEL]: "Sonnet 5",
8389
8435
  [HAIKU_MODEL]: "Haiku 4.5"
8390
8436
  };
8391
8437
  var SELECTABLE_MODELS = [OPUS_MODEL, SONNET_MODEL, HAIKU_MODEL];
@@ -8415,7 +8461,7 @@ function isNewSessionEffortLevel(value) {
8415
8461
 
8416
8462
  // ../services/claude-session-manager/src/sidecar-store.ts
8417
8463
  import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync as readdirSync9, readFileSync as readFileSync16, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
8418
- import { join as join15 } from "path";
8464
+ import { join as join16 } from "path";
8419
8465
  function escapeRegExp(s) {
8420
8466
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8421
8467
  }
@@ -8423,7 +8469,7 @@ function createSidecarStore(config) {
8423
8469
  const { suffix, validate: validate2 } = config;
8424
8470
  const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
8425
8471
  function pathFor(sessionsDir, id) {
8426
- return join15(sessionsDir, `${id}${suffix}`);
8472
+ return join16(sessionsDir, `${id}${suffix}`);
8427
8473
  }
8428
8474
  function write(sessionsDir, id, record) {
8429
8475
  mkdirSync2(sessionsDir, { recursive: true });
@@ -8467,7 +8513,7 @@ function createSidecarStore(config) {
8467
8513
  const out = [];
8468
8514
  for (const name of names) {
8469
8515
  if (!suffixRe.test(name)) continue;
8470
- const path2 = join15(sessionsDir, name);
8516
+ const path2 = join16(sessionsDir, name);
8471
8517
  let raw;
8472
8518
  try {
8473
8519
  raw = readFileSync16(path2, "utf8");
@@ -8542,21 +8588,15 @@ function resolveBridgeSource(sessionsDir, forkSessionId, jsonlExists, maxDepth =
8542
8588
  var WEBCHAT_ADMIN_KEY = "webchat-admin";
8543
8589
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8544
8590
  function locateSession(sessionId) {
8545
- const cfg = claudeConfigDir();
8546
- if (!cfg) return { projectDir: null, channel: null };
8547
- for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
8548
- if (basename4(path2) === `${sessionId}.jsonl`) {
8549
- const dir = dirname3(path2);
8550
- const meta = readSidecarMeta(join16(dir, `${sessionId}.meta.json`));
8551
- return { projectDir: dir, channel: meta.channel };
8552
- }
8553
- }
8554
- return { projectDir: null, channel: null };
8591
+ const dir = findSessionProjectDir(sessionId);
8592
+ if (!dir) return { projectDir: null, channel: null };
8593
+ const meta = readSidecarMeta(join17(dir, `${sessionId}.meta.json`));
8594
+ return { projectDir: dir, channel: meta.channel };
8555
8595
  }
8556
8596
  function locateSidecar(sessionId) {
8557
8597
  const cfg = claudeConfigDir();
8558
8598
  if (!cfg) return null;
8559
- const projectsRoot = join16(cfg, "projects");
8599
+ const projectsRoot = join17(cfg, "projects");
8560
8600
  let slugs;
8561
8601
  try {
8562
8602
  slugs = readdirSync10(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
@@ -8564,7 +8604,7 @@ function locateSidecar(sessionId) {
8564
8604
  return null;
8565
8605
  }
8566
8606
  for (const slug of slugs) {
8567
- const metaPath = join16(projectsRoot, slug, `${sessionId}.meta.json`);
8607
+ const metaPath = join17(projectsRoot, slug, `${sessionId}.meta.json`);
8568
8608
  if (existsSync9(metaPath)) {
8569
8609
  const meta = readSidecarMeta(metaPath);
8570
8610
  return { channel: meta.channel, adminUserId: meta.adminUserId };
@@ -8577,7 +8617,7 @@ function readTargetOwner(sessionId) {
8577
8617
  if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
8578
8618
  const { projectDir } = locateSession(sessionId);
8579
8619
  if (projectDir !== null) {
8580
- return { found: true, owner: readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`)).adminUserId };
8620
+ return { found: true, owner: readSidecarMeta(join17(projectDir, `${sessionId}.meta.json`)).adminUserId };
8581
8621
  }
8582
8622
  return { found: false, owner: null };
8583
8623
  }
@@ -8591,7 +8631,7 @@ function sessionSidecarExists(sessionId) {
8591
8631
  function jsonlSizeBytes(projectDir, sessionId) {
8592
8632
  if (projectDir === null) return null;
8593
8633
  try {
8594
- return statSync6(join16(projectDir, `${sessionId}.jsonl`)).size;
8634
+ return statSync6(join17(projectDir, `${sessionId}.jsonl`)).size;
8595
8635
  } catch {
8596
8636
  return null;
8597
8637
  }
@@ -8726,10 +8766,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId) {
8726
8766
  const cfg = claudeConfigDir();
8727
8767
  if (!cfg) return null;
8728
8768
  let best = null;
8729
- for (const { path: path2, isSubagent, archived } of enumerateJsonls(join16(cfg, "projects"))) {
8769
+ for (const { path: path2, isSubagent, archived } of enumerateJsonls(join17(cfg, "projects"))) {
8730
8770
  if (isSubagent || archived) continue;
8731
- const id = basename4(path2).slice(0, -".jsonl".length);
8732
- const meta = readSidecarMeta(join16(dirname3(path2), `${id}.meta.json`));
8771
+ const id = basename6(path2).slice(0, -".jsonl".length);
8772
+ const meta = readSidecarMeta(join17(dirname4(path2), `${id}.meta.json`));
8733
8773
  if (meta.role !== "admin" || meta.channel !== "webchat") continue;
8734
8774
  let mtimeMs;
8735
8775
  try {
@@ -8751,7 +8791,7 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId) {
8751
8791
  function overrideKnownNonArchived(id) {
8752
8792
  const { projectDir } = locateSession(id);
8753
8793
  if (projectDir === null) return sessionSidecarExists(id);
8754
- return basename4(projectDir) !== "archive";
8794
+ return basename6(projectDir) !== "archive";
8755
8795
  }
8756
8796
  function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId) {
8757
8797
  if (requesterUserId === null) {
@@ -9024,7 +9064,7 @@ ${note}` : note;
9024
9064
  console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
9025
9065
  return c.json({ error: "account unresolved" }, 503);
9026
9066
  }
9027
- const accountJsonPath = join16(account.accountDir, "account.json");
9067
+ const accountJsonPath = join17(account.accountDir, "account.json");
9028
9068
  try {
9029
9069
  const parsed = JSON.parse(readFileSync17(accountJsonPath, "utf8"));
9030
9070
  if (op === "model") parsed.adminModel = value;
@@ -9070,7 +9110,7 @@ ${note}` : note;
9070
9110
  const cfg2 = claudeConfigDir();
9071
9111
  if (cfg2) {
9072
9112
  const source2 = resolveBridgeSource(
9073
- join16(cfg2, "sessions"),
9113
+ join17(cfg2, "sessions"),
9074
9114
  target,
9075
9115
  (id) => locateSession(id).projectDir !== null
9076
9116
  );
@@ -9102,15 +9142,15 @@ ${note}` : note;
9102
9142
  const cfg = claudeConfigDir();
9103
9143
  let projectDir = null;
9104
9144
  if (cfg) {
9105
- for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
9106
- if (basename4(path2) === `${sessionId}.jsonl`) {
9107
- projectDir = dirname3(path2);
9145
+ for (const { path: path2 } of enumerateJsonls(join17(cfg, "projects"))) {
9146
+ if (basename6(path2) === `${sessionId}.jsonl`) {
9147
+ projectDir = dirname4(path2);
9108
9148
  break;
9109
9149
  }
9110
9150
  }
9111
9151
  }
9112
9152
  if (source === "latest" && requesterUserId !== null) {
9113
- const owner = readSidecarMeta(join16(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
9153
+ const owner = readSidecarMeta(join17(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
9114
9154
  if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
9115
9155
  console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
9116
9156
  }
@@ -9143,7 +9183,7 @@ import { resolve as resolve13 } from "path";
9143
9183
 
9144
9184
  // app/lib/claude-agent/specialist-roster.ts
9145
9185
  import { existsSync as existsSync10, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "fs";
9146
- import { join as join17 } from "path";
9186
+ import { join as join18 } from "path";
9147
9187
  function field(fm, name) {
9148
9188
  const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
9149
9189
  if (!m) return null;
@@ -9162,7 +9202,7 @@ function readSpecialistRoster(specialistsDir) {
9162
9202
  if (!file.endsWith(".md")) continue;
9163
9203
  let raw;
9164
9204
  try {
9165
- raw = readFileSync18(join17(specialistsDir, file), "utf-8");
9205
+ raw = readFileSync18(join18(specialistsDir, file), "utf-8");
9166
9206
  } catch (err) {
9167
9207
  skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
9168
9208
  continue;
@@ -9279,7 +9319,7 @@ var webchat_greeting_default = app6;
9279
9319
 
9280
9320
  // server/routes/telegram.ts
9281
9321
  import { homedir } from "os";
9282
- import { resolve as resolve14, join as join18 } from "path";
9322
+ import { resolve as resolve14, join as join19 } from "path";
9283
9323
  import { existsSync as existsSync11, readFileSync as readFileSync19 } from "fs";
9284
9324
 
9285
9325
  // app/lib/telegram/gateway/instance.ts
@@ -9339,7 +9379,7 @@ function routeTelegramUpdate(input) {
9339
9379
  var TAG22 = "[telegram-inbound]";
9340
9380
  function configDirName() {
9341
9381
  const platformRoot3 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
9342
- const brandPath = join18(platformRoot3, "config", "brand.json");
9382
+ const brandPath = join19(platformRoot3, "config", "brand.json");
9343
9383
  if (existsSync11(brandPath)) {
9344
9384
  try {
9345
9385
  return JSON.parse(readFileSync19(brandPath, "utf-8")).configDir ?? ".maxy";
@@ -9441,16 +9481,16 @@ app7.post("/", async (c) => {
9441
9481
  var telegram_default = app7;
9442
9482
 
9443
9483
  // server/routes/quickbooks.ts
9444
- import { join as join19 } from "path";
9484
+ import { join as join20 } from "path";
9445
9485
  import { existsSync as existsSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, rmSync, renameSync as renameSync4 } from "fs";
9446
9486
  var TAG23 = "[quickbooks]";
9447
9487
  var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
9448
9488
  var STATE_RE = /^[A-Za-z0-9_-]+$/;
9449
9489
  function pendingPath(accountDir, state) {
9450
- return join19(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
9490
+ return join20(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
9451
9491
  }
9452
9492
  function storePath(accountDir) {
9453
- return join19(accountDir, "secrets", "quickbooks.json");
9493
+ return join20(accountDir, "secrets", "quickbooks.json");
9454
9494
  }
9455
9495
  async function completeConsent(args) {
9456
9496
  const { accountDir, code, realmId } = args;
@@ -9517,7 +9557,7 @@ async function completeConsent(args) {
9517
9557
  refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
9518
9558
  lastRefresh: now
9519
9559
  };
9520
- mkdirSync3(join19(accountDir, "secrets"), { recursive: true });
9560
+ mkdirSync3(join20(accountDir, "secrets"), { recursive: true });
9521
9561
  writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
9522
9562
  const persisted = JSON.parse(readFileSync20(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
9523
9563
  console.error(`${TAG23} op=token-exchange realmId=${realmId} persisted=${persisted}`);
@@ -9555,7 +9595,7 @@ import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
9555
9595
 
9556
9596
  // ../lib/admins-write/src/index.ts
9557
9597
  import { existsSync as existsSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync9, renameSync as renameSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync12, statSync as statSync7, appendFileSync } from "fs";
9558
- import { dirname as dirname4, join as join20 } from "path";
9598
+ import { dirname as dirname5, join as join21 } from "path";
9559
9599
  function id8(value) {
9560
9600
  return value.slice(0, 8);
9561
9601
  }
@@ -9568,7 +9608,7 @@ function appendUsersAuditLine(audit, fields) {
9568
9608
  const line = `[users-audit] action=${fields.action} actor=${actor}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
9569
9609
  `;
9570
9610
  try {
9571
- mkdirSync4(dirname4(audit.logFile), { recursive: true, mode: 448 });
9611
+ mkdirSync4(dirname5(audit.logFile), { recursive: true, mode: 448 });
9572
9612
  appendFileSync(audit.logFile, line, { mode: 384 });
9573
9613
  } catch (err) {
9574
9614
  console.error(
@@ -9586,7 +9626,7 @@ function logLine(input, result) {
9586
9626
  );
9587
9627
  }
9588
9628
  function writeFileAtomic(filePath, contents, mode) {
9589
- mkdirSync4(dirname4(filePath), { recursive: true });
9629
+ mkdirSync4(dirname5(filePath), { recursive: true });
9590
9630
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
9591
9631
  writeFileSync9(tempPath, contents, mode !== void 0 ? { mode } : void 0);
9592
9632
  renameSync5(tempPath, filePath);
@@ -9627,7 +9667,7 @@ function writeAdminEntry(input) {
9627
9667
  return result;
9628
9668
  }
9629
9669
  try {
9630
- const accountJsonPath = join20(input.accountDir, "account.json");
9670
+ const accountJsonPath = join21(input.accountDir, "account.json");
9631
9671
  if (!existsSync13(accountJsonPath)) {
9632
9672
  throw new Error(`account.json not found at ${accountJsonPath}`);
9633
9673
  }
@@ -9675,13 +9715,13 @@ function computeAdminStoreDivergence(input) {
9675
9715
  }
9676
9716
  for (const entry of entries) {
9677
9717
  if (entry.startsWith(".")) continue;
9678
- const accountDir = join20(input.accountsDir, entry);
9718
+ const accountDir = join21(input.accountsDir, entry);
9679
9719
  try {
9680
9720
  if (!statSync7(accountDir).isDirectory()) continue;
9681
9721
  } catch {
9682
9722
  continue;
9683
9723
  }
9684
- const accountJsonPath = join20(accountDir, "account.json");
9724
+ const accountJsonPath = join21(accountDir, "account.json");
9685
9725
  if (!existsSync13(accountJsonPath)) continue;
9686
9726
  let admins = [];
9687
9727
  try {
@@ -10078,8 +10118,8 @@ var onboarding_default = app9;
10078
10118
 
10079
10119
  // server/routes/client-error.ts
10080
10120
  import { appendFileSync as appendFileSync2, existsSync as existsSync15, renameSync as renameSync6, statSync as statSync8 } from "fs";
10081
- import { join as join21 } from "path";
10082
- var CLIENT_ERRORS_LOG = join21(LOG_DIR, "client-errors.log");
10121
+ import { join as join22 } from "path";
10122
+ var CLIENT_ERRORS_LOG = join22(LOG_DIR, "client-errors.log");
10083
10123
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
10084
10124
  var MAX_BODY_SIZE = 8 * 1024;
10085
10125
  var MAX_STACK_LEN = 2e3;
@@ -10409,16 +10449,16 @@ var session_default = app11;
10409
10449
 
10410
10450
  // server/routes/admin/logs.ts
10411
10451
  import { existsSync as existsSync17, readdirSync as readdirSync13, readFileSync as readFileSync23, statSync as statSync9 } from "fs";
10412
- import { resolve as resolve15, basename as basename5 } from "path";
10452
+ import { resolve as resolve15, basename as basename7 } from "path";
10413
10453
 
10414
10454
  // app/lib/logs-read-resolve.ts
10415
10455
  import { existsSync as existsSync16 } from "fs";
10416
- import { join as join22 } from "path";
10456
+ import { join as join23 } from "path";
10417
10457
  function resolveSessionLogPaths(filename, logDirs) {
10418
10458
  const tried = [filename];
10419
10459
  const hits = [];
10420
10460
  for (const dir of logDirs) {
10421
- const fullPath = join22(dir, filename);
10461
+ const fullPath = join23(dir, filename);
10422
10462
  if (existsSync16(fullPath)) {
10423
10463
  hits.push({ path: fullPath, dir });
10424
10464
  }
@@ -10441,7 +10481,7 @@ app12.get("/", async (c) => {
10441
10481
  if (accountLogDir) logDirs.push(accountLogDir);
10442
10482
  logDirs.push(LOG_DIR);
10443
10483
  if (fileParam) {
10444
- const safe = basename5(fileParam);
10484
+ const safe = basename7(fileParam);
10445
10485
  const searched = [];
10446
10486
  for (const dir of logDirs) {
10447
10487
  const filePath = resolve15(dir, safe);
@@ -10511,7 +10551,7 @@ app12.get("/", async (c) => {
10511
10551
  if (hit) {
10512
10552
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
10513
10553
  try {
10514
- const filename = basename5(hit.path);
10554
+ const filename = basename7(hit.path);
10515
10555
  const buffer = readFileSync23(hit.path);
10516
10556
  const onDiskBytes = statSync9(hit.path).size;
10517
10557
  const headers = {
@@ -11420,7 +11460,7 @@ var sessions_default = app16;
11420
11460
 
11421
11461
  // app/lib/claude-agent/spawn-context.ts
11422
11462
  import { existsSync as existsSync21, readFileSync as readFileSync25, readdirSync as readdirSync15, statSync as statSync10 } from "fs";
11423
- import { dirname as dirname5, resolve as resolve18, join as join23 } from "path";
11463
+ import { dirname as dirname6, resolve as resolve18, join as join24 } from "path";
11424
11464
  async function resolveOwnerProfileBlock(accountId, userId) {
11425
11465
  if (!userId) return { ok: false, reason: "missing-user-id" };
11426
11466
  try {
@@ -11461,8 +11501,8 @@ function frontmatterField(manifest, field2) {
11461
11501
  function extractPluginToolDescriptions(pluginDir) {
11462
11502
  const out = /* @__PURE__ */ new Map();
11463
11503
  const candidates = [
11464
- join23(pluginDir, "mcp/dist/index.js"),
11465
- join23(pluginDir, "mcp/src/index.ts")
11504
+ join24(pluginDir, "mcp/dist/index.js"),
11505
+ join24(pluginDir, "mcp/src/index.ts")
11466
11506
  ];
11467
11507
  let raw = null;
11468
11508
  for (const path2 of candidates) {
@@ -11520,21 +11560,21 @@ function listPluginDirs() {
11520
11560
  const platformPlugins = resolve18(PLATFORM_ROOT, "plugins");
11521
11561
  if (existsSync21(platformPlugins)) {
11522
11562
  for (const name of readdirSync15(platformPlugins)) {
11523
- const dir = join23(platformPlugins, name);
11563
+ const dir = join24(platformPlugins, name);
11524
11564
  try {
11525
11565
  if (statSync10(dir).isDirectory()) out.set(name, dir);
11526
11566
  } catch {
11527
11567
  }
11528
11568
  }
11529
11569
  }
11530
- const premiumRoot = resolve18(dirname5(PLATFORM_ROOT), "premium-plugins");
11570
+ const premiumRoot = resolve18(dirname6(PLATFORM_ROOT), "premium-plugins");
11531
11571
  if (existsSync21(premiumRoot)) {
11532
11572
  for (const bundle of readdirSync15(premiumRoot)) {
11533
- const bundlePlugins = join23(premiumRoot, bundle, "plugins");
11573
+ const bundlePlugins = join24(premiumRoot, bundle, "plugins");
11534
11574
  if (!existsSync21(bundlePlugins)) continue;
11535
11575
  try {
11536
11576
  for (const name of readdirSync15(bundlePlugins)) {
11537
- const dir = join23(bundlePlugins, name);
11577
+ const dir = join24(bundlePlugins, name);
11538
11578
  try {
11539
11579
  if (statSync10(dir).isDirectory()) out.set(name, dir);
11540
11580
  } catch {
@@ -11577,7 +11617,7 @@ function computeActivePlugins(accountId) {
11577
11617
  for (const name of Array.from(enabled).sort()) {
11578
11618
  const dir = pluginDirs.get(name);
11579
11619
  if (!dir) continue;
11580
- const fm = readFrontmatter(join23(dir, "PLUGIN.md"));
11620
+ const fm = readFrontmatter(join24(dir, "PLUGIN.md"));
11581
11621
  if (!fm) continue;
11582
11622
  const description = frontmatterField(`---
11583
11623
  ${fm}
@@ -11594,7 +11634,7 @@ ${fm}
11594
11634
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
11595
11635
  );
11596
11636
  if (toolNames.length > 0 && descMap.size === 0) {
11597
- const hasSource = existsSync21(join23(dir, "mcp/dist/index.js")) || existsSync21(join23(dir, "mcp/src/index.ts"));
11637
+ const hasSource = existsSync21(join24(dir, "mcp/dist/index.js")) || existsSync21(join24(dir, "mcp/src/index.ts"));
11598
11638
  if (hasSource) {
11599
11639
  console.warn(
11600
11640
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -11604,7 +11644,7 @@ ${fm}
11604
11644
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
11605
11645
  const skills = [];
11606
11646
  for (const relPath of skillPaths) {
11607
- const skillPath = join23(dir, relPath);
11647
+ const skillPath = join24(dir, relPath);
11608
11648
  const skillFm = readFrontmatter(skillPath);
11609
11649
  if (!skillFm) continue;
11610
11650
  const skillName = frontmatterField(`---
@@ -11648,7 +11688,7 @@ function computeSpecialistDomains(accountId) {
11648
11688
  const out = [];
11649
11689
  for (const file of entries.sort()) {
11650
11690
  if (!file.endsWith(".md")) continue;
11651
- const fm = readFrontmatter(join23(specialistsDir, file));
11691
+ const fm = readFrontmatter(join24(specialistsDir, file));
11652
11692
  if (!fm) continue;
11653
11693
  const wrapped = `---
11654
11694
  ${fm}
@@ -11974,9 +12014,9 @@ var events_default = app19;
11974
12014
  // server/routes/admin/files.ts
11975
12015
  import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync23 } from "fs";
11976
12016
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
11977
- import { realpathSync as realpathSync4 } from "fs";
12017
+ import { realpathSync as realpathSync5 } from "fs";
11978
12018
  import { randomUUID as randomUUID9 } from "crypto";
11979
- import { basename as basename7, dirname as dirname6, join as join25, relative as relative4, resolve as resolve21, sep as sep6 } from "path";
12019
+ import { basename as basename9, dirname as dirname7, join as join26, relative as relative4, resolve as resolve21, sep as sep6 } from "path";
11980
12020
  import { Readable as Readable2 } from "stream";
11981
12021
 
11982
12022
  // ../lib/graph-trash/src/index.ts
@@ -12294,7 +12334,7 @@ async function cascadeDeleteDocument(params) {
12294
12334
 
12295
12335
  // app/lib/file-index.ts
12296
12336
  import * as fsp from "fs/promises";
12297
- import { resolve as resolve20, relative as relative3, join as join24, basename as basename6, extname as extname2, sep as sep5 } from "path";
12337
+ import { resolve as resolve20, relative as relative3, join as join25, basename as basename8, extname as extname2, sep as sep5 } from "path";
12298
12338
  import { tmpdir as tmpdir2 } from "os";
12299
12339
  import { execFile as execFile2 } from "child_process";
12300
12340
  import { promisify as promisify2 } from "util";
@@ -12376,7 +12416,7 @@ async function extractPdf(absolute) {
12376
12416
  return stdout.trim();
12377
12417
  }
12378
12418
  async function ocrPdf(absolute) {
12379
- const outPdf = join24(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
12419
+ const outPdf = join25(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
12380
12420
  try {
12381
12421
  await execFileAsync2(
12382
12422
  "ocrmypdf",
@@ -12432,13 +12472,13 @@ async function extractFileContent(absolute) {
12432
12472
  }
12433
12473
  }
12434
12474
  async function readDisplayName(absolute) {
12435
- const dir = absolute.slice(0, absolute.length - basename6(absolute).length);
12436
- const base = basename6(absolute);
12475
+ const dir = absolute.slice(0, absolute.length - basename8(absolute).length);
12476
+ const base = basename8(absolute);
12437
12477
  const dot = base.lastIndexOf(".");
12438
12478
  const stem = dot === -1 ? base : base.slice(0, dot);
12439
12479
  if (base === `${stem}.meta.json`) return null;
12440
12480
  try {
12441
- const raw = await fsp.readFile(join24(dir, `${stem}.meta.json`), "utf-8");
12481
+ const raw = await fsp.readFile(join25(dir, `${stem}.meta.json`), "utf-8");
12442
12482
  const meta = JSON.parse(raw);
12443
12483
  const dn = meta.displayName ?? meta.filename;
12444
12484
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -12459,7 +12499,7 @@ async function walkSubtree(root, dataRoot, out) {
12459
12499
  for (const entry of entries) {
12460
12500
  if (entry.isSymbolicLink()) continue;
12461
12501
  if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
12462
- const abs = join24(root, entry.name);
12502
+ const abs = join25(root, entry.name);
12463
12503
  if (entry.isDirectory()) {
12464
12504
  const sub = await walkSubtree(abs, dataRoot, out);
12465
12505
  if (!sub.clean) clean = false;
@@ -12571,7 +12611,7 @@ async function cascadeTrashLinkedKnowledgeDocs(session, accountId, relativePaths
12571
12611
  return { kds, sections, chunks };
12572
12612
  }
12573
12613
  async function buildArtifact(accountId, wf, embed2) {
12574
- const name = basename6(wf.absolute);
12614
+ const name = basename8(wf.absolute);
12575
12615
  const { content, route } = await extractFileContent(wf.absolute);
12576
12616
  const displayName = await readDisplayName(wf.absolute);
12577
12617
  const embedInput = `${name}
@@ -12815,7 +12855,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
12815
12855
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
12816
12856
  async function readMeta(absDir, baseName) {
12817
12857
  try {
12818
- const raw = await readFile4(join25(absDir, `${baseName}.meta.json`), "utf8");
12858
+ const raw = await readFile4(join26(absDir, `${baseName}.meta.json`), "utf8");
12819
12859
  const parsed = JSON.parse(raw);
12820
12860
  if (typeof parsed?.filename === "string") {
12821
12861
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -12853,7 +12893,7 @@ async function readAccountNames() {
12853
12893
  }
12854
12894
  async function enrich(absolute, entry, accountNames) {
12855
12895
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
12856
- const meta = await readMeta(join25(absolute, entry.name), entry.name);
12896
+ const meta = await readMeta(join26(absolute, entry.name), entry.name);
12857
12897
  if (meta?.filename) {
12858
12898
  entry.displayName = meta.filename;
12859
12899
  entry.mimeType = meta.mimeType;
@@ -13017,7 +13057,7 @@ app20.get("/", requireAdminSession, async (c) => {
13017
13057
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
13018
13058
  const protectedEntry = isProtectedFromDeletion(childRel).protected;
13019
13059
  try {
13020
- const entryPath = join25(absolute, name);
13060
+ const entryPath = join26(absolute, name);
13021
13061
  const s = await stat4(entryPath);
13022
13062
  entries.push({
13023
13063
  name,
@@ -13057,11 +13097,27 @@ app20.get("/download", requireAdminSession, async (c) => {
13057
13097
  const rawPath = c.req.query("path") ?? "";
13058
13098
  if (!rawPath) return c.json({ error: "path required" }, 400);
13059
13099
  const root = c.req.query("root") ?? "data";
13060
- if (root !== "data" && root !== "claude-uploads") {
13100
+ if (root !== "data" && root !== "claude-uploads" && root !== "scratchpad") {
13061
13101
  return c.json({ error: "invalid root" }, 400);
13062
13102
  }
13063
13103
  const disposition = c.req.query("disposition") ?? "attachment";
13064
- const resolution = root === "claude-uploads" ? resolveClaudeUploadsPath(rawPath) : resolveDataPath(rawPath);
13104
+ let scratchpadRoot = null;
13105
+ if (root === "scratchpad") {
13106
+ const sessionId = c.req.query("sessionId") ?? "";
13107
+ if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
13108
+ const projectDir = findSessionProjectDir(sessionId);
13109
+ if (!projectDir) {
13110
+ console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
13111
+ return c.json({ error: "Not found" }, 404);
13112
+ }
13113
+ const meta = readSidecarMeta(join26(projectDir, `${sessionId}.meta.json`));
13114
+ if (!meta.accountId || meta.accountId !== accountId) {
13115
+ console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
13116
+ return c.json({ error: "Not found" }, 404);
13117
+ }
13118
+ scratchpadRoot = sessionScratchpadRoot(projectDir, sessionId);
13119
+ }
13120
+ const resolution = root === "scratchpad" ? resolveScratchpadPath(rawPath, scratchpadRoot) : root === "claude-uploads" ? resolveClaudeUploadsPath(rawPath) : resolveDataPath(rawPath);
13065
13121
  if (!resolution.ok) {
13066
13122
  if (resolution.status === 403) {
13067
13123
  console.error(`[data] path-traversal-blocked root="${root}" requested="${rawPath}" resolved="${resolution.resolved ?? "n/a"}"`);
@@ -13076,7 +13132,7 @@ app20.get("/download", requireAdminSession, async (c) => {
13076
13132
  console.error(`[data] account-scope-blocked root="claude-uploads" attachmentId="${attachmentId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
13077
13133
  return c.json({ error: "Not found" }, 404);
13078
13134
  }
13079
- } else if (crossesForeignAccountPartition(relPath, accountId)) {
13135
+ } else if (root === "data" && crossesForeignAccountPartition(relPath, accountId)) {
13080
13136
  console.error(`[data] account-scope-blocked endpoint="/api/admin/files/download" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
13081
13137
  return c.json({ error: "Not found" }, 404);
13082
13138
  }
@@ -13085,7 +13141,7 @@ app20.get("/download", requireAdminSession, async (c) => {
13085
13141
  if (!info.isFile()) {
13086
13142
  return c.json({ error: "Path is not a file" }, 400);
13087
13143
  }
13088
- const filename = basename7(absolute);
13144
+ const filename = basename9(absolute);
13089
13145
  const mimeType = detectMimeType(absolute);
13090
13146
  const nodeStream = createReadStream2(absolute);
13091
13147
  const webStream = Readable2.toWeb(nodeStream);
@@ -13141,7 +13197,7 @@ async function* walkRegularFiles(dirAbsolute) {
13141
13197
  const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
13142
13198
  for (const d of dirents) {
13143
13199
  if (d.isSymbolicLink()) continue;
13144
- const child = join25(dirAbsolute, d.name);
13200
+ const child = join26(dirAbsolute, d.name);
13145
13201
  if (d.isDirectory()) {
13146
13202
  yield* walkRegularFiles(child);
13147
13203
  continue;
@@ -13190,7 +13246,7 @@ app20.get("/download-zip", requireAdminSession, async (c) => {
13190
13246
  const info = await stat4(absolute);
13191
13247
  if (info.isDirectory()) {
13192
13248
  dirsWalked++;
13193
- const parentAbs = dirname6(absolute);
13249
+ const parentAbs = dirname7(absolute);
13194
13250
  for await (const fileAbs of walkRegularFiles(absolute)) {
13195
13251
  const within = relative4(absolute, fileAbs).split(sep6).join("/");
13196
13252
  const fileRel = relPath === "" || relPath === "." ? within : `${relPath}/${within}`;
@@ -13201,7 +13257,7 @@ app20.get("/download-zip", requireAdminSession, async (c) => {
13201
13257
  if (over) return over;
13202
13258
  }
13203
13259
  } else if (info.isFile()) {
13204
- const over = await addFile(absolute, info.size, basename7(absolute));
13260
+ const over = await addFile(absolute, info.size, basename9(absolute));
13205
13261
  if (over) return over;
13206
13262
  } else {
13207
13263
  return c.json({ error: "Path is not a file or directory" }, 400);
@@ -13230,12 +13286,12 @@ function dataUploadCeiling() {
13230
13286
  }
13231
13287
  async function resolveUploadTarget(c, accountId, uid) {
13232
13288
  const rawName = c.req.query("filename") ?? "";
13233
- const safeName = basename7(rawName).replace(/[\0/\\]/g, "_");
13289
+ const safeName = basename9(rawName).replace(/[\0/\\]/g, "_");
13234
13290
  if (!safeName) return { ok: false, status: 400, error: "filename query param required" };
13235
13291
  const rawRelpath = c.req.query("relpath") ?? "";
13236
13292
  const relpath = rawRelpath !== "" ? rawRelpath : null;
13237
13293
  const token = c.req.query("token") ?? "";
13238
- const finalName = relpath ? basename7(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
13294
+ const finalName = relpath ? basename9(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
13239
13295
  const mimeType = (c.req.header("content-type") ?? "").split(";")[0].trim();
13240
13296
  if (!SUPPORTED_MIME_TYPES.has(mimeType)) {
13241
13297
  console.error(`[data-upload] op=reject-mime uid=${uid} mime="${mimeType}" token=${token} rel="${relpath ?? ""}"`);
@@ -13244,8 +13300,8 @@ async function resolveUploadTarget(c, accountId, uid) {
13244
13300
  const rawDir = c.req.query("path") ?? "";
13245
13301
  const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
13246
13302
  if (!base.ok) return { ok: false, status: base.status, error: base.error };
13247
- const relDir = relpath ? dirname6(relpath) : ".";
13248
- const destRel = relDir === "." ? base.relative : join25(base.relative, relDir);
13303
+ const relDir = relpath ? dirname7(relpath) : ".";
13304
+ const destRel = relDir === "." ? base.relative : join26(base.relative, relDir);
13249
13305
  if (crossesForeignAccountPartition(destRel, accountId)) {
13250
13306
  console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
13251
13307
  return { ok: false, status: 404, error: "Not found" };
@@ -13263,8 +13319,8 @@ async function resolveUploadTarget(c, accountId, uid) {
13263
13319
  const info = await stat4(destDir).catch(() => null);
13264
13320
  if (!info || !info.isDirectory()) return { ok: false, status: 400, error: "Upload destination is not a directory" };
13265
13321
  }
13266
- const dataRootReal = realpathSync4(DATA_ROOT);
13267
- const destDirReal = realpathSync4(destDir);
13322
+ const dataRootReal = realpathSync5(DATA_ROOT);
13323
+ const destDirReal = realpathSync5(destDir);
13268
13324
  if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep6)) {
13269
13325
  console.error(`[data-upload] op=path-traversal-blocked uid=${uid} requested="${destRel}" resolved="${destDirReal}"`);
13270
13326
  return { ok: false, status: 403, error: "Upload destination escapes DATA_ROOT" };
@@ -13605,7 +13661,7 @@ app20.delete("/", requireAdminSession, async (c) => {
13605
13661
  console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
13606
13662
  return c.json({ error: "Not found" }, 404);
13607
13663
  }
13608
- const base = basename7(absolute);
13664
+ const base = basename9(absolute);
13609
13665
  const protection = isProtectedFromDeletion(relPath);
13610
13666
  if (protection.protected) {
13611
13667
  console.error(`[data] file-delete blocked path="${relPath}" reason="protected" rule="${protection.rule}"`);
@@ -13621,7 +13677,7 @@ app20.delete("/", requireAdminSession, async (c) => {
13621
13677
  }
13622
13678
  const dot = base.lastIndexOf(".");
13623
13679
  const stem = dot === -1 ? base : base.slice(0, dot);
13624
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join25(dirname6(absolute), `${stem}.meta.json`) : null;
13680
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join26(dirname7(absolute), `${stem}.meta.json`) : null;
13625
13681
  await unlink2(absolute);
13626
13682
  if (sidecarPath) {
13627
13683
  try {
@@ -13717,8 +13773,8 @@ app20.post("/rename", requireAdminSession, async (c) => {
13717
13773
  console.error(`[data] file-rename blocked path="${src.relative}" reason="protected"`);
13718
13774
  return c.json({ error: "Protected entry \u2014 refusing to rename" }, 403);
13719
13775
  }
13720
- const destAbs = resolve21(dirname6(src.absolute), newName);
13721
- const newRel = `${dirname6(src.relative)}/${newName}`.replace(/^\.\//, "");
13776
+ const destAbs = resolve21(dirname7(src.absolute), newName);
13777
+ const newRel = `${dirname7(src.relative)}/${newName}`.replace(/^\.\//, "");
13722
13778
  if (isProtectedFromRename(newRel)) {
13723
13779
  console.error(`[data] file-rename blocked path="${newRel}" reason="protected-target"`);
13724
13780
  return c.json({ error: "That name is reserved" }, 403);
@@ -15849,7 +15905,7 @@ var graph_default_view_default = app26;
15849
15905
 
15850
15906
  // server/routes/admin/sidebar-artefacts.ts
15851
15907
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
15852
- import { resolve as resolve22, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename8 } from "path";
15908
+ import { resolve as resolve22, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
15853
15909
  import { existsSync as existsSync24 } from "fs";
15854
15910
  var LIMIT = 50;
15855
15911
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
@@ -15902,7 +15958,7 @@ async function fetchAccountFileArtefacts(accountId) {
15902
15958
  const modifiedAt = r.get("modifiedAt") ?? "";
15903
15959
  return {
15904
15960
  id: `account-file:${relativePath}`,
15905
- name: displayName ?? basename8(relativePath),
15961
+ name: displayName ?? basename10(relativePath),
15906
15962
  kind: "account-file",
15907
15963
  updatedAt: modifiedAt,
15908
15964
  mimeType,
@@ -16555,10 +16611,10 @@ var system_stats_default = app34;
16555
16611
 
16556
16612
  // server/routes/admin/health.ts
16557
16613
  import { existsSync as existsSync25, readFileSync as readFileSync27 } from "fs";
16558
- import { resolve as resolve23, join as join26 } from "path";
16614
+ import { resolve as resolve23, join as join27 } from "path";
16559
16615
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
16560
16616
  var brandHostname = "maxy";
16561
- var brandJsonPath = join26(PLATFORM_ROOT6, "config", "brand.json");
16617
+ var brandJsonPath = join27(PLATFORM_ROOT6, "config", "brand.json");
16562
16618
  if (existsSync25(brandJsonPath)) {
16563
16619
  try {
16564
16620
  const brand = JSON.parse(readFileSync27(brandJsonPath, "utf-8"));
@@ -17337,7 +17393,7 @@ var browser_default = app42;
17337
17393
 
17338
17394
  // server/routes/admin/calendar.ts
17339
17395
  import { existsSync as existsSync26 } from "fs";
17340
- import { join as join28 } from "path";
17396
+ import { join as join29 } from "path";
17341
17397
 
17342
17398
  // server/lib/calendar-ics.ts
17343
17399
  var CRLF = "\r\n";
@@ -17437,7 +17493,7 @@ function countVEvents(ics) {
17437
17493
 
17438
17494
  // server/lib/calendar-availability.ts
17439
17495
  import { readFileSync as readFileSync28 } from "fs";
17440
- import { join as join27 } from "path";
17496
+ import { join as join28 } from "path";
17441
17497
  var AVAILABILITY_FILENAME = "calendar-availability.json";
17442
17498
  var REQUIRED_KEYS = [
17443
17499
  "timezone",
@@ -17446,7 +17502,7 @@ var REQUIRED_KEYS = [
17446
17502
  "weekly"
17447
17503
  ];
17448
17504
  function readAvailabilityConfig(accountDir) {
17449
- const path2 = join27(accountDir, AVAILABILITY_FILENAME);
17505
+ const path2 = join28(accountDir, AVAILABILITY_FILENAME);
17450
17506
  let raw;
17451
17507
  try {
17452
17508
  raw = readFileSync28(path2, "utf-8");
@@ -17808,7 +17864,7 @@ app43.get("/booking-link", requireAdminSession, (c) => {
17808
17864
  console.error('[calendar] op=booking-link-fail err="no account configured"');
17809
17865
  return c.json({ bookingDomain: null });
17810
17866
  }
17811
- if (!existsSync26(join28(account.accountDir, AVAILABILITY_FILENAME))) {
17867
+ if (!existsSync26(join29(account.accountDir, AVAILABILITY_FILENAME))) {
17812
17868
  console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
17813
17869
  return c.json({ bookingDomain: null });
17814
17870
  }
@@ -18099,7 +18155,7 @@ app47.route("/request-magic-link", request_magic_link_default);
18099
18155
  var access_default = app47;
18100
18156
 
18101
18157
  // server/routes/sites.ts
18102
- import { existsSync as existsSync27, readFileSync as readFileSync29, realpathSync as realpathSync5, statSync as statSync11 } from "fs";
18158
+ import { existsSync as existsSync27, readFileSync as readFileSync29, realpathSync as realpathSync6, statSync as statSync11 } from "fs";
18103
18159
  import { resolve as resolve25 } from "path";
18104
18160
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
18105
18161
  var MIME = {
@@ -18191,8 +18247,8 @@ app48.get("/:rel{.*}", (c) => {
18191
18247
  let realPath;
18192
18248
  let realRoot;
18193
18249
  try {
18194
- realPath = realpathSync5(filePath);
18195
- realRoot = realpathSync5(rootDir);
18250
+ realPath = realpathSync6(filePath);
18251
+ realRoot = realpathSync6(rootDir);
18196
18252
  } catch {
18197
18253
  console.error(`[sites] not-found path=${reqPath} status=404`);
18198
18254
  return c.text("Not found", 404);
@@ -18240,7 +18296,7 @@ var sites_default = app48;
18240
18296
  // app/lib/visitor-token.ts
18241
18297
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
18242
18298
  import { mkdirSync as mkdirSync6, readFileSync as readFileSync30, writeFileSync as writeFileSync11 } from "fs";
18243
- import { dirname as dirname7 } from "path";
18299
+ import { dirname as dirname8 } from "path";
18244
18300
  var TOKEN_PREFIX = "v1.";
18245
18301
  var SECRET_BYTES = 32;
18246
18302
  var DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -18257,7 +18313,7 @@ function getSecret() {
18257
18313
  }
18258
18314
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
18259
18315
  try {
18260
- mkdirSync6(dirname7(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
18316
+ mkdirSync6(dirname8(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
18261
18317
  writeFileSync11(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
18262
18318
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
18263
18319
  } catch {
@@ -18316,7 +18372,7 @@ var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
18316
18372
 
18317
18373
  // app/lib/brand-config.ts
18318
18374
  import { existsSync as existsSync28, readFileSync as readFileSync31 } from "fs";
18319
- import { join as join29 } from "path";
18375
+ import { join as join30 } from "path";
18320
18376
  var cached2 = null;
18321
18377
  var cachedAttempted = false;
18322
18378
  function readBrandConfig() {
@@ -18324,7 +18380,7 @@ function readBrandConfig() {
18324
18380
  cachedAttempted = true;
18325
18381
  const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
18326
18382
  if (!platformRoot3) return null;
18327
- const brandPath = join29(platformRoot3, "config", "brand.json");
18383
+ const brandPath = join30(platformRoot3, "config", "brand.json");
18328
18384
  if (!existsSync28(brandPath)) return null;
18329
18385
  try {
18330
18386
  cached2 = JSON.parse(readFileSync31(brandPath, "utf-8"));
@@ -19365,7 +19421,7 @@ async function startFileWatcher(opts = {}) {
19365
19421
 
19366
19422
  // app/lib/migrate-uploads.ts
19367
19423
  import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
19368
- import { dirname as dirname8, relative as relative6, resolve as resolve28 } from "path";
19424
+ import { dirname as dirname9, relative as relative6, resolve as resolve28 } from "path";
19369
19425
  var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19370
19426
  async function walkFiles(dir) {
19371
19427
  const out = [];
@@ -19397,7 +19453,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
19397
19453
  for (const oldAbs of files) {
19398
19454
  const suffix = relative6(srcDir, oldAbs);
19399
19455
  const newAbs = resolve28(destDir, suffix);
19400
- await mkdir5(dirname8(newAbs), { recursive: true });
19456
+ await mkdir5(dirname9(newAbs), { recursive: true });
19401
19457
  await rename2(oldAbs, newAbs);
19402
19458
  moved++;
19403
19459
  const oldRel = relative6(dataRoot, oldAbs);
@@ -19489,7 +19545,7 @@ async function migrateUploads(opts = {}) {
19489
19545
  // app/lib/migrate-admin-webchat-sidecars.ts
19490
19546
  import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
19491
19547
  import { existsSync as existsSync30 } from "fs";
19492
- import { join as join30 } from "path";
19548
+ import { join as join31 } from "path";
19493
19549
  var ADMIN_ROLE2 = "admin";
19494
19550
  var WEBCHAT_CHANNEL2 = "webchat";
19495
19551
  var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
@@ -19534,7 +19590,7 @@ async function collectLiveSidecars(projectsRoot) {
19534
19590
  }
19535
19591
  for (const slug of slugs) {
19536
19592
  if (!slug.isDirectory()) continue;
19537
- const slugDir = join30(projectsRoot, slug.name);
19593
+ const slugDir = join31(projectsRoot, slug.name);
19538
19594
  let entries;
19539
19595
  try {
19540
19596
  entries = await readdir6(slugDir, { withFileTypes: true });
@@ -19543,9 +19599,9 @@ async function collectLiveSidecars(projectsRoot) {
19543
19599
  }
19544
19600
  for (const entry of entries) {
19545
19601
  if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
19546
- out.push(join30(slugDir, entry.name));
19602
+ out.push(join31(slugDir, entry.name));
19547
19603
  } else if (entry.isDirectory() && entry.name === "subagents") {
19548
- const subDir = join30(slugDir, entry.name);
19604
+ const subDir = join31(slugDir, entry.name);
19549
19605
  let subs;
19550
19606
  try {
19551
19607
  subs = await readdir6(subDir, { withFileTypes: true });
@@ -19553,7 +19609,7 @@ async function collectLiveSidecars(projectsRoot) {
19553
19609
  continue;
19554
19610
  }
19555
19611
  for (const s of subs) {
19556
- if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join30(subDir, s.name));
19612
+ if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join31(subDir, s.name));
19557
19613
  }
19558
19614
  }
19559
19615
  }
@@ -19565,7 +19621,7 @@ function shortId(path2) {
19565
19621
  return base.slice(0, 8);
19566
19622
  }
19567
19623
  async function migrateAdminWebchatSidecars(opts = {}) {
19568
- const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join30(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
19624
+ const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join31(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
19569
19625
  const usersFile = opts.usersFile ?? USERS_FILE;
19570
19626
  const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
19571
19627
  const resolveName = opts.resolveName ?? defaultResolveName;
@@ -21473,9 +21529,9 @@ function buildTelegramSpawnRequest(input) {
21473
21529
  }
21474
21530
 
21475
21531
  // app/lib/telegram/outbound/send-document.ts
21476
- import { realpathSync as realpathSync6 } from "fs";
21532
+ import { realpathSync as realpathSync7 } from "fs";
21477
21533
  import { readFile as readFile7, stat as stat7 } from "fs/promises";
21478
- import { resolve as resolve29, basename as basename9 } from "path";
21534
+ import { resolve as resolve29, basename as basename11 } from "path";
21479
21535
  var TAG35 = "[telegram:outbound]";
21480
21536
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
21481
21537
  async function sendTelegramDocument(input) {
@@ -21489,8 +21545,8 @@ async function sendTelegramDocument(input) {
21489
21545
  const accountDir = resolve29(platformRoot3, "..", "data/accounts", maxyAccountId);
21490
21546
  let resolvedPath;
21491
21547
  try {
21492
- resolvedPath = realpathSync6(filePath);
21493
- const accountResolved = realpathSync6(accountDir);
21548
+ resolvedPath = realpathSync7(filePath);
21549
+ const accountResolved = realpathSync7(accountDir);
21494
21550
  if (!resolvedPath.startsWith(accountResolved + "/")) {
21495
21551
  console.error(`${TAG35} document REJECTED reason=outside_account_directory`);
21496
21552
  return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
@@ -21512,7 +21568,7 @@ async function sendTelegramDocument(input) {
21512
21568
  error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
21513
21569
  };
21514
21570
  }
21515
- const filename = basename9(resolvedPath);
21571
+ const filename = basename11(resolvedPath);
21516
21572
  const buffer = Buffer.from(await readFile7(resolvedPath));
21517
21573
  const form = new FormData();
21518
21574
  form.append("chat_id", String(chatId));
@@ -21622,12 +21678,12 @@ function startTelegramNativeFileFollower(input) {
21622
21678
  }
21623
21679
 
21624
21680
  // server/telegram-descriptor.ts
21625
- import { resolve as resolve30, join as join31 } from "path";
21681
+ import { resolve as resolve30, join as join32 } from "path";
21626
21682
  function telegramGatewayUrl() {
21627
21683
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
21628
21684
  }
21629
21685
  function telegramServerPath() {
21630
- return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ?? join31(__dirname, ".."), "services/telegram-channel/dist/server.js");
21686
+ return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve30(process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, ".."), "services/telegram-channel/dist/server.js");
21631
21687
  }
21632
21688
 
21633
21689
  // app/lib/channel-pty-bridge/public-session-end-review.ts
@@ -22088,7 +22144,7 @@ function clientFrom(c) {
22088
22144
  );
22089
22145
  }
22090
22146
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
22091
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join32(PLATFORM_ROOT8, "config", "brand.json") : "";
22147
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join33(PLATFORM_ROOT8, "config", "brand.json") : "";
22092
22148
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
22093
22149
  if (BRAND_JSON_PATH && !existsSync32(BRAND_JSON_PATH)) {
22094
22150
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
@@ -22127,7 +22183,7 @@ var brandLoginOpts = {
22127
22183
  appleTouchIconPath: brandAppIcon512Path,
22128
22184
  themeColor: BRAND.defaultColors?.primary
22129
22185
  };
22130
- var ALIAS_DOMAINS_PATH = join32(homedir3(), BRAND.configDir, "alias-domains.json");
22186
+ var ALIAS_DOMAINS_PATH = join33(homedir3(), BRAND.configDir, "alias-domains.json");
22131
22187
  function loadAliasDomains() {
22132
22188
  try {
22133
22189
  if (!existsSync32(ALIAS_DOMAINS_PATH)) return null;
@@ -22159,7 +22215,7 @@ var app54 = new Hono();
22159
22215
  var nativeFileFollowers = /* @__PURE__ */ new Map();
22160
22216
  var waGateway = new WaGateway({
22161
22217
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
22162
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve32(process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
22218
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve32(process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
22163
22219
  // Task 751 — file delivery on the native channel: resolve the platform
22164
22220
  // account + path validation here and funnel through the shared send core.
22165
22221
  sendDocument: async ({ senderId, accountId, filePath, caption }) => {
@@ -22175,7 +22231,7 @@ var waGateway = new WaGateway({
22175
22231
  caption,
22176
22232
  accountId,
22177
22233
  maxyAccountId,
22178
- platformRoot: resolve32(process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, ".."))
22234
+ platformRoot: resolve32(process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, ".."))
22179
22235
  });
22180
22236
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
22181
22237
  },
@@ -22779,7 +22835,7 @@ var SW_SOURCE = (() => {
22779
22835
  function readInstalledVersion() {
22780
22836
  try {
22781
22837
  if (!PLATFORM_ROOT8) return "unknown";
22782
- const versionFile = join32(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
22838
+ const versionFile = join33(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
22783
22839
  if (!existsSync32(versionFile)) return "unknown";
22784
22840
  const content = readFileSync33(versionFile, "utf-8").trim();
22785
22841
  return content || "unknown";
@@ -22839,11 +22895,11 @@ ${clientErrorReporterScript}
22839
22895
  return html;
22840
22896
  }
22841
22897
  function loadBrandingCache(agentSlug) {
22842
- const configDir2 = join32(homedir3(), BRAND.configDir);
22898
+ const configDir2 = join33(homedir3(), BRAND.configDir);
22843
22899
  try {
22844
22900
  const accountId = getDefaultAccountId();
22845
22901
  if (!accountId) return null;
22846
- const cachePath = join32(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
22902
+ const cachePath = join33(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
22847
22903
  if (!existsSync32(cachePath)) return null;
22848
22904
  return JSON.parse(readFileSync33(cachePath, "utf-8"));
22849
22905
  } catch {
@@ -23063,7 +23119,7 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
23063
23119
  var httpServer = serve({ fetch: app54.fetch, port, hostname });
23064
23120
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
23065
23121
  {
23066
- const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, "..");
23122
+ const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, "..");
23067
23123
  const reconcileScript = resolve32(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
23068
23124
  const RECONCILE_INTERVAL_MS = 12e4;
23069
23125
  const runReconcile = () => {
@@ -23085,7 +23141,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
23085
23141
  loop.unref();
23086
23142
  }
23087
23143
  {
23088
- const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, "..");
23144
+ const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, "..");
23089
23145
  const auditScript = resolve32(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
23090
23146
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
23091
23147
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
@@ -23290,7 +23346,7 @@ try {
23290
23346
  } catch (err) {
23291
23347
  console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
23292
23348
  }
23293
- var configDirForWhatsApp = basename10(MAXY_DIR) || ".maxy";
23349
+ var configDirForWhatsApp = basename12(MAXY_DIR) || ".maxy";
23294
23350
  var bootAccount = resolveAccount();
23295
23351
  if (bootAccount) {
23296
23352
  migrateRemovedConfigKeys(bootAccount.accountDir);
@@ -23352,7 +23408,7 @@ if (bootAccountConfig?.whatsapp) {
23352
23408
  }
23353
23409
  init({
23354
23410
  configDir: configDirForWhatsApp,
23355
- platformRoot: resolve32(process.env.MAXY_PLATFORM_ROOT ?? join32(__dirname, "..")),
23411
+ platformRoot: resolve32(process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, "..")),
23356
23412
  accountConfig: bootAccountConfig,
23357
23413
  onMessage: async (msg) => {
23358
23414
  if (msg.isOwnerMirror) {