@rubytech/create-maxy-code 0.1.405 → 0.1.408

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 (29) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/scheduling/PLUGIN.md +2 -0
  3. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.d.ts +2 -0
  4. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.d.ts.map +1 -0
  5. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.js +19 -0
  6. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.js.map +1 -0
  7. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/deliverability-grounding.test.d.ts +2 -0
  8. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/deliverability-grounding.test.d.ts.map +1 -0
  9. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/deliverability-grounding.test.js +33 -0
  10. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/deliverability-grounding.test.js.map +1 -0
  11. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +4 -0
  12. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +5 -1
  13. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts +8 -7
  14. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts.map +1 -1
  15. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js +63 -40
  16. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js.map +1 -1
  17. package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts +40 -0
  18. package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts.map +1 -0
  19. package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js +159 -0
  20. package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js.map +1 -0
  21. package/payload/platform/services/claude-session-manager/dist/connector-availability.d.ts +36 -0
  22. package/payload/platform/services/claude-session-manager/dist/connector-availability.d.ts.map +1 -0
  23. package/payload/platform/services/claude-session-manager/dist/connector-availability.js +76 -0
  24. package/payload/platform/services/claude-session-manager/dist/connector-availability.js.map +1 -0
  25. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +2 -1
  26. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  27. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -2
  28. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  29. package/payload/server/server.js +107 -70
@@ -1307,7 +1307,7 @@ var serveStatic = (options = { root: "" }) => {
1307
1307
  // server/index.ts
1308
1308
  import { readFileSync as readFileSync35, existsSync as existsSync33, watchFile } from "fs";
1309
1309
  import { spawn as spawn3 } from "child_process";
1310
- import { resolve as resolve33, join as join34, basename as basename13 } from "path";
1310
+ import { resolve as resolve33, join as join35, basename as basename13 } from "path";
1311
1311
  import { homedir as homedir3 } from "os";
1312
1312
  import { monitorEventLoopDelay } from "perf_hooks";
1313
1313
 
@@ -4248,6 +4248,16 @@ function getStatus() {
4248
4248
  function getSocket(accountId) {
4249
4249
  return connections.get(accountId)?.sock ?? null;
4250
4250
  }
4251
+ function selectConnection(conns, accountId) {
4252
+ const presentKeys = conns.map((c) => c.accountId);
4253
+ const conn = conns.find((c) => c.accountId === accountId) ?? conns.find((c) => c.platformAccountId === accountId);
4254
+ if (!conn) return { ok: false, reason: "key-miss", presentKeys };
4255
+ if (!conn.sock) return { ok: false, reason: "disconnected", presentKeys };
4256
+ return { ok: true, sock: conn.sock, accountId: conn.accountId };
4257
+ }
4258
+ function resolveSocket(accountId) {
4259
+ return selectConnection(Array.from(connections.values()), accountId);
4260
+ }
4251
4261
  async function registerLoginSocket(accountId, sock, authDir) {
4252
4262
  if (!configDir) throw new Error("WhatsApp manager not initialized");
4253
4263
  let platformAccountId;
@@ -7442,11 +7452,15 @@ app2.post("/send-admin", async (c) => {
7442
7452
  );
7443
7453
  }
7444
7454
  const accountId = validateAccountId(body.accountId);
7445
- const sock = getSocket(accountId);
7446
- if (!sock) {
7447
- return c.json({ error: `WhatsApp account "${accountId}" is not connected.` }, 503);
7455
+ const res = resolveSocket(accountId);
7456
+ if (!res.ok) {
7457
+ if (res.reason === "key-miss") {
7458
+ console.error(`[whatsapp:outbound] op=socket-key-miss accountId=${accountId} presentKeys=${res.presentKeys.join(",") || "none"}`);
7459
+ return c.json({ error: `No WhatsApp socket is registered for account "${accountId}" (present: ${res.presentKeys.join(", ") || "none"}). This is an account-keying mismatch, not a dropped connection.` }, 503);
7460
+ }
7461
+ return c.json({ error: `WhatsApp account "${accountId}" is registered but its socket is disconnected.` }, 503);
7448
7462
  }
7449
- const result = await sendTextMessage(sock, normalizeE164(phone), text, { accountId });
7463
+ const result = await sendTextMessage(res.sock, normalizeE164(phone), text, { accountId: res.accountId });
7450
7464
  if (!result.success) {
7451
7465
  return c.json({ error: result.error ?? "send failed" }, 500);
7452
7466
  }
@@ -10501,6 +10515,9 @@ function claudeBin() {
10501
10515
  return process.env.CLAUDE_BIN ?? "claude";
10502
10516
  }
10503
10517
 
10518
+ // server/routes/onboarding.ts
10519
+ import { dirname as dirname8, join as join23 } from "path";
10520
+
10504
10521
  // app/lib/claude-keychain.ts
10505
10522
  import { execFileSync as execFileSync2 } from "child_process";
10506
10523
  var CREDS_SERVICE_PREFIX = "Claude Code-credentials";
@@ -10567,6 +10584,15 @@ function bridgeKeychainToFile(deps) {
10567
10584
  deps.log(`[onboarding] op=login-writeback src=keychain dst=host-creds-file bytes=${blob.length}`);
10568
10585
  return { wrote: true, reason: "ok", bytes: blob.length, service };
10569
10586
  }
10587
+ function persistKeychainService(result, persist, log) {
10588
+ if (!result.wrote || !result.service) return;
10589
+ try {
10590
+ persist(result.service);
10591
+ log(`[onboarding] op=keychain-service-persist service=${JSON.stringify(result.service)}`);
10592
+ } catch (err) {
10593
+ log(`[onboarding] op=keychain-service-persist result=failed err=${err instanceof Error ? err.message : String(err)}`);
10594
+ }
10595
+ }
10570
10596
  function listHostCredsMdats() {
10571
10597
  try {
10572
10598
  const out = execFileSync2("security", ["dump-keychain"], { encoding: "utf-8", timeout: 1e4 });
@@ -10879,7 +10905,7 @@ app9.post("/claude-auth", async (c) => {
10879
10905
  claudeProc2.stderr?.on("data", onClaudeOutput);
10880
10906
  claudeProc2.once("close", () => {
10881
10907
  closeSync3(claudeAuthLogFd);
10882
- bridgeKeychainToFile({
10908
+ const writebackResult = bridgeKeychainToFile({
10883
10909
  platform: process.platform,
10884
10910
  before: darwinCredsBefore,
10885
10911
  listMdats: listHostCredsMdats,
@@ -10891,6 +10917,11 @@ app9.post("/claude-auth", async (c) => {
10891
10917
  },
10892
10918
  log: (line) => console.log(line)
10893
10919
  });
10920
+ persistKeychainService(
10921
+ writebackResult,
10922
+ (service) => writeFileSync10(join23(dirname8(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
10923
+ (line) => console.log(line)
10924
+ );
10894
10925
  if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
10895
10926
  });
10896
10927
  return c.json({ started: true, transport: "native" });
@@ -11154,8 +11185,8 @@ var onboarding_default = app9;
11154
11185
 
11155
11186
  // server/routes/client-error.ts
11156
11187
  import { appendFileSync as appendFileSync3, existsSync as existsSync16, renameSync as renameSync8, statSync as statSync9 } from "fs";
11157
- import { join as join23 } from "path";
11158
- var CLIENT_ERRORS_LOG = join23(LOG_DIR, "client-errors.log");
11188
+ import { join as join24 } from "path";
11189
+ var CLIENT_ERRORS_LOG = join24(LOG_DIR, "client-errors.log");
11159
11190
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
11160
11191
  var MAX_BODY_SIZE = 8 * 1024;
11161
11192
  var MAX_STACK_LEN = 2e3;
@@ -11522,12 +11553,12 @@ import { resolve as resolve16, basename as basename8 } from "path";
11522
11553
 
11523
11554
  // app/lib/logs-read-resolve.ts
11524
11555
  import { existsSync as existsSync17 } from "fs";
11525
- import { join as join24 } from "path";
11556
+ import { join as join25 } from "path";
11526
11557
  function resolveSessionLogPaths(filename, logDirs) {
11527
11558
  const tried = [filename];
11528
11559
  const hits = [];
11529
11560
  for (const dir of logDirs) {
11530
- const fullPath = join24(dir, filename);
11561
+ const fullPath = join25(dir, filename);
11531
11562
  if (existsSync17(fullPath)) {
11532
11563
  hits.push({ path: fullPath, dir });
11533
11564
  }
@@ -12555,7 +12586,7 @@ var sessions_default = app17;
12555
12586
 
12556
12587
  // app/lib/claude-agent/spawn-context.ts
12557
12588
  import { existsSync as existsSync22, readFileSync as readFileSync27, readdirSync as readdirSync16, statSync as statSync11 } from "fs";
12558
- import { dirname as dirname8, resolve as resolve19, join as join25 } from "path";
12589
+ import { dirname as dirname9, resolve as resolve19, join as join26 } from "path";
12559
12590
  async function resolveOwnerProfileBlock(accountId, userId) {
12560
12591
  if (!userId) return { ok: false, reason: "missing-user-id" };
12561
12592
  try {
@@ -12596,8 +12627,8 @@ function frontmatterField(manifest, field2) {
12596
12627
  function extractPluginToolDescriptions(pluginDir) {
12597
12628
  const out = /* @__PURE__ */ new Map();
12598
12629
  const candidates = [
12599
- join25(pluginDir, "mcp/dist/index.js"),
12600
- join25(pluginDir, "mcp/src/index.ts")
12630
+ join26(pluginDir, "mcp/dist/index.js"),
12631
+ join26(pluginDir, "mcp/src/index.ts")
12601
12632
  ];
12602
12633
  let raw = null;
12603
12634
  for (const path2 of candidates) {
@@ -12655,21 +12686,21 @@ function listPluginDirs() {
12655
12686
  const platformPlugins = resolve19(PLATFORM_ROOT, "plugins");
12656
12687
  if (existsSync22(platformPlugins)) {
12657
12688
  for (const name of readdirSync16(platformPlugins)) {
12658
- const dir = join25(platformPlugins, name);
12689
+ const dir = join26(platformPlugins, name);
12659
12690
  try {
12660
12691
  if (statSync11(dir).isDirectory()) out.set(name, dir);
12661
12692
  } catch {
12662
12693
  }
12663
12694
  }
12664
12695
  }
12665
- const premiumRoot = resolve19(dirname8(PLATFORM_ROOT), "premium-plugins");
12696
+ const premiumRoot = resolve19(dirname9(PLATFORM_ROOT), "premium-plugins");
12666
12697
  if (existsSync22(premiumRoot)) {
12667
12698
  for (const bundle of readdirSync16(premiumRoot)) {
12668
- const bundlePlugins = join25(premiumRoot, bundle, "plugins");
12699
+ const bundlePlugins = join26(premiumRoot, bundle, "plugins");
12669
12700
  if (!existsSync22(bundlePlugins)) continue;
12670
12701
  try {
12671
12702
  for (const name of readdirSync16(bundlePlugins)) {
12672
- const dir = join25(bundlePlugins, name);
12703
+ const dir = join26(bundlePlugins, name);
12673
12704
  try {
12674
12705
  if (statSync11(dir).isDirectory()) out.set(name, dir);
12675
12706
  } catch {
@@ -12712,7 +12743,7 @@ function computeActivePlugins(accountId) {
12712
12743
  for (const name of Array.from(enabled).sort()) {
12713
12744
  const dir = pluginDirs.get(name);
12714
12745
  if (!dir) continue;
12715
- const fm = readFrontmatter(join25(dir, "PLUGIN.md"));
12746
+ const fm = readFrontmatter(join26(dir, "PLUGIN.md"));
12716
12747
  if (!fm) continue;
12717
12748
  const description = frontmatterField(`---
12718
12749
  ${fm}
@@ -12729,7 +12760,7 @@ ${fm}
12729
12760
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
12730
12761
  );
12731
12762
  if (toolNames.length > 0 && descMap.size === 0) {
12732
- const hasSource = existsSync22(join25(dir, "mcp/dist/index.js")) || existsSync22(join25(dir, "mcp/src/index.ts"));
12763
+ const hasSource = existsSync22(join26(dir, "mcp/dist/index.js")) || existsSync22(join26(dir, "mcp/src/index.ts"));
12733
12764
  if (hasSource) {
12734
12765
  console.warn(
12735
12766
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -12739,7 +12770,7 @@ ${fm}
12739
12770
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
12740
12771
  const skills = [];
12741
12772
  for (const relPath of skillPaths) {
12742
- const skillPath = join25(dir, relPath);
12773
+ const skillPath = join26(dir, relPath);
12743
12774
  const skillFm = readFrontmatter(skillPath);
12744
12775
  if (!skillFm) continue;
12745
12776
  const skillName = frontmatterField(`---
@@ -12783,7 +12814,7 @@ function computeSpecialistDomains(accountId) {
12783
12814
  const out = [];
12784
12815
  for (const file of entries.sort()) {
12785
12816
  if (!file.endsWith(".md")) continue;
12786
- const fm = readFrontmatter(join25(specialistsDir, file));
12817
+ const fm = readFrontmatter(join26(specialistsDir, file));
12787
12818
  if (!fm) continue;
12788
12819
  const wrapped = `---
12789
12820
  ${fm}
@@ -13111,7 +13142,7 @@ import { createReadStream as createReadStream2, createWriteStream as createWrite
13111
13142
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
13112
13143
  import { realpathSync as realpathSync5 } from "fs";
13113
13144
  import { randomUUID as randomUUID9 } from "crypto";
13114
- import { basename as basename10, dirname as dirname9, join as join27, relative as relative4, resolve as resolve22, sep as sep6 } from "path";
13145
+ import { basename as basename10, dirname as dirname10, join as join28, relative as relative4, resolve as resolve22, sep as sep6 } from "path";
13115
13146
  import { Readable as Readable2 } from "stream";
13116
13147
 
13117
13148
  // ../lib/graph-trash/src/index.ts
@@ -13429,7 +13460,7 @@ async function cascadeDeleteDocument(params) {
13429
13460
 
13430
13461
  // app/lib/file-index.ts
13431
13462
  import * as fsp from "fs/promises";
13432
- import { resolve as resolve21, relative as relative3, join as join26, basename as basename9, extname as extname2, sep as sep5 } from "path";
13463
+ import { resolve as resolve21, relative as relative3, join as join27, basename as basename9, extname as extname2, sep as sep5 } from "path";
13433
13464
  import { tmpdir as tmpdir2 } from "os";
13434
13465
  import { execFile as execFile2 } from "child_process";
13435
13466
  import { promisify as promisify2 } from "util";
@@ -13511,7 +13542,7 @@ async function extractPdf(absolute) {
13511
13542
  return stdout.trim();
13512
13543
  }
13513
13544
  async function ocrPdf(absolute) {
13514
- const outPdf = join26(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
13545
+ const outPdf = join27(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
13515
13546
  try {
13516
13547
  await execFileAsync2(
13517
13548
  "ocrmypdf",
@@ -13573,7 +13604,7 @@ async function readDisplayName(absolute) {
13573
13604
  const stem = dot === -1 ? base : base.slice(0, dot);
13574
13605
  if (base === `${stem}.meta.json`) return null;
13575
13606
  try {
13576
- const raw = await fsp.readFile(join26(dir, `${stem}.meta.json`), "utf-8");
13607
+ const raw = await fsp.readFile(join27(dir, `${stem}.meta.json`), "utf-8");
13577
13608
  const meta = JSON.parse(raw);
13578
13609
  const dn = meta.displayName ?? meta.filename;
13579
13610
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -13594,7 +13625,7 @@ async function walkSubtree(root, dataRoot, out) {
13594
13625
  for (const entry of entries) {
13595
13626
  if (entry.isSymbolicLink()) continue;
13596
13627
  if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
13597
- const abs = join26(root, entry.name);
13628
+ const abs = join27(root, entry.name);
13598
13629
  if (entry.isDirectory()) {
13599
13630
  const sub = await walkSubtree(abs, dataRoot, out);
13600
13631
  if (!sub.clean) clean = false;
@@ -13950,7 +13981,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
13950
13981
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13951
13982
  async function readMeta(absDir, baseName) {
13952
13983
  try {
13953
- const raw = await readFile4(join27(absDir, `${baseName}.meta.json`), "utf8");
13984
+ const raw = await readFile4(join28(absDir, `${baseName}.meta.json`), "utf8");
13954
13985
  const parsed = JSON.parse(raw);
13955
13986
  if (typeof parsed?.filename === "string") {
13956
13987
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -13988,7 +14019,7 @@ async function readAccountNames() {
13988
14019
  }
13989
14020
  async function enrich(absolute, entry, accountNames) {
13990
14021
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
13991
- const meta = await readMeta(join27(absolute, entry.name), entry.name);
14022
+ const meta = await readMeta(join28(absolute, entry.name), entry.name);
13992
14023
  if (meta?.filename) {
13993
14024
  entry.displayName = meta.filename;
13994
14025
  entry.mimeType = meta.mimeType;
@@ -14152,7 +14183,7 @@ app21.get("/", requireAdminSession, async (c) => {
14152
14183
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
14153
14184
  const protectedEntry = isProtectedFromDeletion(childRel).protected;
14154
14185
  try {
14155
- const entryPath = join27(absolute, name);
14186
+ const entryPath = join28(absolute, name);
14156
14187
  const s = await stat4(entryPath);
14157
14188
  entries.push({
14158
14189
  name,
@@ -14205,7 +14236,7 @@ app21.get("/download", requireAdminSession, async (c) => {
14205
14236
  console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
14206
14237
  return c.json({ error: "Not found" }, 404);
14207
14238
  }
14208
- const meta = readSidecarMeta(join27(projectDir, `${sessionId}.meta.json`));
14239
+ const meta = readSidecarMeta(join28(projectDir, `${sessionId}.meta.json`));
14209
14240
  if (!meta.accountId || meta.accountId !== accountId) {
14210
14241
  console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
14211
14242
  return c.json({ error: "Not found" }, 404);
@@ -14292,7 +14323,7 @@ async function* walkRegularFiles(dirAbsolute) {
14292
14323
  const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
14293
14324
  for (const d of dirents) {
14294
14325
  if (d.isSymbolicLink()) continue;
14295
- const child = join27(dirAbsolute, d.name);
14326
+ const child = join28(dirAbsolute, d.name);
14296
14327
  if (d.isDirectory()) {
14297
14328
  yield* walkRegularFiles(child);
14298
14329
  continue;
@@ -14341,7 +14372,7 @@ app21.get("/download-zip", requireAdminSession, async (c) => {
14341
14372
  const info = await stat4(absolute);
14342
14373
  if (info.isDirectory()) {
14343
14374
  dirsWalked++;
14344
- const parentAbs = dirname9(absolute);
14375
+ const parentAbs = dirname10(absolute);
14345
14376
  for await (const fileAbs of walkRegularFiles(absolute)) {
14346
14377
  const within = relative4(absolute, fileAbs).split(sep6).join("/");
14347
14378
  const fileRel = relPath === "" || relPath === "." ? within : `${relPath}/${within}`;
@@ -14395,8 +14426,8 @@ async function resolveUploadTarget(c, accountId, uid) {
14395
14426
  const rawDir = c.req.query("path") ?? "";
14396
14427
  const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
14397
14428
  if (!base.ok) return { ok: false, status: base.status, error: base.error };
14398
- const relDir = relpath ? dirname9(relpath) : ".";
14399
- const destRel = relDir === "." ? base.relative : join27(base.relative, relDir);
14429
+ const relDir = relpath ? dirname10(relpath) : ".";
14430
+ const destRel = relDir === "." ? base.relative : join28(base.relative, relDir);
14400
14431
  if (crossesForeignAccountPartition(destRel, accountId)) {
14401
14432
  console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
14402
14433
  return { ok: false, status: 404, error: "Not found" };
@@ -14772,7 +14803,7 @@ app21.delete("/", requireAdminSession, async (c) => {
14772
14803
  }
14773
14804
  const dot = base.lastIndexOf(".");
14774
14805
  const stem = dot === -1 ? base : base.slice(0, dot);
14775
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join27(dirname9(absolute), `${stem}.meta.json`) : null;
14806
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join28(dirname10(absolute), `${stem}.meta.json`) : null;
14776
14807
  await unlink2(absolute);
14777
14808
  if (sidecarPath) {
14778
14809
  try {
@@ -14868,8 +14899,8 @@ app21.post("/rename", requireAdminSession, async (c) => {
14868
14899
  console.error(`[data] file-rename blocked path="${src.relative}" reason="protected"`);
14869
14900
  return c.json({ error: "Protected entry \u2014 refusing to rename" }, 403);
14870
14901
  }
14871
- const destAbs = resolve22(dirname9(src.absolute), newName);
14872
- const newRel = `${dirname9(src.relative)}/${newName}`.replace(/^\.\//, "");
14902
+ const destAbs = resolve22(dirname10(src.absolute), newName);
14903
+ const newRel = `${dirname10(src.relative)}/${newName}`.replace(/^\.\//, "");
14873
14904
  if (isProtectedFromRename(newRel)) {
14874
14905
  console.error(`[data] file-rename blocked path="${newRel}" reason="protected-target"`);
14875
14906
  return c.json({ error: "That name is reserved" }, 403);
@@ -17738,10 +17769,10 @@ var system_stats_default = app36;
17738
17769
 
17739
17770
  // server/routes/admin/health.ts
17740
17771
  import { existsSync as existsSync26, readFileSync as readFileSync29 } from "fs";
17741
- import { resolve as resolve24, join as join28 } from "path";
17772
+ import { resolve as resolve24, join as join29 } from "path";
17742
17773
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
17743
17774
  var brandHostname = "maxy";
17744
- var brandJsonPath = join28(PLATFORM_ROOT6, "config", "brand.json");
17775
+ var brandJsonPath = join29(PLATFORM_ROOT6, "config", "brand.json");
17745
17776
  if (existsSync26(brandJsonPath)) {
17746
17777
  try {
17747
17778
  const brand = JSON.parse(readFileSync29(brandJsonPath, "utf-8"));
@@ -18528,7 +18559,7 @@ var browser_default = app44;
18528
18559
 
18529
18560
  // server/routes/admin/calendar.ts
18530
18561
  import { existsSync as existsSync27 } from "fs";
18531
- import { join as join30 } from "path";
18562
+ import { join as join31 } from "path";
18532
18563
 
18533
18564
  // server/lib/calendar-ics.ts
18534
18565
  var CRLF = "\r\n";
@@ -18628,7 +18659,7 @@ function countVEvents(ics) {
18628
18659
 
18629
18660
  // server/lib/calendar-availability.ts
18630
18661
  import { readFileSync as readFileSync30 } from "fs";
18631
- import { join as join29 } from "path";
18662
+ import { join as join30 } from "path";
18632
18663
  var AVAILABILITY_FILENAME = "calendar-availability.json";
18633
18664
  var REQUIRED_KEYS = [
18634
18665
  "timezone",
@@ -18637,7 +18668,7 @@ var REQUIRED_KEYS = [
18637
18668
  "weekly"
18638
18669
  ];
18639
18670
  function readAvailabilityConfig(accountDir) {
18640
- const path2 = join29(accountDir, AVAILABILITY_FILENAME);
18671
+ const path2 = join30(accountDir, AVAILABILITY_FILENAME);
18641
18672
  let raw;
18642
18673
  try {
18643
18674
  raw = readFileSync30(path2, "utf-8");
@@ -18999,7 +19030,7 @@ app45.get("/booking-link", requireAdminSession, (c) => {
18999
19030
  console.error('[calendar] op=booking-link-fail err="no account configured"');
19000
19031
  return c.json({ bookingDomain: null });
19001
19032
  }
19002
- if (!existsSync27(join30(account.accountDir, AVAILABILITY_FILENAME))) {
19033
+ if (!existsSync27(join31(account.accountDir, AVAILABILITY_FILENAME))) {
19003
19034
  console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
19004
19035
  return c.json({ bookingDomain: null });
19005
19036
  }
@@ -19433,7 +19464,7 @@ var sites_default = app50;
19433
19464
  // app/lib/visitor-token.ts
19434
19465
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
19435
19466
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync32, writeFileSync as writeFileSync11 } from "fs";
19436
- import { dirname as dirname10 } from "path";
19467
+ import { dirname as dirname11 } from "path";
19437
19468
  var TOKEN_PREFIX = "v1.";
19438
19469
  var SECRET_BYTES = 32;
19439
19470
  var DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -19450,7 +19481,7 @@ function getSecret() {
19450
19481
  }
19451
19482
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
19452
19483
  try {
19453
- mkdirSync7(dirname10(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
19484
+ mkdirSync7(dirname11(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
19454
19485
  writeFileSync11(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
19455
19486
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
19456
19487
  } catch {
@@ -19509,7 +19540,7 @@ var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
19509
19540
 
19510
19541
  // app/lib/brand-config.ts
19511
19542
  import { existsSync as existsSync29, readFileSync as readFileSync33 } from "fs";
19512
- import { join as join31 } from "path";
19543
+ import { join as join32 } from "path";
19513
19544
  var cached = null;
19514
19545
  var cachedAttempted = false;
19515
19546
  function readBrandConfig() {
@@ -19517,7 +19548,7 @@ function readBrandConfig() {
19517
19548
  cachedAttempted = true;
19518
19549
  const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
19519
19550
  if (!platformRoot3) return null;
19520
- const brandPath = join31(platformRoot3, "config", "brand.json");
19551
+ const brandPath = join32(platformRoot3, "config", "brand.json");
19521
19552
  if (!existsSync29(brandPath)) return null;
19522
19553
  try {
19523
19554
  cached = JSON.parse(readFileSync33(brandPath, "utf-8"));
@@ -20558,7 +20589,7 @@ async function startFileWatcher(opts = {}) {
20558
20589
 
20559
20590
  // app/lib/migrate-uploads.ts
20560
20591
  import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
20561
- import { dirname as dirname11, relative as relative6, resolve as resolve29 } from "path";
20592
+ import { dirname as dirname12, relative as relative6, resolve as resolve29 } from "path";
20562
20593
  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;
20563
20594
  async function walkFiles(dir) {
20564
20595
  const out = [];
@@ -20590,7 +20621,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
20590
20621
  for (const oldAbs of files) {
20591
20622
  const suffix = relative6(srcDir, oldAbs);
20592
20623
  const newAbs = resolve29(destDir, suffix);
20593
- await mkdir5(dirname11(newAbs), { recursive: true });
20624
+ await mkdir5(dirname12(newAbs), { recursive: true });
20594
20625
  await rename2(oldAbs, newAbs);
20595
20626
  moved++;
20596
20627
  const oldRel = relative6(dataRoot, oldAbs);
@@ -20682,7 +20713,7 @@ async function migrateUploads(opts = {}) {
20682
20713
  // app/lib/migrate-admin-webchat-sidecars.ts
20683
20714
  import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
20684
20715
  import { existsSync as existsSync31 } from "fs";
20685
- import { join as join32 } from "path";
20716
+ import { join as join33 } from "path";
20686
20717
  var ADMIN_ROLE2 = "admin";
20687
20718
  var WEBCHAT_CHANNEL2 = "webchat";
20688
20719
  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;
@@ -20727,7 +20758,7 @@ async function collectLiveSidecars(projectsRoot) {
20727
20758
  }
20728
20759
  for (const slug of slugs) {
20729
20760
  if (!slug.isDirectory()) continue;
20730
- const slugDir = join32(projectsRoot, slug.name);
20761
+ const slugDir = join33(projectsRoot, slug.name);
20731
20762
  let entries;
20732
20763
  try {
20733
20764
  entries = await readdir6(slugDir, { withFileTypes: true });
@@ -20736,9 +20767,9 @@ async function collectLiveSidecars(projectsRoot) {
20736
20767
  }
20737
20768
  for (const entry of entries) {
20738
20769
  if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
20739
- out.push(join32(slugDir, entry.name));
20770
+ out.push(join33(slugDir, entry.name));
20740
20771
  } else if (entry.isDirectory() && entry.name === "subagents") {
20741
- const subDir = join32(slugDir, entry.name);
20772
+ const subDir = join33(slugDir, entry.name);
20742
20773
  let subs;
20743
20774
  try {
20744
20775
  subs = await readdir6(subDir, { withFileTypes: true });
@@ -20746,7 +20777,7 @@ async function collectLiveSidecars(projectsRoot) {
20746
20777
  continue;
20747
20778
  }
20748
20779
  for (const s of subs) {
20749
- if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join32(subDir, s.name));
20780
+ if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join33(subDir, s.name));
20750
20781
  }
20751
20782
  }
20752
20783
  }
@@ -20758,7 +20789,7 @@ function shortId(path2) {
20758
20789
  return base.slice(0, 8);
20759
20790
  }
20760
20791
  async function migrateAdminWebchatSidecars(opts = {}) {
20761
- const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join32(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
20792
+ const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join33(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
20762
20793
  const usersFile = opts.usersFile ?? USERS_FILE;
20763
20794
  const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
20764
20795
  const resolveName = opts.resolveName ?? defaultResolveName;
@@ -22815,12 +22846,12 @@ function startTelegramNativeFileFollower(input) {
22815
22846
  }
22816
22847
 
22817
22848
  // server/telegram-descriptor.ts
22818
- import { resolve as resolve31, join as join33 } from "path";
22849
+ import { resolve as resolve31, join as join34 } from "path";
22819
22850
  function telegramGatewayUrl() {
22820
22851
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
22821
22852
  }
22822
22853
  function telegramServerPath() {
22823
- return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join33(__dirname, ".."), "services/telegram-channel/dist/server.js");
22854
+ return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, ".."), "services/telegram-channel/dist/server.js");
22824
22855
  }
22825
22856
 
22826
22857
  // app/lib/channel-pty-bridge/public-session-end-review.ts
@@ -23320,7 +23351,7 @@ function clientFrom(c) {
23320
23351
  );
23321
23352
  }
23322
23353
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
23323
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join34(PLATFORM_ROOT8, "config", "brand.json") : "";
23354
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join35(PLATFORM_ROOT8, "config", "brand.json") : "";
23324
23355
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
23325
23356
  if (BRAND_JSON_PATH && !existsSync33(BRAND_JSON_PATH)) {
23326
23357
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
@@ -23359,7 +23390,7 @@ var brandLoginOpts = {
23359
23390
  appleTouchIconPath: brandAppIcon512Path,
23360
23391
  themeColor: BRAND.defaultColors?.primary
23361
23392
  };
23362
- var ALIAS_DOMAINS_PATH = join34(homedir3(), BRAND.configDir, "alias-domains.json");
23393
+ var ALIAS_DOMAINS_PATH = join35(homedir3(), BRAND.configDir, "alias-domains.json");
23363
23394
  function loadAliasDomains() {
23364
23395
  try {
23365
23396
  if (!existsSync33(ALIAS_DOMAINS_PATH)) return null;
@@ -23391,7 +23422,7 @@ var app56 = new Hono();
23391
23422
  var nativeFileFollowers = /* @__PURE__ */ new Map();
23392
23423
  var waGateway = new WaGateway({
23393
23424
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
23394
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
23425
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
23395
23426
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
23396
23427
  // path-validation scope) is the sender's effective SESSION account, resolved
23397
23428
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -23406,7 +23437,7 @@ var waGateway = new WaGateway({
23406
23437
  caption,
23407
23438
  accountId,
23408
23439
  maxyAccountId,
23409
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, ".."))
23440
+ platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, ".."))
23410
23441
  });
23411
23442
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
23412
23443
  },
@@ -23571,9 +23602,15 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
23571
23602
  waHandleInbound: (input) => waGateway.handleInbound(input),
23572
23603
  tgHandleInbound: (input) => telegramGateway.handleInbound(input),
23573
23604
  sendWhatsAppText: async (accountId, destination, text) => {
23574
- const sock = getSocket(accountId);
23575
- if (!sock) throw new Error("WhatsApp disconnected \u2014 cannot deliver scheduled reply");
23576
- await sendTextMessage(sock, toWhatsappJid(destination), text, { accountId });
23605
+ const res = resolveSocket(accountId);
23606
+ if (!res.ok) {
23607
+ if (res.reason === "key-miss") {
23608
+ console.error(`[whatsapp-native] op=socket-key-miss accountId=${accountId} presentKeys=${res.presentKeys.join(",") || "none"}`);
23609
+ throw new Error(`WhatsApp socket key miss: no socket is registered for accountId=${accountId} (present keys: ${res.presentKeys.join(",") || "none"}). This is an account-keying fault, not a dropped link \u2014 do not advise re-pairing.`);
23610
+ }
23611
+ throw new Error(`WhatsApp disconnected: the socket for accountId=${accountId} is registered but its transport is down; cannot deliver scheduled reply.`);
23612
+ }
23613
+ await sendTextMessage(res.sock, toWhatsappJid(destination), text, { accountId: res.accountId });
23577
23614
  },
23578
23615
  sendTelegramText: async (botToken, chatId, text) => {
23579
23616
  const sent = await sendTelegramText(botToken, chatId, text);
@@ -24048,7 +24085,7 @@ var SW_SOURCE = (() => {
24048
24085
  function readInstalledVersion() {
24049
24086
  try {
24050
24087
  if (!PLATFORM_ROOT8) return "unknown";
24051
- const versionFile = join34(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
24088
+ const versionFile = join35(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
24052
24089
  if (!existsSync33(versionFile)) return "unknown";
24053
24090
  const content = readFileSync35(versionFile, "utf-8").trim();
24054
24091
  return content || "unknown";
@@ -24108,11 +24145,11 @@ ${clientErrorReporterScript}
24108
24145
  return html;
24109
24146
  }
24110
24147
  function loadBrandingCache(agentSlug) {
24111
- const configDir2 = join34(homedir3(), BRAND.configDir);
24148
+ const configDir2 = join35(homedir3(), BRAND.configDir);
24112
24149
  try {
24113
24150
  const accountId = getDefaultAccountId();
24114
24151
  if (!accountId) return null;
24115
- const cachePath = join34(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
24152
+ const cachePath = join35(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
24116
24153
  if (!existsSync33(cachePath)) return null;
24117
24154
  return JSON.parse(readFileSync35(cachePath, "utf-8"));
24118
24155
  } catch {
@@ -24336,7 +24373,7 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
24336
24373
  var httpServer = serve({ fetch: app56.fetch, port, hostname });
24337
24374
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
24338
24375
  {
24339
- const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, "..");
24376
+ const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, "..");
24340
24377
  const reconcileScript = resolve33(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
24341
24378
  const RECONCILE_INTERVAL_MS = 12e4;
24342
24379
  const runReconcile = () => {
@@ -24358,7 +24395,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
24358
24395
  loop.unref();
24359
24396
  }
24360
24397
  {
24361
- const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, "..");
24398
+ const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, "..");
24362
24399
  const auditScript = resolve33(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
24363
24400
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
24364
24401
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
@@ -24626,7 +24663,7 @@ if (bootAccountConfig?.whatsapp) {
24626
24663
  }
24627
24664
  init({
24628
24665
  configDir: configDirForWhatsApp,
24629
- platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join34(__dirname, "..")),
24666
+ platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, "..")),
24630
24667
  accountConfig: bootAccountConfig,
24631
24668
  onMessage: async (msg) => {
24632
24669
  if (msg.isOwnerMirror) {