@rubytech/create-maxy-code 0.1.506 → 0.1.507

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 (104) hide show
  1. package/package.json +2 -2
  2. package/payload/platform/config/brand.json +79 -18
  3. package/payload/platform/lib/account-schema-regions/dist/index.d.ts +17 -5
  4. package/payload/platform/lib/account-schema-regions/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/account-schema-regions/dist/index.js +20 -6
  6. package/payload/platform/lib/account-schema-regions/dist/index.js.map +1 -1
  7. package/payload/platform/lib/account-schema-regions/src/index.ts +20 -6
  8. package/payload/platform/plugins/admin/PLUGIN.md +36 -0
  9. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +48 -2
  10. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +7 -0
  11. package/payload/platform/plugins/aeo/PLUGIN.md +3 -0
  12. package/payload/platform/plugins/browser/PLUGIN.md +18 -0
  13. package/payload/platform/plugins/connector/PLUGIN.md +4 -0
  14. package/payload/platform/plugins/contacts/PLUGIN.md +9 -0
  15. package/payload/platform/plugins/docs/references/admin-ui.md +21 -1
  16. package/payload/platform/plugins/docs/references/plugins-guide.md +26 -0
  17. package/payload/platform/plugins/email/PLUGIN.md +17 -0
  18. package/payload/platform/plugins/filesystem/PLUGIN.md +6 -0
  19. package/payload/platform/plugins/google/PLUGIN.md +12 -0
  20. package/payload/platform/plugins/graph/PLUGIN.md +3 -0
  21. package/payload/platform/plugins/graph-viewer/PLUGIN.md +1 -0
  22. package/payload/platform/plugins/ledger/PLUGIN.md +7 -0
  23. package/payload/platform/plugins/memory/PLUGIN.md +41 -0
  24. package/payload/platform/plugins/outlook/PLUGIN.md +24 -0
  25. package/payload/platform/plugins/quickbooks/PLUGIN.md +15 -0
  26. package/payload/platform/plugins/replicate/PLUGIN.md +3 -0
  27. package/payload/platform/plugins/scheduling/PLUGIN.md +10 -0
  28. package/payload/platform/plugins/storage-broker/PLUGIN.md +12 -0
  29. package/payload/platform/plugins/telegram/PLUGIN.md +3 -0
  30. package/payload/platform/plugins/url-get/PLUGIN.md +1 -0
  31. package/payload/platform/plugins/voice-mirror/PLUGIN.md +5 -0
  32. package/payload/platform/plugins/whatsapp/PLUGIN.md +12 -0
  33. package/payload/platform/plugins/work/PLUGIN.md +15 -0
  34. package/payload/platform/plugins/workflows/PLUGIN.md +8 -0
  35. package/payload/platform/scripts/check-risk-class.mjs +145 -0
  36. package/payload/platform/scripts/lib/__pycache__/account-schema-owned-dirs.cpython-314.pyc +0 -0
  37. package/payload/platform/scripts/lib/provision-account-dir.sh +4 -1
  38. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/http-server.js +4 -0
  40. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  41. package/payload/platform/services/claude-session-manager/dist/index.js +8 -0
  42. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +13 -0
  44. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/tool-surface.js +33 -8
  46. package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -1
  47. package/payload/server/{chunk-5ADBNEJA.js → chunk-2WAXM5N2.js} +111 -111
  48. package/payload/server/maxy-edge.js +1 -1
  49. package/payload/server/public/activity.html +5 -5
  50. package/payload/server/public/agents.html +4 -4
  51. package/payload/server/public/assets/{AdminLoginScreens-D5KOQA8S.js → AdminLoginScreens-YT7jsh_H.js} +1 -1
  52. package/payload/server/public/assets/{AdminShell-C8wazpnz.js → AdminShell-Ckht9hmU.js} +1 -1
  53. package/payload/server/public/assets/{activity-CFqkDhTs.js → activity-DH3Wgc3O.js} +1 -1
  54. package/payload/server/public/assets/admin-DetvulAu.js +1 -0
  55. package/payload/server/public/assets/{agents-DPulfmrd.js → agents-X_IvDHLZ.js} +1 -1
  56. package/payload/server/public/assets/{browser-T_5xbnJh.js → browser-Bym8QhfA.js} +1 -1
  57. package/payload/server/public/assets/{calendar-CKjuiG8c.js → calendar-CFnufJOy.js} +1 -1
  58. package/payload/server/public/assets/chat-wrckyIpw.js +1 -0
  59. package/payload/server/public/assets/chevron-left-Dtk3jEK5.js +1 -0
  60. package/payload/server/public/assets/chevron-right-Dih6IZ8B.js +1 -0
  61. package/payload/server/public/assets/clock-iJCrrmWM.js +1 -0
  62. package/payload/server/public/assets/data-D76--TYs.js +1 -0
  63. package/payload/server/public/assets/{file-text-c6cA4Evd.js → file-text-zch0E1GJ.js} +1 -1
  64. package/payload/server/public/assets/{graph-DIk-o45J.js → graph-BavHLzpV.js} +1 -1
  65. package/payload/server/public/assets/{graph-labels-5bjxhC_p.js → graph-labels-CBwh4g-6.js} +1 -1
  66. package/payload/server/public/assets/{maximize-2-BCQkFb1_.js → maximize-2-bTn_Ozpi.js} +1 -1
  67. package/payload/server/public/assets/{operator-0UnNo2ms.js → operator-a4IOwf62.js} +1 -1
  68. package/payload/server/public/assets/page-3T2mE63b.js +1 -0
  69. package/payload/server/public/assets/{page-HVtUfub2.js → page-D6M1CmPe.js} +4 -4
  70. package/payload/server/public/assets/{public-CKEYyIPn.js → public-B3y_YU1G.js} +1 -1
  71. package/payload/server/public/assets/{rotate-ccw-dTpO5dhL.js → rotate-ccw-BGvzNB1b.js} +1 -1
  72. package/payload/server/public/assets/{routines-C6P1-Dto.js → routines-C7Dr16am.js} +1 -1
  73. package/payload/server/public/assets/{skills-ClrpVqlz.js → skills-DFeb3XO3.js} +1 -1
  74. package/payload/server/public/assets/{tasks-C8SNhSFC.js → tasks-CSfnCKJe.js} +1 -1
  75. package/payload/server/public/assets/{time-entry-format-CCO6N6XZ.js → time-entry-format-BgZqOOqG.js} +1 -1
  76. package/payload/server/public/assets/{triangle-alert-CHjdKpag.js → triangle-alert-DBJ7xz_t.js} +1 -1
  77. package/payload/server/public/assets/{useCopyFeedback-BTUu3-l8.js → useCopyFeedback-BFOujMl-.js} +1 -1
  78. package/payload/server/public/assets/useSubAccountSwitcher-BkQ5tA8A.css +1 -0
  79. package/payload/server/public/assets/{useVoiceRecorder-BeNqxmm2.js → useVoiceRecorder-BP6CpYQD.js} +1 -1
  80. package/payload/server/public/assets/{wrench-CeNnc7oO.js → wrench-DdaRhfzS.js} +1 -1
  81. package/payload/server/public/brand/fonts/inter-400.woff2 +0 -0
  82. package/payload/server/public/brand/fonts/inter-500.woff2 +0 -0
  83. package/payload/server/public/brand-defaults.css +47 -4
  84. package/payload/server/public/browser.html +4 -4
  85. package/payload/server/public/calendar.html +7 -7
  86. package/payload/server/public/chat.html +13 -13
  87. package/payload/server/public/data.html +11 -11
  88. package/payload/server/public/graph.html +9 -9
  89. package/payload/server/public/index.html +14 -14
  90. package/payload/server/public/operator.html +14 -14
  91. package/payload/server/public/public.html +13 -13
  92. package/payload/server/public/routines.html +6 -6
  93. package/payload/server/public/skills.html +5 -5
  94. package/payload/server/public/tasks.html +6 -6
  95. package/payload/server/server.js +702 -586
  96. package/payload/server/public/assets/admin-B-EGUWS4.js +0 -1
  97. package/payload/server/public/assets/chat-DWLYAA70.js +0 -1
  98. package/payload/server/public/assets/chevron-left-DBMCTKlT.js +0 -1
  99. package/payload/server/public/assets/chevron-right-SBAr6zzc.js +0 -1
  100. package/payload/server/public/assets/clock-kkzt7Scf.js +0 -1
  101. package/payload/server/public/assets/data-CV8N9qcy.js +0 -1
  102. package/payload/server/public/assets/page-JJa2xdzf.js +0 -1
  103. package/payload/server/public/assets/useSubAccountSwitcher-DyrH8DA8.css +0 -1
  104. /package/payload/server/public/assets/{useSubAccountSwitcher-DSW9vDi2.js → useSubAccountSwitcher-0PfRrN6i.js} +0 -0
@@ -118,7 +118,7 @@ import {
118
118
  vncLog,
119
119
  walkPremiumBundles,
120
120
  writeAdminUserAndPerson
121
- } from "./chunk-5ADBNEJA.js";
121
+ } from "./chunk-2WAXM5N2.js";
122
122
  import {
123
123
  D1_MAX_SQL_STATEMENT_BYTES,
124
124
  D1_QUERY_MAX_BODY_BYTES,
@@ -225,7 +225,16 @@ var require_dist2 = __commonJS({
225
225
  Object.defineProperty(exports, "__esModule", { value: true });
226
226
  exports.HOME_FIXED = void 0;
227
227
  exports.parseSchemaRegions = parseSchemaRegions2;
228
- exports.HOME_FIXED = Object.freeze(["projects", "contacts", "documents"]);
228
+ exports.HOME_FIXED = Object.freeze([
229
+ "projects",
230
+ "contacts",
231
+ "documents",
232
+ "output",
233
+ "generated",
234
+ "extracted",
235
+ "sites",
236
+ "uploads"
237
+ ]);
229
238
  var ONT_START2 = "<!-- ontology-buckets:start -->";
230
239
  var ONT_END2 = "<!-- ontology-buckets:end -->";
231
240
  var PLUGIN_START = "<!-- plugin-owned-dirs:start -->";
@@ -1921,6 +1930,12 @@ function invalidate(resource, accountId, source = "action") {
1921
1930
  keyGenerations.set(key, (keyGenerations.get(key) ?? 0) + 1);
1922
1931
  markOrDrop(key);
1923
1932
  }
1933
+ notifyAny(resource, accountId);
1934
+ }
1935
+ function notify(resource, accountId) {
1936
+ notifyAny(resource, accountId);
1937
+ }
1938
+ function notifyAny(resource, accountId) {
1924
1939
  pendingNotifications.set(`${resource}::${accountId ?? "*"}`, { resource, accountId });
1925
1940
  if (notifyTimer === null) {
1926
1941
  notifyTimer = setTimeout(flushNotifications, NOTIFY_COALESCE_MS);
@@ -2277,11 +2292,102 @@ function attachRouteCacheWatchers() {
2277
2292
  }
2278
2293
  }
2279
2294
 
2295
+ // server/lib/manager-events-subscriber.ts
2296
+ var TAG = "[webchat-pointer]";
2297
+ var TURN_EVENTS = /* @__PURE__ */ new Set(["row-updated", "row-created"]);
2298
+ var MAX_BACKOFF_MS = 3e4;
2299
+ var STABLE_CONNECTION_MS = 3e4;
2300
+ var lastStatusBySession = /* @__PURE__ */ new Map();
2301
+ function handleManagerFrame(raw) {
2302
+ const lines = raw.split("\n");
2303
+ const eventLine = lines.find((l) => l.startsWith("event: "));
2304
+ const dataLine = lines.find((l) => l.startsWith("data: "));
2305
+ if (!eventLine || !dataLine) return null;
2306
+ if (!TURN_EVENTS.has(eventLine.slice("event: ".length).trim())) return null;
2307
+ let body;
2308
+ try {
2309
+ body = JSON.parse(dataLine.slice("data: ".length));
2310
+ } catch {
2311
+ console.error(`${TAG} op=skip reason=unparseable-frame`);
2312
+ return null;
2313
+ }
2314
+ const sessionId = String(body.sessionId ?? "unknown").slice(0, 8);
2315
+ const accountId = typeof body.accountId === "string" && body.accountId ? body.accountId : null;
2316
+ if (!accountId) {
2317
+ console.error(`${TAG} op=skip reason=no-account sessionId=${sessionId}`);
2318
+ return null;
2319
+ }
2320
+ const status = String(body.status ?? "unknown");
2321
+ const fullSessionId = String(body.sessionId ?? "");
2322
+ if (fullSessionId && lastStatusBySession.get(fullSessionId) === status) {
2323
+ return null;
2324
+ }
2325
+ if (fullSessionId) lastStatusBySession.set(fullSessionId, status);
2326
+ console.log(
2327
+ `${TAG} op=event sessionId=${sessionId} accountId=${accountId.slice(0, 8)} activity=${status}`
2328
+ );
2329
+ notify("webchat-pointer", accountId);
2330
+ return { resource: "webchat-pointer", accountId };
2331
+ }
2332
+ var connections = 0;
2333
+ var started = false;
2334
+ var abort = null;
2335
+ function startManagerEventsSubscriber() {
2336
+ if (started) return;
2337
+ started = true;
2338
+ abort = new AbortController();
2339
+ void connectLoop(abort.signal);
2340
+ }
2341
+ async function connectLoop(signal) {
2342
+ let backoffMs = 1e3;
2343
+ for (; ; ) {
2344
+ if (signal.aborted) return;
2345
+ let port2;
2346
+ try {
2347
+ port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "webchat-pointer" });
2348
+ } catch {
2349
+ console.error(`${TAG} op=drop reason=manager-port-unset`);
2350
+ return;
2351
+ }
2352
+ const connectedAt = Date.now();
2353
+ try {
2354
+ const res = await fetch(`http://127.0.0.1:${port2}/events`, { signal });
2355
+ if (!res.ok || !res.body) throw new Error(`status ${res.status}`);
2356
+ connections += 1;
2357
+ console.log(`${TAG} op=subscribe upstream-count=${connections}`);
2358
+ const reader = res.body.getReader();
2359
+ const decoder = new TextDecoder();
2360
+ let buffer = "";
2361
+ for (; ; ) {
2362
+ const { done, value } = await reader.read();
2363
+ if (done) break;
2364
+ buffer += decoder.decode(value, { stream: true });
2365
+ let cut = buffer.indexOf("\n\n");
2366
+ while (cut !== -1) {
2367
+ handleManagerFrame(buffer.slice(0, cut));
2368
+ buffer = buffer.slice(cut + 2);
2369
+ cut = buffer.indexOf("\n\n");
2370
+ }
2371
+ }
2372
+ connections -= 1;
2373
+ } catch (err) {
2374
+ if (connections > 0) connections -= 1;
2375
+ if (signal.aborted) return;
2376
+ console.error(`${TAG} op=drop reason=${err instanceof Error ? err.message : String(err)}`);
2377
+ }
2378
+ if (signal.aborted) return;
2379
+ if (Date.now() - connectedAt >= STABLE_CONNECTION_MS) backoffMs = 1e3;
2380
+ console.log(`${TAG} op=reconnect inMs=${backoffMs} upstream-count=${connections}`);
2381
+ await new Promise((r) => setTimeout(r, backoffMs));
2382
+ backoffMs = Math.min(backoffMs * 2, MAX_BACKOFF_MS);
2383
+ }
2384
+ }
2385
+
2280
2386
  // server/index.ts
2281
2387
  import { monitorEventLoopDelay } from "perf_hooks";
2282
2388
 
2283
2389
  // app/lib/whatsapp/inbound/media-download-guard.ts
2284
- var TAG = "[media-guard]";
2390
+ var TAG2 = "[media-guard]";
2285
2391
  var inFlight2 = 0;
2286
2392
  var containedCount = 0;
2287
2393
  function containedSinceBoot() {
@@ -2311,13 +2417,13 @@ function handleEscapedMediaError(err, channel) {
2311
2417
  if (undiciFrame && inFlight2 > 0) {
2312
2418
  containedCount += 1;
2313
2419
  console.error(
2314
- `${TAG} op=contained channel=${channel} inFlight=${inFlight2} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)}
2420
+ `${TAG2} op=contained channel=${channel} inFlight=${inFlight2} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)}
2315
2421
  ${stack}`
2316
2422
  );
2317
2423
  return true;
2318
2424
  }
2319
2425
  console.error(
2320
- `${TAG} op=escaped channel=${channel} inFlight=${inFlight2} undiciFrame=${undiciFrame} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)} contained=false`
2426
+ `${TAG2} op=escaped channel=${channel} inFlight=${inFlight2} undiciFrame=${undiciFrame} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)} contained=false`
2321
2427
  );
2322
2428
  return false;
2323
2429
  }
@@ -2342,7 +2448,7 @@ function installMediaDownloadGuard() {
2342
2448
  );
2343
2449
  process.exit(1);
2344
2450
  });
2345
- console.error(`${TAG} op=installed`);
2451
+ console.error(`${TAG2} op=installed`);
2346
2452
  }
2347
2453
 
2348
2454
  // app/lib/whatsapp/ingest-audit.ts
@@ -2352,7 +2458,7 @@ import { join as join4 } from "path";
2352
2458
  // app/lib/whatsapp/ingest-ledger.ts
2353
2459
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, appendFileSync as appendFileSync2, readFileSync as readFileSync3, writeFileSync, readdirSync as readdirSync3 } from "fs";
2354
2460
  import { join as join3 } from "path";
2355
- var TAG2 = "[wa-ingest-ledger]";
2461
+ var TAG3 = "[wa-ingest-ledger]";
2356
2462
  var LEDGER_ROOT = () => join3(process.env.MAXY_DIR_OVERRIDE ?? MAXY_DIR, "data", "whatsapp-ingest-ledger");
2357
2463
  var ensuredRoots = /* @__PURE__ */ new Set();
2358
2464
  function ledgerFilePath(account) {
@@ -2374,7 +2480,7 @@ function appendStanza(entry) {
2374
2480
  appendFileSync2(ledgerFilePath(entry.account), JSON.stringify(row) + "\n");
2375
2481
  } catch (err) {
2376
2482
  console.error(
2377
- `${TAG2} FAIL op=append msgId=${entry.msgId} err=${err instanceof Error ? err.message : String(err)}`
2483
+ `${TAG3} FAIL op=append msgId=${entry.msgId} err=${err instanceof Error ? err.message : String(err)}`
2378
2484
  );
2379
2485
  }
2380
2486
  }
@@ -2388,7 +2494,7 @@ function markDeclined(entry) {
2388
2494
  appendFileSync2(ledgerFilePath(entry.account), JSON.stringify(row) + "\n");
2389
2495
  } catch (err) {
2390
2496
  console.error(
2391
- `${TAG2} FAIL op=decline msgId=${entry.msgId} err=${err instanceof Error ? err.message : String(err)}`
2497
+ `${TAG3} FAIL op=decline msgId=${entry.msgId} err=${err instanceof Error ? err.message : String(err)}`
2392
2498
  );
2393
2499
  }
2394
2500
  }
@@ -2449,7 +2555,7 @@ function listLedgerAccounts() {
2449
2555
  }
2450
2556
 
2451
2557
  // app/lib/whatsapp/ingest-audit.ts
2452
- var TAG3 = "[wa-ingest-audit]";
2558
+ var TAG4 = "[wa-ingest-audit]";
2453
2559
  var DEFAULT_GRACE_MS = 10 * 60 * 1e3;
2454
2560
  var DEFAULT_RETAIN_MS = 24 * 60 * 60 * 1e3;
2455
2561
  var idCache = /* @__PURE__ */ new Map();
@@ -2551,7 +2657,7 @@ function runIngestAudit(opts) {
2551
2657
  }
2552
2658
  result.oldestUnpersistedMin = Math.round(oldestUnpersistedAgeMs / 6e4);
2553
2659
  console.error(
2554
- `${TAG3} op=reconcile stanzas=${result.stanzas} persisted=${result.persisted} unpersisted=${result.unpersisted.length} ids=${result.unpersisted.join(",") || "none"} oldestUnpersistedMin=${result.oldestUnpersistedMin} skippedStatus=${result.skippedStatus} skippedReaction=${result.skippedReaction} declined=${result.declined} contained=${containedSinceBoot()} inFlight=${mediaDownloadsInFlight()} guard=${guardInstalled() ? "installed" : "absent"}`
2660
+ `${TAG4} op=reconcile stanzas=${result.stanzas} persisted=${result.persisted} unpersisted=${result.unpersisted.length} ids=${result.unpersisted.join(",") || "none"} oldestUnpersistedMin=${result.oldestUnpersistedMin} skippedStatus=${result.skippedStatus} skippedReaction=${result.skippedReaction} declined=${result.declined} contained=${containedSinceBoot()} inFlight=${mediaDownloadsInFlight()} guard=${guardInstalled() ? "installed" : "absent"}`
2555
2661
  );
2556
2662
  return result;
2557
2663
  }
@@ -3044,7 +3150,7 @@ import fsSync from "fs";
3044
3150
  import fs from "fs/promises";
3045
3151
  import path from "path";
3046
3152
  import os from "os";
3047
- var TAG4 = "[whatsapp:auth]";
3153
+ var TAG5 = "[whatsapp:auth]";
3048
3154
  function resolveAuthDir(configDir2, accountId) {
3049
3155
  return path.join(os.homedir(), configDir2, "credentials", "whatsapp", accountId);
3050
3156
  }
@@ -3076,7 +3182,7 @@ async function authExists(authDir) {
3076
3182
  JSON.parse(raw);
3077
3183
  return true;
3078
3184
  } catch (err) {
3079
- console.warn(`${TAG4} credential validation failed path=${credsPath}: ${String(err)}`);
3185
+ console.warn(`${TAG5} credential validation failed path=${credsPath}: ${String(err)}`);
3080
3186
  return false;
3081
3187
  }
3082
3188
  }
@@ -3103,9 +3209,9 @@ function maybeRestoreCredsFromBackup(authDir) {
3103
3209
  if (!backupRaw) return;
3104
3210
  JSON.parse(backupRaw);
3105
3211
  fsSync.copyFileSync(backupPath, credsPath);
3106
- console.error(`${TAG4} restored corrupted creds.json from backup in ${authDir}`);
3212
+ console.error(`${TAG5} restored corrupted creds.json from backup in ${authDir}`);
3107
3213
  } catch (err) {
3108
- console.warn(`${TAG4} credential restore failed authDir=${authDir}: ${String(err)}`);
3214
+ console.warn(`${TAG5} credential restore failed authDir=${authDir}: ${String(err)}`);
3109
3215
  }
3110
3216
  }
3111
3217
  function readSelfId(authDir) {
@@ -3128,7 +3234,7 @@ function readSelfId(authDir) {
3128
3234
  }
3129
3235
  return { e164, jid, lid };
3130
3236
  } catch (err) {
3131
- console.warn(`${TAG4} readSelfId failed authDir=${authDir}: ${String(err)}`);
3237
+ console.warn(`${TAG5} readSelfId failed authDir=${authDir}: ${String(err)}`);
3132
3238
  return { e164: null, jid: null, lid: null };
3133
3239
  }
3134
3240
  }
@@ -3162,21 +3268,21 @@ async function clearAuth(authDir) {
3162
3268
  try {
3163
3269
  await fs.access(authDir);
3164
3270
  } catch {
3165
- console.error(`${TAG4} no auth dir found at ${authDir}`);
3271
+ console.error(`${TAG5} no auth dir found at ${authDir}`);
3166
3272
  return false;
3167
3273
  }
3168
3274
  await fs.rm(authDir, { recursive: true, force: true });
3169
- console.error(`${TAG4} cleared credentials at ${authDir}`);
3275
+ console.error(`${TAG5} cleared credentials at ${authDir}`);
3170
3276
  return true;
3171
3277
  }
3172
3278
  function discardAuthDirSync(authDir) {
3173
3279
  try {
3174
3280
  if (!fsSync.existsSync(authDir)) return false;
3175
3281
  fsSync.rmSync(authDir, { recursive: true, force: true });
3176
- console.error(`${TAG4} discarded credential dir ${authDir}`);
3282
+ console.error(`${TAG5} discarded credential dir ${authDir}`);
3177
3283
  return true;
3178
3284
  } catch (err) {
3179
- console.warn(`${TAG4} discardAuthDirSync failed authDir=${authDir}: ${String(err)}`);
3285
+ console.warn(`${TAG5} discardAuthDirSync failed authDir=${authDir}: ${String(err)}`);
3180
3286
  return false;
3181
3287
  }
3182
3288
  }
@@ -3208,7 +3314,7 @@ import { createRequire } from "module";
3208
3314
  // app/lib/whatsapp/baileys-debug-window.ts
3209
3315
  import fs2 from "fs";
3210
3316
  import path2 from "path";
3211
- var TAG5 = "[whatsapp:session]";
3317
+ var TAG6 = "[whatsapp:session]";
3212
3318
  var SENTINEL_BASENAME = "baileys-debug-until";
3213
3319
  var STAT_INTERVAL_MS = 1e3;
3214
3320
  var VALID_LEVELS = /* @__PURE__ */ new Set(["trace", "debug", "info"]);
@@ -3248,11 +3354,11 @@ function resolveDebugWindow(authDir, nowMs = Date.now()) {
3248
3354
  const wasActive = prev?.state.active ?? false;
3249
3355
  if (!wasActive && state.active) {
3250
3356
  console.error(
3251
- `${TAG5} op=baileys-debug-window-open account=${path2.basename(authDir)} level=${state.level} until=${new Date(deadlineMs).toISOString()}`
3357
+ `${TAG6} op=baileys-debug-window-open account=${path2.basename(authDir)} level=${state.level} until=${new Date(deadlineMs).toISOString()}`
3252
3358
  );
3253
3359
  } else if (wasActive && !state.active) {
3254
3360
  console.error(
3255
- `${TAG5} op=baileys-debug-window-close account=${path2.basename(authDir)}`
3361
+ `${TAG6} op=baileys-debug-window-close account=${path2.basename(authDir)}`
3256
3362
  );
3257
3363
  }
3258
3364
  cache2.set(authDir, { checkedAtMs: nowMs, state });
@@ -3260,7 +3366,7 @@ function resolveDebugWindow(authDir, nowMs = Date.now()) {
3260
3366
  }
3261
3367
 
3262
3368
  // app/lib/whatsapp/session.ts
3263
- var TAG6 = "[whatsapp:session]";
3369
+ var TAG7 = "[whatsapp:session]";
3264
3370
  var WIRE_TAG = "[whatsapp:wire]";
3265
3371
  var baileysPkgVersion = (() => {
3266
3372
  try {
@@ -3270,7 +3376,7 @@ var baileysPkgVersion = (() => {
3270
3376
  return "unknown";
3271
3377
  }
3272
3378
  })();
3273
- console.error(`${TAG6} baileys package loaded version=${baileysPkgVersion}`);
3379
+ console.error(`${TAG7} baileys package loaded version=${baileysPkgVersion}`);
3274
3380
  var __BAILEYS_TAG = "[whatsapp:baileys]";
3275
3381
  var INSPECT_OPTS = {
3276
3382
  depth: null,
@@ -3331,7 +3437,7 @@ function createBaileysLogger(bindings = {}, authDir) {
3331
3437
  }
3332
3438
  var credsSaveQueue = Promise.resolve();
3333
3439
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
3334
- console.error(`${TAG6} draining credential save queue\u2026`);
3440
+ console.error(`${TAG7} draining credential save queue\u2026`);
3335
3441
  const timer = new Promise(
3336
3442
  (resolve46) => setTimeout(() => resolve46("timeout"), timeoutMs)
3337
3443
  );
@@ -3340,9 +3446,9 @@ async function drainCredsSaveQueue(timeoutMs = 5e3) {
3340
3446
  timer
3341
3447
  ]);
3342
3448
  if (result === "timeout") {
3343
- console.error(`${TAG6} credential save queue drain timed out after ${timeoutMs}ms`);
3449
+ console.error(`${TAG7} credential save queue drain timed out after ${timeoutMs}ms`);
3344
3450
  } else {
3345
- console.error(`${TAG6} credential save queue drained`);
3451
+ console.error(`${TAG7} credential save queue drained`);
3346
3452
  }
3347
3453
  }
3348
3454
  function readCredsJsonRaw2(filePath) {
@@ -3365,11 +3471,11 @@ async function safeSaveCreds(authDir, saveCreds) {
3365
3471
  JSON.parse(raw);
3366
3472
  fsSync2.copyFileSync(credsPath, backupPath);
3367
3473
  } catch (err) {
3368
- console.warn(`${TAG6} backup pre-copy failed (parse or write) authDir=${authDir}: ${String(err)}`);
3474
+ console.warn(`${TAG7} backup pre-copy failed (parse or write) authDir=${authDir}: ${String(err)}`);
3369
3475
  }
3370
3476
  }
3371
3477
  } catch (err) {
3372
- console.warn(`${TAG6} backup preparation failed authDir=${authDir}: ${String(err)}`);
3478
+ console.warn(`${TAG7} backup preparation failed authDir=${authDir}: ${String(err)}`);
3373
3479
  }
3374
3480
  try {
3375
3481
  await Promise.resolve(saveCreds());
@@ -3377,20 +3483,20 @@ async function safeSaveCreds(authDir, saveCreds) {
3377
3483
  try {
3378
3484
  const stats = await fs3.stat(credsPath);
3379
3485
  if (stats.size <= 1) {
3380
- console.error(`${TAG6} WARNING: creds file empty/truncated after save path=${credsPath} size=${stats.size}`);
3486
+ console.error(`${TAG7} WARNING: creds file empty/truncated after save path=${credsPath} size=${stats.size}`);
3381
3487
  } else {
3382
- console.error(`${TAG6} creds saved and verified path=${credsPath} size=${stats.size}`);
3488
+ console.error(`${TAG7} creds saved and verified path=${credsPath} size=${stats.size}`);
3383
3489
  }
3384
3490
  } catch (statErr) {
3385
- console.error(`${TAG6} creds NOT found on disk after save path=${credsPath}: ${String(statErr)}`);
3491
+ console.error(`${TAG7} creds NOT found on disk after save path=${credsPath}: ${String(statErr)}`);
3386
3492
  }
3387
3493
  } catch (err) {
3388
- console.error(`${TAG6} failed saving creds to ${authDir}: ${String(err)}`);
3494
+ console.error(`${TAG7} failed saving creds to ${authDir}: ${String(err)}`);
3389
3495
  }
3390
3496
  }
3391
3497
  function enqueueSaveCreds(authDir, saveCreds) {
3392
3498
  credsSaveQueue = credsSaveQueue.then(() => safeSaveCreds(authDir, saveCreds)).catch((err) => {
3393
- console.error(`${TAG6} creds save queue error: ${String(err)}`);
3499
+ console.error(`${TAG7} creds save queue error: ${String(err)}`);
3394
3500
  });
3395
3501
  }
3396
3502
  async function createWaSocket(opts) {
@@ -3404,12 +3510,12 @@ async function createWaSocket(opts) {
3404
3510
  if (!silent) {
3405
3511
  const preCensus = credsCensus(authDir);
3406
3512
  console.error(
3407
- `${TAG6} op=creds-pre cid=${cid} account=${acct} credsPresent=${preCensus.credsPresent} registered=${preCensus.registered} hasAccount=${preCensus.hasAccountSignature}`
3513
+ `${TAG7} op=creds-pre cid=${cid} account=${acct} credsPresent=${preCensus.credsPresent} registered=${preCensus.registered} hasAccount=${preCensus.hasAccountSignature}`
3408
3514
  );
3409
3515
  }
3410
3516
  const openTs = Date.now();
3411
3517
  console.error(
3412
- `${TAG6} op=socket-open cid=${cid} account=${acct} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")} openTs=${openTs}`
3518
+ `${TAG7} op=socket-open cid=${cid} account=${acct} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")} openTs=${openTs}`
3413
3519
  );
3414
3520
  const baileysLogger = createBaileysLogger({}, authDir);
3415
3521
  const sock = makeWASocket({
@@ -3426,7 +3532,7 @@ async function createWaSocket(opts) {
3426
3532
  fireInitQueries: false
3427
3533
  });
3428
3534
  sock.ev.on("creds.update", () => {
3429
- console.error(`${TAG6} creds.update received \u2014 saving to ${authDir}`);
3535
+ console.error(`${TAG7} creds.update received \u2014 saving to ${authDir}`);
3430
3536
  enqueueSaveCreds(authDir, saveCreds);
3431
3537
  });
3432
3538
  let qrSequence = 0;
@@ -3446,14 +3552,14 @@ async function createWaSocket(opts) {
3446
3552
  parts.push(`disconnectReason=${formatError(update.lastDisconnect.error)}`);
3447
3553
  }
3448
3554
  if (!silent && parts.length > 0) {
3449
- console.error(`${TAG6} connection.update ${parts.join(" ")}`);
3555
+ console.error(`${TAG7} connection.update ${parts.join(" ")}`);
3450
3556
  }
3451
3557
  if (update.qr && !silent) {
3452
3558
  const now = Date.now();
3453
3559
  const sinceLastRefMs = lastQrTs ? now - lastQrTs : null;
3454
3560
  lastQrTs = now;
3455
3561
  console.error(
3456
- `${TAG6} op=qr cid=${cid} qr=#${qrSequence} sinceOpenMs=${now - openTs} sinceLastRefMs=${sinceLastRefMs ?? "n/a"}`
3562
+ `${TAG7} op=qr cid=${cid} qr=#${qrSequence} sinceOpenMs=${now - openTs} sinceLastRefMs=${sinceLastRefMs ?? "n/a"}`
3457
3563
  );
3458
3564
  }
3459
3565
  if (update.isNewLogin === true && !pairSuccessLogged && !silent) {
@@ -3462,7 +3568,7 @@ async function createWaSocket(opts) {
3462
3568
  const sinceCodeIssuedMs = codeIssuedTs ? Date.now() - codeIssuedTs : null;
3463
3569
  const afterCensus = credsCensus(authDir);
3464
3570
  console.error(
3465
- `${TAG6} op=pair-success cid=${cid} account=${acct} sinceCodeIssuedMs=${sinceCodeIssuedMs ?? "n/a"} hasAccountAfter=${afterCensus.hasAccountSignature}`
3571
+ `${TAG7} op=pair-success cid=${cid} account=${acct} sinceCodeIssuedMs=${sinceCodeIssuedMs ?? "n/a"} hasAccountAfter=${afterCensus.hasAccountSignature}`
3466
3572
  );
3467
3573
  }
3468
3574
  if (update.qr && onQr) {
@@ -3472,25 +3578,25 @@ async function createWaSocket(opts) {
3472
3578
  const status = getStatusCode(update.lastDisconnect?.error);
3473
3579
  if (!silent) {
3474
3580
  console.error(
3475
- `${TAG6} op=close cid=${cid} account=${acct} status=${status ?? "unknown"} reason="${formatError(update.lastDisconnect?.error)}" socketLifeMs=${Date.now() - openTs} kind=${closeKind(status, everOpen)}`
3581
+ `${TAG7} op=close cid=${cid} account=${acct} status=${status ?? "unknown"} reason="${formatError(update.lastDisconnect?.error)}" socketLifeMs=${Date.now() - openTs} kind=${closeKind(status, everOpen)}`
3476
3582
  );
3477
3583
  }
3478
3584
  if (status === DisconnectReason.loggedOut && !silent) {
3479
- console.error(`${TAG6} session logged out (401) \u2014 re-link required`);
3585
+ console.error(`${TAG7} session logged out (401) \u2014 re-link required`);
3480
3586
  }
3481
3587
  }
3482
3588
  if (update.connection === "open") {
3483
3589
  everOpen = true;
3484
- if (!silent) console.error(`${TAG6} connected`);
3590
+ if (!silent) console.error(`${TAG7} connected`);
3485
3591
  }
3486
3592
  onConnectionUpdate?.(update);
3487
3593
  } catch (err) {
3488
- console.error(`${TAG6} connection.update handler error: ${String(err)}`);
3594
+ console.error(`${TAG7} connection.update handler error: ${String(err)}`);
3489
3595
  }
3490
3596
  });
3491
3597
  if (sock.ws && typeof sock.ws.on === "function") {
3492
3598
  sock.ws.on("error", (err) => {
3493
- console.error(`${TAG6} WebSocket error: ${String(err)}`);
3599
+ console.error(`${TAG7} WebSocket error: ${String(err)}`);
3494
3600
  });
3495
3601
  sock.ws.on("CB:message", (node) => {
3496
3602
  const attrs = node?.attrs ?? {};
@@ -3643,7 +3749,7 @@ function withTimeout(label, promise, timeoutMs) {
3643
3749
  }
3644
3750
 
3645
3751
  // app/lib/whatsapp/init-queries.ts
3646
- var TAG7 = "[whatsapp:init]";
3752
+ var TAG8 = "[whatsapp:init]";
3647
3753
  var DEFAULT_QUERY_TIMEOUT_MS = 15e3;
3648
3754
  var INSPECT_OPTS2 = {
3649
3755
  depth: null,
@@ -3671,20 +3777,20 @@ async function runInitQueries(sock, ctx) {
3671
3777
  elapsedMs: 0
3672
3778
  };
3673
3779
  console.error(
3674
- `${TAG7} runInitQueries start account=${ctx.accountId} attempt=${ctx.attempt} selfPhone=${ctx.selfPhone ?? "unknown"} authDir=${ctx.authDir} queryTimeoutMs=${queryTimeoutMs}`
3780
+ `${TAG8} runInitQueries start account=${ctx.accountId} attempt=${ctx.attempt} selfPhone=${ctx.selfPhone ?? "unknown"} authDir=${ctx.authDir} queryTimeoutMs=${queryTimeoutMs}`
3675
3781
  );
3676
3782
  console.error(
3677
- `${TAG7} fetchProps SKIPPED account=${ctx.accountId} reason=no-platform-consumer`
3783
+ `${TAG8} fetchProps SKIPPED account=${ctx.accountId} reason=no-platform-consumer`
3678
3784
  );
3679
3785
  if (ctx.signal?.aborted) {
3680
3786
  result.aborted = true;
3681
3787
  result.elapsedMs = Date.now() - startedAt;
3682
3788
  console.error(
3683
- `${TAG7} runInitQueries aborted before start account=${ctx.accountId}`
3789
+ `${TAG8} runInitQueries aborted before start account=${ctx.accountId}`
3684
3790
  );
3685
3791
  return result;
3686
3792
  }
3687
- console.error(`${TAG7} fetchBlocklist start account=${ctx.accountId}`);
3793
+ console.error(`${TAG8} fetchBlocklist start account=${ctx.accountId}`);
3688
3794
  try {
3689
3795
  const blocklist = await withTimeout(
3690
3796
  "fetchBlocklist",
@@ -3694,24 +3800,24 @@ async function runInitQueries(sock, ctx) {
3694
3800
  const count = Array.isArray(blocklist) ? blocklist.length : 0;
3695
3801
  result.blocklistOk = true;
3696
3802
  console.error(
3697
- `${TAG7} fetchBlocklist ok account=${ctx.accountId} count=${count}`
3803
+ `${TAG8} fetchBlocklist ok account=${ctx.accountId} count=${count}`
3698
3804
  );
3699
3805
  } catch (err) {
3700
3806
  const formatted = formatErr(err);
3701
3807
  result.errors.blocklist = formatted;
3702
3808
  console.error(
3703
- `${TAG7} fetchBlocklist FAILED account=${ctx.accountId}: ${formatted}`
3809
+ `${TAG8} fetchBlocklist FAILED account=${ctx.accountId}: ${formatted}`
3704
3810
  );
3705
3811
  }
3706
3812
  if (ctx.signal?.aborted) {
3707
3813
  result.aborted = true;
3708
3814
  result.elapsedMs = Date.now() - startedAt;
3709
3815
  console.error(
3710
- `${TAG7} runInitQueries aborted mid-sequence account=${ctx.accountId} after=fetchBlocklist`
3816
+ `${TAG8} runInitQueries aborted mid-sequence account=${ctx.accountId} after=fetchBlocklist`
3711
3817
  );
3712
3818
  return result;
3713
3819
  }
3714
- console.error(`${TAG7} fetchPrivacySettings start account=${ctx.accountId}`);
3820
+ console.error(`${TAG8} fetchPrivacySettings start account=${ctx.accountId}`);
3715
3821
  try {
3716
3822
  const settings = await withTimeout(
3717
3823
  "fetchPrivacySettings",
@@ -3721,18 +3827,18 @@ async function runInitQueries(sock, ctx) {
3721
3827
  );
3722
3828
  result.privacySettingsOk = true;
3723
3829
  console.error(
3724
- `${TAG7} fetchPrivacySettings ok account=${ctx.accountId} keys=${settings ? Object.keys(settings).join(",") : ""}`
3830
+ `${TAG8} fetchPrivacySettings ok account=${ctx.accountId} keys=${settings ? Object.keys(settings).join(",") : ""}`
3725
3831
  );
3726
3832
  } catch (err) {
3727
3833
  const formatted = formatErr(err);
3728
3834
  result.errors.privacySettings = formatted;
3729
3835
  console.error(
3730
- `${TAG7} fetchPrivacySettings FAILED account=${ctx.accountId}: ${formatted}`
3836
+ `${TAG8} fetchPrivacySettings FAILED account=${ctx.accountId}: ${formatted}`
3731
3837
  );
3732
3838
  }
3733
3839
  result.elapsedMs = Date.now() - startedAt;
3734
3840
  console.error(
3735
- `${TAG7} runInitQueries done account=${ctx.accountId} blocklistOk=${result.blocklistOk} privacySettingsOk=${result.privacySettingsOk} elapsedMs=${result.elapsedMs}`
3841
+ `${TAG8} runInitQueries done account=${ctx.accountId} blocklistOk=${result.blocklistOk} privacySettingsOk=${result.privacySettingsOk} elapsedMs=${result.elapsedMs}`
3736
3842
  );
3737
3843
  return result;
3738
3844
  }
@@ -4474,7 +4580,7 @@ function isDuplicateInbound(key) {
4474
4580
  }
4475
4581
 
4476
4582
  // app/lib/whatsapp/inbound/self-chat.ts
4477
- var TAG8 = "[whatsapp:self-chat]";
4583
+ var TAG9 = "[whatsapp:self-chat]";
4478
4584
  function normalizeJid(jid) {
4479
4585
  const m = jid.match(/^(\d+)(?::\d+)?@(s\.whatsapp\.net|lid)$/i);
4480
4586
  return m ? `${m[1]}@${m[2].toLowerCase()}` : jid;
@@ -4494,10 +4600,10 @@ function evaluateSelfChatCommand(input) {
4494
4600
  const connAtMs = input.lastConnectedAtMs ?? 0;
4495
4601
  const msgId = input.msgId ?? "?";
4496
4602
  console.error(
4497
- `${TAG8} op=seen account=${input.accountId} msgId=${msgId} tsMs=${tsMs} connAtMs=${connAtMs} fromMe=true`
4603
+ `${TAG9} op=seen account=${input.accountId} msgId=${msgId} tsMs=${tsMs} connAtMs=${connAtMs} fromMe=true`
4498
4604
  );
4499
4605
  const skip = (reason) => {
4500
- console.error(`${TAG8} op=skip account=${input.accountId} msgId=${msgId} reason=${reason}`);
4606
+ console.error(`${TAG9} op=skip account=${input.accountId} msgId=${msgId} reason=${reason}`);
4501
4607
  return { kind: "skip", reason };
4502
4608
  };
4503
4609
  if (input.msgId && isAgentSentMessage(input.msgId)) return skip("echo");
@@ -4505,13 +4611,13 @@ function evaluateSelfChatCommand(input) {
4505
4611
  if (isDuplicateInbound(`${input.accountId}:${input.remoteJid}:${input.msgId}`)) return skip("duplicate");
4506
4612
  if (!input.text) return skip("no-text");
4507
4613
  console.error(
4508
- `${TAG8} op=dispatch account=${input.accountId} msgId=${msgId} bytes=${Buffer.byteLength(input.text, "utf8")} agentType=admin`
4614
+ `${TAG9} op=dispatch account=${input.accountId} msgId=${msgId} bytes=${Buffer.byteLength(input.text, "utf8")} agentType=admin`
4509
4615
  );
4510
4616
  return { kind: "dispatch", text: input.text };
4511
4617
  }
4512
4618
 
4513
4619
  // app/lib/whatsapp/activity.ts
4514
- var TAG9 = "[whatsapp:activity]";
4620
+ var TAG10 = "[whatsapp:activity]";
4515
4621
  var RECENT_EVENTS_MAX = 200;
4516
4622
  var counters = /* @__PURE__ */ new Map();
4517
4623
  var recentEvents = [];
@@ -4539,10 +4645,10 @@ function recordActivity(event) {
4539
4645
  recentEvents.splice(0, recentEvents.length - RECENT_EVENTS_MAX);
4540
4646
  }
4541
4647
  console.error(
4542
- `${TAG9} channel-activity: direction=${direction} account=${accountId} jid=${jid}` + (messageType ? ` type=${messageType}` : "")
4648
+ `${TAG10} channel-activity: direction=${direction} account=${accountId} jid=${jid}` + (messageType ? ` type=${messageType}` : "")
4543
4649
  );
4544
4650
  } catch (err) {
4545
- console.error(`${TAG9} recording failed: ${String(err)}`);
4651
+ console.error(`${TAG10} recording failed: ${String(err)}`);
4546
4652
  }
4547
4653
  }
4548
4654
  function getChannelActivity(accountId) {
@@ -4563,7 +4669,7 @@ function getChannelActivity(accountId) {
4563
4669
  }
4564
4670
 
4565
4671
  // app/lib/whatsapp/outbound/send.ts
4566
- var TAG10 = "[whatsapp:outbound]";
4672
+ var TAG11 = "[whatsapp:outbound]";
4567
4673
  function buildQuoted(q2) {
4568
4674
  return {
4569
4675
  key: {
@@ -4584,14 +4690,14 @@ async function sendTextMessage(sock, to, text, opts) {
4584
4690
  const messageId = result?.key?.id;
4585
4691
  if (messageId) {
4586
4692
  trackAgentSentMessage(messageId);
4587
- console.error(`${TAG10} sent text to=${jid} id=${messageId}`);
4693
+ console.error(`${TAG11} sent text to=${jid} id=${messageId}`);
4588
4694
  }
4589
4695
  if (opts?.accountId) {
4590
4696
  recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: "text" });
4591
4697
  }
4592
4698
  return { success: true, messageId: messageId ?? void 0 };
4593
4699
  } catch (err) {
4594
- console.error(`${TAG10} send failed to=${to}: ${String(err)}`);
4700
+ console.error(`${TAG11} send failed to=${to}: ${String(err)}`);
4595
4701
  return { success: false, error: String(err) };
4596
4702
  }
4597
4703
  }
@@ -4668,20 +4774,20 @@ async function sendMediaMessage(sock, to, media, opts) {
4668
4774
  const messageId = result?.key?.id;
4669
4775
  if (messageId) {
4670
4776
  trackAgentSentMessage(messageId);
4671
- console.error(`${TAG10} sent ${media.type} to=${jid} id=${messageId}`);
4777
+ console.error(`${TAG11} sent ${media.type} to=${jid} id=${messageId}`);
4672
4778
  }
4673
4779
  if (opts?.accountId) {
4674
4780
  recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: media.type });
4675
4781
  }
4676
4782
  return { success: true, messageId: messageId ?? void 0 };
4677
4783
  } catch (err) {
4678
- console.error(`${TAG10} send media failed to=${to}: ${String(err)}`);
4784
+ console.error(`${TAG11} send media failed to=${to}: ${String(err)}`);
4679
4785
  return { success: false, error: String(err) };
4680
4786
  }
4681
4787
  }
4682
4788
 
4683
4789
  // app/lib/whatsapp/persist-message.ts
4684
- var TAG11 = "[whatsapp-persist]";
4790
+ var TAG12 = "[whatsapp-persist]";
4685
4791
  var sessionWriteLocks = /* @__PURE__ */ new Map();
4686
4792
  async function persistWhatsAppMessage(input) {
4687
4793
  if (!input.body && !input.attachmentId || !input.msgKeyId) return null;
@@ -4732,14 +4838,14 @@ async function persistWhatsAppMessage(input) {
4732
4838
  };
4733
4839
  const result = await session.run(cypher, params);
4734
4840
  if (result.records.length === 0) {
4735
- console.error(`${TAG11} skip reason=conversation-not-found accountId=${input.platformAccountId} cacheKey=${input.cacheKey} messageId=${messageId}`);
4841
+ console.error(`${TAG12} skip reason=conversation-not-found accountId=${input.platformAccountId} cacheKey=${input.cacheKey} messageId=${messageId}`);
4736
4842
  return null;
4737
4843
  }
4738
4844
  const rec = result.records[0];
4739
4845
  const senderElementId = rec.get("senderElementId");
4740
4846
  const senderReused = rec.get("senderReused") === true;
4741
4847
  console.error(
4742
- `${TAG11} sender-resolved telephone=${senderTelephone} nodeKind=Person elementId=${senderElementId} reused=${senderReused}`
4848
+ `${TAG12} sender-resolved telephone=${senderTelephone} nodeKind=Person elementId=${senderElementId} reused=${senderReused}`
4743
4849
  );
4744
4850
  const diskRecord = {
4745
4851
  messageId,
@@ -4761,18 +4867,18 @@ async function persistWhatsAppMessage(input) {
4761
4867
  const { created } = appendMessage(input.platformAccountId, diskRecord, altDedupeRemoteJids);
4762
4868
  const ms = Date.now() - t0;
4763
4869
  if (!created) {
4764
- console.error(`${TAG11} noop reason=existing-message messageId=${messageId}`);
4870
+ console.error(`${TAG12} noop reason=existing-message messageId=${messageId}`);
4765
4871
  return { messageId, created: false, senderElementId };
4766
4872
  }
4767
4873
  console.error(
4768
- `${TAG11} write messageId=${messageId} accountId=${input.platformAccountId} cacheKey=${input.cacheKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} attachment=${input.attachmentId ?? "none"} ms=${ms}`
4874
+ `${TAG12} write messageId=${messageId} accountId=${input.platformAccountId} cacheKey=${input.cacheKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} attachment=${input.attachmentId ?? "none"} ms=${ms}`
4769
4875
  );
4770
4876
  return { messageId, created: true, senderElementId };
4771
4877
  } catch (err) {
4772
4878
  const ms = Date.now() - t0;
4773
4879
  const reason = sanitizeReason(err);
4774
4880
  console.error(
4775
- `${TAG11} FAIL accountId=${input.platformAccountId} waname=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
4881
+ `${TAG12} FAIL accountId=${input.platformAccountId} waname=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
4776
4882
  );
4777
4883
  return null;
4778
4884
  } finally {
@@ -4805,7 +4911,7 @@ function sanitizeReason(err) {
4805
4911
  }
4806
4912
 
4807
4913
  // app/lib/whatsapp/ensure-conversation.ts
4808
- var TAG12 = "[whatsapp-persist]";
4914
+ var TAG13 = "[whatsapp-persist]";
4809
4915
  async function ensureWhatsAppConversation(input) {
4810
4916
  const t0 = Date.now();
4811
4917
  try {
@@ -4817,19 +4923,19 @@ async function ensureWhatsAppConversation(input) {
4817
4923
  const ms = Date.now() - t0;
4818
4924
  if (!result.sessionId) {
4819
4925
  console.error(
4820
- `${TAG12} conversation-merged FAIL cacheKey=${input.cacheKey} reason=null-sessionId ms=${ms}`
4926
+ `${TAG13} conversation-merged FAIL cacheKey=${input.cacheKey} reason=null-sessionId ms=${ms}`
4821
4927
  );
4822
4928
  return null;
4823
4929
  }
4824
4930
  console.error(
4825
- `${TAG12} conversation-merged cacheKey=${input.cacheKey} agentType=${input.agentType} channel=whatsapp accountId=${input.platformAccountId} connectionAccountId=${input.connectionAccountId ?? input.platformAccountId} created=${result.created} ms=${ms}`
4931
+ `${TAG13} conversation-merged cacheKey=${input.cacheKey} agentType=${input.agentType} channel=whatsapp accountId=${input.platformAccountId} connectionAccountId=${input.connectionAccountId ?? input.platformAccountId} created=${result.created} ms=${ms}`
4826
4932
  );
4827
4933
  return { sessionId: result.sessionId, created: result.created };
4828
4934
  } catch (err) {
4829
4935
  const ms = Date.now() - t0;
4830
4936
  const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
4831
4937
  console.error(
4832
- `${TAG12} conversation-merged FAIL cacheKey=${input.cacheKey} reason=${reason} ms=${ms}`
4938
+ `${TAG13} conversation-merged FAIL cacheKey=${input.cacheKey} reason=${reason} ms=${ms}`
4833
4939
  );
4834
4940
  return null;
4835
4941
  }
@@ -5391,7 +5497,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
5391
5497
  }
5392
5498
 
5393
5499
  // app/lib/whatsapp/inbound/media.ts
5394
- var TAG13 = "[whatsapp:media]";
5500
+ var TAG14 = "[whatsapp:media]";
5395
5501
  var MEDIA_DIR = "/tmp/maxy-media";
5396
5502
  var DOWNLOAD_TIMEOUT_MS = 45e3;
5397
5503
  var DETACHED_GRACE_MS = 3e5;
@@ -5481,25 +5587,25 @@ async function downloadInboundMediaBuffer(msg, sock, opts) {
5481
5587
  }
5482
5588
  );
5483
5589
  if (!buffer || buffer.length === 0) {
5484
- console.error(`${TAG13} primary download returned empty, trying direct fallback`);
5590
+ console.error(`${TAG14} primary download returned empty, trying direct fallback`);
5485
5591
  const downloadable = getDownloadableContent(content);
5486
5592
  if (downloadable) {
5487
5593
  try {
5488
5594
  const stream2 = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
5489
5595
  buffer = await streamToBuffer(stream2);
5490
5596
  } catch (fallbackErr) {
5491
- console.error(`${TAG13} direct download fallback failed: ${String(fallbackErr)}`);
5597
+ console.error(`${TAG14} direct download fallback failed: ${String(fallbackErr)}`);
5492
5598
  }
5493
5599
  }
5494
5600
  }
5495
5601
  if (!buffer || buffer.length === 0) {
5496
- console.error(`${TAG13} download failed: empty buffer for ${mimetype ?? "unknown"}`);
5602
+ console.error(`${TAG14} download failed: empty buffer for ${mimetype ?? "unknown"}`);
5497
5603
  return void 0;
5498
5604
  }
5499
5605
  if (buffer.length > maxBytes) {
5500
5606
  const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
5501
5607
  const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
5502
- console.error(`${TAG13} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
5608
+ console.error(`${TAG14} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
5503
5609
  return void 0;
5504
5610
  }
5505
5611
  return {
@@ -5513,7 +5619,7 @@ async function downloadInboundMediaBuffer(msg, sock, opts) {
5513
5619
  endMediaDownload();
5514
5620
  return settled;
5515
5621
  } catch (err) {
5516
- console.error(`${TAG13} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
5622
+ console.error(`${TAG14} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
5517
5623
  if (isTimeoutError(err)) {
5518
5624
  const t = setTimeout(endMediaDownload, DETACHED_GRACE_MS);
5519
5625
  t.unref?.();
@@ -5531,7 +5637,7 @@ async function downloadInboundMedia(msg, sock, opts) {
5531
5637
  const filePath = join8(MEDIA_DIR, `${randomUUID4()}.${ext}`);
5532
5638
  await writeFile2(filePath, res.buffer);
5533
5639
  const sizeKB = (res.buffer.length / 1024).toFixed(0);
5534
- console.error(`${TAG13} media downloaded type=${res.mimetype} size=${sizeKB}KB path=${filePath}`);
5640
+ console.error(`${TAG14} media downloaded type=${res.mimetype} size=${sizeKB}KB path=${filePath}`);
5535
5641
  return { path: filePath, mimetype: res.mimetype, size: res.buffer.length };
5536
5642
  }
5537
5643
  async function storeInboundMediaServable(msg, sock, accountId, seed, opts) {
@@ -5540,15 +5646,15 @@ async function storeInboundMediaServable(msg, sock, accountId, seed, opts) {
5540
5646
  if (attachmentExists(accountId, attachmentId)) return attachmentId;
5541
5647
  const res = await downloadInboundMediaBufferCached(msg, sock, opts);
5542
5648
  if (!res) {
5543
- console.error(`${TAG13} servable-store skip reason=no-buffer id=${attachmentId}`);
5649
+ console.error(`${TAG14} servable-store skip reason=no-buffer id=${attachmentId}`);
5544
5650
  return null;
5545
5651
  }
5546
5652
  const filename = res.filename ?? `${attachmentId}.${mimeToExt(res.mimetype)}`;
5547
5653
  await storeMediaBuffer(accountId, attachmentId, filename, res.mimetype, res.buffer);
5548
- console.error(`${TAG13} servable-store ok id=${attachmentId} mime=${res.mimetype} bytes=${res.buffer.length}`);
5654
+ console.error(`${TAG14} servable-store ok id=${attachmentId} mime=${res.mimetype} bytes=${res.buffer.length}`);
5549
5655
  return attachmentId;
5550
5656
  } catch (err) {
5551
- console.error(`${TAG13} servable-store FAIL id=${attachmentId} reason=${String(err).slice(0, 120)}`);
5657
+ console.error(`${TAG14} servable-store FAIL id=${attachmentId} reason=${String(err).slice(0, 120)}`);
5552
5658
  return null;
5553
5659
  }
5554
5660
  }
@@ -5596,7 +5702,7 @@ function createBoundedQueue(limit, opts) {
5596
5702
  }
5597
5703
 
5598
5704
  // app/lib/whatsapp/inbound/debounce.ts
5599
- var TAG14 = "[whatsapp:debounce]";
5705
+ var TAG15 = "[whatsapp:debounce]";
5600
5706
  var STT_TAG = "[whatsapp:stt-await]";
5601
5707
  function createInboundDebouncer(opts) {
5602
5708
  const { debounceMs, buildKey, onFlush, onError } = opts;
@@ -5627,7 +5733,7 @@ function createInboundDebouncer(opts) {
5627
5733
  pending.delete(key);
5628
5734
  const batchSize = batch.entries.length;
5629
5735
  try {
5630
- console.error(`${TAG14} debounce flush key=${key} batchSize=${batchSize}`);
5736
+ console.error(`${TAG15} debounce flush key=${key} batchSize=${batchSize}`);
5631
5737
  const result = onFlush(batch.entries);
5632
5738
  if (result && typeof result.catch === "function") {
5633
5739
  result.catch(onError);
@@ -5707,7 +5813,7 @@ function combineInboundBatch(entries2) {
5707
5813
  }
5708
5814
 
5709
5815
  // app/lib/whatsapp/opening-hours.ts
5710
- var TAG15 = "[whatsapp:hours]";
5816
+ var TAG16 = "[whatsapp:hours]";
5711
5817
  async function isBusinessOpen(accountId) {
5712
5818
  try {
5713
5819
  const timezone = await resolveTimezone(accountId);
@@ -5725,7 +5831,7 @@ async function isBusinessOpen(accountId) {
5725
5831
  { accountId, dayOfWeek, previousDayOfWeek }
5726
5832
  );
5727
5833
  if (result.records.length === 0) {
5728
- console.error(`${TAG15} [${accountId}] business hours check: no opening hours configured, treating as open`);
5834
+ console.error(`${TAG16} [${accountId}] business hours check: no opening hours configured, treating as open`);
5729
5835
  return { open: true, reason: "no opening hours configured" };
5730
5836
  }
5731
5837
  const specs = result.records.filter((r) => r.get("opens") != null && r.get("closes") != null).map((r) => ({
@@ -5734,7 +5840,7 @@ async function isBusinessOpen(accountId) {
5734
5840
  closes: String(r.get("closes")).trim()
5735
5841
  }));
5736
5842
  if (specs.length === 0) {
5737
- console.error(`${TAG15} [${accountId}] business hours check: no opening hours configured, treating as open`);
5843
+ console.error(`${TAG16} [${accountId}] business hours check: no opening hours configured, treating as open`);
5738
5844
  return { open: true, reason: "no opening hours configured" };
5739
5845
  }
5740
5846
  for (const spec of specs) {
@@ -5744,7 +5850,7 @@ async function isBusinessOpen(accountId) {
5744
5850
  if (spec.opens > spec.closes && currentTime < spec.closes) {
5745
5851
  const hoursStr = `${spec.opens}-${spec.closes} (${spec.day})`;
5746
5852
  console.error(
5747
- `${TAG15} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
5853
+ `${TAG16} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
5748
5854
  );
5749
5855
  return {
5750
5856
  open: true,
@@ -5757,7 +5863,7 @@ async function isBusinessOpen(accountId) {
5757
5863
  } else if (isTimeInRange(currentTime, spec.opens, spec.closes)) {
5758
5864
  const hoursStr = `${spec.opens}-${spec.closes}`;
5759
5865
  console.error(
5760
- `${TAG15} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
5866
+ `${TAG16} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
5761
5867
  );
5762
5868
  return {
5763
5869
  open: true,
@@ -5771,7 +5877,7 @@ async function isBusinessOpen(accountId) {
5771
5877
  const todaySpecs = specs.filter((s) => s.day === dayOfWeek);
5772
5878
  const allHours = todaySpecs.map((s) => `${s.opens}-${s.closes}`).join(", ") || "none today";
5773
5879
  console.error(
5774
- `${TAG15} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
5880
+ `${TAG16} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
5775
5881
  );
5776
5882
  return {
5777
5883
  open: false,
@@ -5785,7 +5891,7 @@ async function isBusinessOpen(accountId) {
5785
5891
  }
5786
5892
  } catch (err) {
5787
5893
  console.error(
5788
- `${TAG15} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
5894
+ `${TAG16} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
5789
5895
  );
5790
5896
  return { open: true, reason: "hours check failed (treating as open)" };
5791
5897
  }
@@ -5831,7 +5937,7 @@ import { execFile } from "child_process";
5831
5937
  import { unlink, stat } from "fs/promises";
5832
5938
  import { promisify } from "util";
5833
5939
  var execFileAsync = promisify(execFile);
5834
- var TAG16 = "[stt]";
5940
+ var TAG17 = "[stt]";
5835
5941
  var WHISPER_BINARY = process.env.WHISPER_BINARY ?? "/opt/whisper.cpp/build/bin/whisper-cli";
5836
5942
  var WHISPER_MODEL = process.env.WHISPER_MODEL ?? "/opt/whisper.cpp/models/ggml-base.bin";
5837
5943
  var WHISPER_TIMEOUT_MS = 20 * 60 * 1e3;
@@ -5850,11 +5956,11 @@ async function transcribe(audioPath, mimetype) {
5850
5956
  const s = await stat(audioPath);
5851
5957
  audioBytes = s.size;
5852
5958
  } catch {
5853
- console.error(`${TAG16} failed: file not readable path=${audioPath}`);
5959
+ console.error(`${TAG17} failed: file not readable path=${audioPath}`);
5854
5960
  return void 0;
5855
5961
  }
5856
5962
  console.error(
5857
- `${TAG16} start provider=whisper-local audio_bytes=${audioBytes} mimetype=${mimetype} path=${audioPath}`
5963
+ `${TAG17} start provider=whisper-local audio_bytes=${audioBytes} mimetype=${mimetype} path=${audioPath}`
5858
5964
  );
5859
5965
  const wavPath = audioPath.replace(/\.[^.]+$/, "") + ".wav";
5860
5966
  try {
@@ -5873,7 +5979,7 @@ async function transcribe(audioPath, mimetype) {
5873
5979
  ], { timeout: 3e4 });
5874
5980
  } catch (err) {
5875
5981
  const reason = err instanceof Error ? err.message : String(err);
5876
- console.error(`${TAG16} failed: ffmpeg conversion error=${reason}`);
5982
+ console.error(`${TAG17} failed: ffmpeg conversion error=${reason}`);
5877
5983
  return void 0;
5878
5984
  }
5879
5985
  try {
@@ -5889,20 +5995,20 @@ async function transcribe(audioPath, mimetype) {
5889
5995
  const durationMs = Date.now() - startMs;
5890
5996
  const { text, count: stripped } = stripSpecialTokens(stdout.trim());
5891
5997
  if (!text) {
5892
- console.error(`${TAG16} failed: whisper returned empty output duration_ms=${durationMs}`);
5998
+ console.error(`${TAG17} failed: whisper returned empty output duration_ms=${durationMs}`);
5893
5999
  return void 0;
5894
6000
  }
5895
6001
  const langMatch = stderr.match(/auto-detected language:\s*(\w+)/);
5896
6002
  const language = langMatch?.[1] ?? "unknown";
5897
6003
  const words = text.split(/\s+/).filter(Boolean).length;
5898
6004
  console.error(
5899
- `${TAG16} done provider=whisper-local duration_ms=${durationMs} words=${words} stripped=${stripped} lang=${language}`
6005
+ `${TAG17} done provider=whisper-local duration_ms=${durationMs} words=${words} stripped=${stripped} lang=${language}`
5900
6006
  );
5901
6007
  return { text, language, durationMs };
5902
6008
  } catch (err) {
5903
6009
  const durationMs = Date.now() - startMs;
5904
6010
  const reason = err instanceof Error ? err.message : String(err);
5905
- console.error(`${TAG16} failed provider=whisper-local duration_ms=${durationMs} error=${reason}`);
6011
+ console.error(`${TAG17} failed provider=whisper-local duration_ms=${durationMs} error=${reason}`);
5906
6012
  return void 0;
5907
6013
  } finally {
5908
6014
  unlink(wavPath).catch(() => {
@@ -5921,7 +6027,7 @@ var WaReplyError = class extends Error {
5921
6027
  };
5922
6028
 
5923
6029
  // app/lib/whatsapp/manager.ts
5924
- var TAG17 = "[whatsapp:manager]";
6030
+ var TAG18 = "[whatsapp:manager]";
5925
6031
  var MAX_RECONNECT_ATTEMPTS = 10;
5926
6032
  var MESSAGE_STORE_MAX = 500;
5927
6033
  var APPEND_MEDIA_CONCURRENCY = 3;
@@ -5929,7 +6035,7 @@ var APPEND_MEDIA_MAX_PENDING = 24;
5929
6035
  var appendMediaQueue = createBoundedQueue(APPEND_MEDIA_CONCURRENCY, {
5930
6036
  maxPending: APPEND_MEDIA_MAX_PENDING
5931
6037
  });
5932
- var connections = /* @__PURE__ */ new Map();
6038
+ var connections2 = /* @__PURE__ */ new Map();
5933
6039
  var configDir = null;
5934
6040
  var whatsAppConfig = {};
5935
6041
  var onInboundMessage = null;
@@ -5958,7 +6064,7 @@ function storeMessage(storeKey, entry) {
5958
6064
  if (entries2.length > MESSAGE_STORE_MAX) {
5959
6065
  const trimmed = entries2.length - MESSAGE_STORE_MAX;
5960
6066
  entries2.splice(0, trimmed);
5961
- console.error(`${TAG17} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
6067
+ console.error(`${TAG18} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
5962
6068
  }
5963
6069
  }
5964
6070
  function deriveCacheKey(input) {
@@ -6001,7 +6107,7 @@ function buildSelfChatDispatch(input) {
6001
6107
  }
6002
6108
  async function init(opts) {
6003
6109
  if (initialized) {
6004
- console.error(`${TAG17} already initialized`);
6110
+ console.error(`${TAG18} already initialized`);
6005
6111
  return;
6006
6112
  }
6007
6113
  configDir = opts.configDir;
@@ -6009,20 +6115,20 @@ async function init(opts) {
6009
6115
  loadConfig(opts.accountConfig);
6010
6116
  const accountIds = listCredentialAccountIds(configDir);
6011
6117
  if (accountIds.length === 0) {
6012
- console.error(`${TAG17} init: no stored WhatsApp credentials found`);
6118
+ console.error(`${TAG18} init: no stored WhatsApp credentials found`);
6013
6119
  initialized = true;
6014
6120
  return;
6015
6121
  }
6016
- console.error(`${TAG17} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
6122
+ console.error(`${TAG18} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
6017
6123
  initialized = true;
6018
6124
  for (const accountId of accountIds) {
6019
6125
  const accountCfg = whatsAppConfig.accounts?.[accountId];
6020
6126
  if (accountCfg?.enabled === false) {
6021
- console.error(`${TAG17} skipping disabled account=${accountId}`);
6127
+ console.error(`${TAG18} skipping disabled account=${accountId}`);
6022
6128
  continue;
6023
6129
  }
6024
6130
  startConnection(accountId).catch((err) => {
6025
- console.error(`${TAG17} failed to auto-start account=${accountId}: ${formatError(err)}`);
6131
+ console.error(`${TAG18} failed to auto-start account=${accountId}: ${formatError(err)}`);
6026
6132
  });
6027
6133
  }
6028
6134
  }
@@ -6031,7 +6137,7 @@ async function startConnection(accountId) {
6031
6137
  const authDir = resolveAuthDir(configDir, accountId);
6032
6138
  const hasAuth = await authExists(authDir);
6033
6139
  if (!hasAuth) {
6034
- console.error(`${TAG17} no credentials for account=${accountId}`);
6140
+ console.error(`${TAG18} no credentials for account=${accountId}`);
6035
6141
  return;
6036
6142
  }
6037
6143
  let platformAccountId;
@@ -6063,11 +6169,11 @@ async function startConnection(accountId) {
6063
6169
  debouncer: null,
6064
6170
  lidMapping: null
6065
6171
  };
6066
- connections.set(accountId, conn);
6172
+ connections2.set(accountId, conn);
6067
6173
  await connectWithReconnect(conn);
6068
6174
  }
6069
6175
  async function stopConnection(accountId) {
6070
- const conn = connections.get(accountId);
6176
+ const conn = connections2.get(accountId);
6071
6177
  if (!conn) return;
6072
6178
  conn.abortController.abort();
6073
6179
  if (conn.debouncer) {
@@ -6082,14 +6188,14 @@ async function stopConnection(accountId) {
6082
6188
  conn.sock.ev.removeAllListeners("creds.update");
6083
6189
  conn.sock.ws?.close?.();
6084
6190
  } catch (err) {
6085
- console.warn(`${TAG17} socket cleanup error during stop account=${accountId}: ${String(err)}`);
6191
+ console.warn(`${TAG18} socket cleanup error during stop account=${accountId}: ${String(err)}`);
6086
6192
  }
6087
6193
  }
6088
- connections.delete(accountId);
6089
- console.error(`${TAG17} stopped account=${accountId}`);
6194
+ connections2.delete(accountId);
6195
+ console.error(`${TAG18} stopped account=${accountId}`);
6090
6196
  }
6091
6197
  function getStatus() {
6092
- return Array.from(connections.values()).map((conn) => ({
6198
+ return Array.from(connections2.values()).map((conn) => ({
6093
6199
  accountId: conn.accountId,
6094
6200
  accountName: conn.accountName,
6095
6201
  connected: conn.connected,
@@ -6113,14 +6219,14 @@ function selectConnection(conns, accountId) {
6113
6219
  return { ok: true, sock: conn.sock, accountId: conn.accountId };
6114
6220
  }
6115
6221
  function resolveSocket(accountId) {
6116
- return selectConnection(Array.from(connections.values()), accountId);
6222
+ return selectConnection(Array.from(connections2.values()), accountId);
6117
6223
  }
6118
6224
  function selectStoreAccountKey(conns, accountId) {
6119
6225
  const conn = findConnectionByKey(conns, accountId);
6120
6226
  return conn ? conn.platformAccountId : accountId;
6121
6227
  }
6122
6228
  function resolveReadStoreKey(accountId) {
6123
- return selectStoreAccountKey(Array.from(connections.values()), accountId);
6229
+ return selectStoreAccountKey(Array.from(connections2.values()), accountId);
6124
6230
  }
6125
6231
  function resolveInboundPersistAccount(args) {
6126
6232
  const result = args.accessResult;
@@ -6130,7 +6236,7 @@ function resolveInboundPersistAccount(args) {
6130
6236
  return args.connPlatformAccountId;
6131
6237
  }
6132
6238
  function resolveConversationPersistAccount(sendAccountId, counterpartyPhone) {
6133
- const conn = findConnectionByKey(Array.from(connections.values()), sendAccountId);
6239
+ const conn = findConnectionByKey(Array.from(connections2.values()), sendAccountId);
6134
6240
  if (!conn) return sendAccountId;
6135
6241
  const access = checkDmAccess({
6136
6242
  senderPhone: counterpartyPhone,
@@ -6146,7 +6252,7 @@ function resolveConversationPersistAccount(sendAccountId, counterpartyPhone) {
6146
6252
  });
6147
6253
  }
6148
6254
  function listConnectionPlatformAccountIds() {
6149
- return [...connections.values()].map((conn) => conn.platformAccountId);
6255
+ return [...connections2.values()].map((conn) => conn.platformAccountId);
6150
6256
  }
6151
6257
  async function registerLoginSocket(accountId, sock, authDir) {
6152
6258
  if (!configDir) throw new Error("WhatsApp manager not initialized");
@@ -6181,13 +6287,13 @@ async function registerLoginSocket(accountId, sock, authDir) {
6181
6287
  lidMapping: null
6182
6288
  };
6183
6289
  applySelfIdentity(conn, sock, "register");
6184
- connections.set(accountId, conn);
6290
+ connections2.set(accountId, conn);
6185
6291
  monitorInbound(conn);
6186
6292
  try {
6187
6293
  await sock.sendPresenceUpdate("available");
6188
- console.error(`${TAG17} presence set to available account=${accountId}`);
6294
+ console.error(`${TAG18} presence set to available account=${accountId}`);
6189
6295
  } catch (err) {
6190
- console.error(`${TAG17} presence update failed account=${accountId}: ${String(err)}`);
6296
+ console.error(`${TAG18} presence update failed account=${accountId}: ${String(err)}`);
6191
6297
  }
6192
6298
  await runInitQueries(sock, {
6193
6299
  accountId,
@@ -6198,7 +6304,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
6198
6304
  });
6199
6305
  watchForDisconnect(conn);
6200
6306
  attachSelfIdRefreshOnCredsUpdate(conn);
6201
- console.error(`${TAG17} registered login socket for account=${accountId} phone=${conn.selfPhone ?? "unknown"}`);
6307
+ console.error(`${TAG18} registered login socket for account=${accountId} phone=${conn.selfPhone ?? "unknown"}`);
6202
6308
  }
6203
6309
  function attachSelfIdRefreshOnCredsUpdate(conn) {
6204
6310
  if (!conn.sock) return;
@@ -6240,10 +6346,10 @@ function listStoreAccountKeys() {
6240
6346
  }
6241
6347
  async function shutdown() {
6242
6348
  await drainCredsSaveQueue();
6243
- const ids = Array.from(connections.keys());
6349
+ const ids = Array.from(connections2.keys());
6244
6350
  await Promise.all(ids.map((id) => stopConnection(id)));
6245
6351
  initialized = false;
6246
- console.error(`${TAG17} shutdown complete`);
6352
+ console.error(`${TAG18} shutdown complete`);
6247
6353
  }
6248
6354
  function loadConfig(accountConfig) {
6249
6355
  try {
@@ -6254,19 +6360,19 @@ function loadConfig(accountConfig) {
6254
6360
  if (result.ok) {
6255
6361
  whatsAppConfig = result.data;
6256
6362
  if (result.droppedKeys.length > 0) {
6257
- console.error(`${TAG17} config: dropped unknown keys=[${result.droppedKeys.join(",")}] preserved known config`);
6363
+ console.error(`${TAG18} config: dropped unknown keys=[${result.droppedKeys.join(",")}] preserved known config`);
6258
6364
  }
6259
6365
  } else {
6260
- console.error(`${TAG17} config validation failed: ${result.error.message}`);
6366
+ console.error(`${TAG18} config validation failed: ${result.error.message}`);
6261
6367
  whatsAppConfig = {};
6262
6368
  }
6263
6369
  const diskAdmin = Array.isArray(wa.adminPhones) ? wa.adminPhones : [];
6264
6370
  if (diskAdmin.length > 0 && (whatsAppConfig.adminPhones?.length ?? 0) === 0) {
6265
- console.error(`${TAG17} WARN adminPhones present on disk but empty after load`);
6371
+ console.error(`${TAG18} WARN adminPhones present on disk but empty after load`);
6266
6372
  }
6267
6373
  }
6268
6374
  } catch (err) {
6269
- console.error(`${TAG17} config load error: ${String(err)}`);
6375
+ console.error(`${TAG18} config load error: ${String(err)}`);
6270
6376
  whatsAppConfig = {};
6271
6377
  }
6272
6378
  }
@@ -6277,7 +6383,7 @@ async function connectWithReconnect(conn) {
6277
6383
  let cycleError = null;
6278
6384
  let connectedAt;
6279
6385
  try {
6280
- console.error(`${TAG17} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
6386
+ console.error(`${TAG18} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
6281
6387
  if (conn.debouncer) {
6282
6388
  await conn.debouncer.destroy();
6283
6389
  conn.debouncer = null;
@@ -6290,7 +6396,7 @@ async function connectWithReconnect(conn) {
6290
6396
  conn.sock = sock;
6291
6397
  applySelfIdentity(conn, sock, "pre-listener");
6292
6398
  monitorInbound(conn);
6293
- console.error(`${TAG17} socket created account=${conn.accountId} \u2014 waiting for connection`);
6399
+ console.error(`${TAG18} socket created account=${conn.accountId} \u2014 waiting for connection`);
6294
6400
  await waitForConnection(sock);
6295
6401
  connectedAt = Date.now();
6296
6402
  conn.connected = true;
@@ -6298,12 +6404,12 @@ async function connectWithReconnect(conn) {
6298
6404
  conn.lastError = void 0;
6299
6405
  conn.terminalReason = void 0;
6300
6406
  applySelfIdentity(conn, sock, "post-connect");
6301
- console.error(`${TAG17} connected account=${conn.accountId} phone=${conn.selfPhone ?? "unknown"}`);
6407
+ console.error(`${TAG18} connected account=${conn.accountId} phone=${conn.selfPhone ?? "unknown"}`);
6302
6408
  try {
6303
6409
  await sock.sendPresenceUpdate("available");
6304
- console.error(`${TAG17} presence set to available account=${conn.accountId}`);
6410
+ console.error(`${TAG18} presence set to available account=${conn.accountId}`);
6305
6411
  } catch (err) {
6306
- console.error(`${TAG17} presence update failed account=${conn.accountId}: ${String(err)}`);
6412
+ console.error(`${TAG18} presence update failed account=${conn.accountId}: ${String(err)}`);
6307
6413
  }
6308
6414
  await runInitQueries(sock, {
6309
6415
  accountId: conn.accountId,
@@ -6326,10 +6432,10 @@ async function connectWithReconnect(conn) {
6326
6432
  }
6327
6433
  const classification = classifyDisconnect(err);
6328
6434
  conn.lastError = classification.message;
6329
- console.error(`${TAG17} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
6435
+ console.error(`${TAG18} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
6330
6436
  if (!classification.shouldRetry) {
6331
6437
  conn.terminalReason = classification.message;
6332
- console.error(`${TAG17} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
6438
+ console.error(`${TAG18} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
6333
6439
  return;
6334
6440
  }
6335
6441
  }
@@ -6342,7 +6448,7 @@ async function connectWithReconnect(conn) {
6342
6448
  if (decision.action === "abort") {
6343
6449
  const stuckReason = `GIVING UP account=${conn.accountId} attempts=${decision.finalAttempts}/${maxAttempts} uptimeMsLast=${uptimeMs} stableThresholdMs=${STABLE_UPTIME_MS} lastError=${conn.lastError ?? "(none)"}`;
6344
6450
  console.error(
6345
- `${TAG17} ${stuckReason} \u2014 re-pair via QR or restart required; WhatsApp will not reconnect automatically`
6451
+ `${TAG18} ${stuckReason} \u2014 re-pair via QR or restart required; WhatsApp will not reconnect automatically`
6346
6452
  );
6347
6453
  conn.sessionStuckReason = stuckReason;
6348
6454
  conn.lastError = stuckReason;
@@ -6351,17 +6457,17 @@ async function connectWithReconnect(conn) {
6351
6457
  conn.reconnectAttempts = decision.nextAttempts;
6352
6458
  if (decision.reason === "short-lived") {
6353
6459
  console.error(
6354
- `${TAG17} short-lived session account=${conn.accountId} uptimeMs=${uptimeMs} attempt=${decision.nextAttempts}/${maxAttempts} lastError=${conn.lastError ?? "(clean disconnect)"}`
6460
+ `${TAG18} short-lived session account=${conn.accountId} uptimeMs=${uptimeMs} attempt=${decision.nextAttempts}/${maxAttempts} lastError=${conn.lastError ?? "(clean disconnect)"}`
6355
6461
  );
6356
6462
  } else {
6357
6463
  console.error(
6358
- `${TAG17} session stable account=${conn.accountId} uptimeMs=${uptimeMs} \u2014 reconnect counter reset`
6464
+ `${TAG18} session stable account=${conn.accountId} uptimeMs=${uptimeMs} \u2014 reconnect counter reset`
6359
6465
  );
6360
6466
  }
6361
6467
  if (decision.reason === "short-lived" || cycleError) {
6362
6468
  const delay = computeBackoff(Math.max(1, decision.nextAttempts));
6363
6469
  console.error(
6364
- `${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
6470
+ `${TAG18} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
6365
6471
  );
6366
6472
  await new Promise((resolve46) => {
6367
6473
  const timer = setTimeout(resolve46, delay);
@@ -6394,12 +6500,12 @@ function watchForDisconnect(conn) {
6394
6500
  if (!conn.sock) return;
6395
6501
  conn.sock.ev.on("connection.update", (update) => {
6396
6502
  if (update.connection === "close") {
6397
- if (connections.get(conn.accountId) !== conn) return;
6398
- console.error(`${TAG17} socket disconnected for account=${conn.accountId}`);
6503
+ if (connections2.get(conn.accountId) !== conn) return;
6504
+ console.error(`${TAG18} socket disconnected for account=${conn.accountId}`);
6399
6505
  conn.connected = false;
6400
6506
  conn.sock = null;
6401
6507
  connectWithReconnect(conn).catch((err) => {
6402
- console.error(`${TAG17} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
6508
+ console.error(`${TAG18} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
6403
6509
  });
6404
6510
  }
6405
6511
  });
@@ -6425,7 +6531,7 @@ function monitorInbound(conn) {
6425
6531
  if (!conn.sock || !onInboundMessage) return;
6426
6532
  const sock = conn.sock;
6427
6533
  const debounceMs = whatsAppConfig.accounts?.[conn.accountId]?.debounceMs ?? whatsAppConfig.debounceMs ?? 0;
6428
- console.error(`${TAG17} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
6534
+ console.error(`${TAG18} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
6429
6535
  conn.debouncer = createInboundDebouncer({
6430
6536
  debounceMs,
6431
6537
  buildKey: (payload) => {
@@ -6435,12 +6541,12 @@ function monitorInbound(conn) {
6435
6541
  onFlush: (entries2) => {
6436
6542
  if (!onInboundMessage) return;
6437
6543
  if (entries2.length > 1) {
6438
- console.error(`${TAG17} debounce: combining ${entries2.length} messages account=${conn.accountId} from=${entries2[0].senderPhone}`);
6544
+ console.error(`${TAG18} debounce: combining ${entries2.length} messages account=${conn.accountId} from=${entries2[0].senderPhone}`);
6439
6545
  }
6440
6546
  dispatchInboundPayload(conn, combineInboundBatch(entries2));
6441
6547
  },
6442
6548
  onError: (err) => {
6443
- console.error(`${TAG17} debounce flush error account=${conn.accountId}: ${String(err)}`);
6549
+ console.error(`${TAG18} debounce flush error account=${conn.accountId}: ${String(err)}`);
6444
6550
  }
6445
6551
  });
6446
6552
  sock.ev.on("messages.upsert", async (upsert) => {
@@ -6494,7 +6600,7 @@ function monitorInbound(conn) {
6494
6600
  }
6495
6601
  const entries2 = messageStore.get(storeKey);
6496
6602
  console.error(
6497
- `${TAG17} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries2?.length ?? 0}/${MESSAGE_STORE_MAX}) storeAccount=${persistAccountId} socketOwner=${conn.platformAccountId}`
6603
+ `${TAG18} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries2?.length ?? 0}/${MESSAGE_STORE_MAX}) storeAccount=${persistAccountId} socketOwner=${conn.platformAccountId}`
6498
6604
  );
6499
6605
  recordActivity({
6500
6606
  accountId: conn.accountId,
@@ -6548,7 +6654,7 @@ function monitorInbound(conn) {
6548
6654
  const wantsServableMedia = mediaServable && !!conn.sock && (!fromMe || !alreadyRecorded);
6549
6655
  if (fromMe && mediaServable && !!conn.sock) {
6550
6656
  console.error(
6551
- `${TAG17} fromMe-media-echo msgKey=${msg.key.id} decision=${alreadyRecorded ? "skip" : "store"} reason=${alreadyRecorded ? "already-recorded" : "no-prior-record"}`
6657
+ `${TAG18} fromMe-media-echo msgKey=${msg.key.id} decision=${alreadyRecorded ? "skip" : "store"} reason=${alreadyRecorded ? "already-recorded" : "no-prior-record"}`
6552
6658
  );
6553
6659
  }
6554
6660
  const mediaSeed = `whatsapp-live:${conn.accountId}:${canonicalRemoteJid}:${msg.key.id}`;
@@ -6600,7 +6706,7 @@ function monitorInbound(conn) {
6600
6706
  receiptDeferredToWorker = true;
6601
6707
  if (!accepted) {
6602
6708
  console.error(
6603
- `${TAG17} append-media overflow account=${conn.platformAccountId} msgKey=${msgKeyId ?? "?"} \u2014 pending cap ${APPEND_MEDIA_MAX_PENDING} reached, text-fallback persist, inline media shed`
6709
+ `${TAG18} append-media overflow account=${conn.platformAccountId} msgKey=${msgKeyId ?? "?"} \u2014 pending cap ${APPEND_MEDIA_MAX_PENDING} reached, text-fallback persist, inline media shed`
6604
6710
  );
6605
6711
  const persisted = await persistWhatsAppMessage({
6606
6712
  ...basePersist,
@@ -6676,13 +6782,13 @@ function monitorInbound(conn) {
6676
6782
  const skippedSenderJid = isGroupJid(remoteJid) ? msg.key.participant ?? remoteJid : remoteJid;
6677
6783
  const skippedSenderPhone = await resolveJidToE164(skippedSenderJid, conn.lidMapping) ?? skippedSenderJid;
6678
6784
  console.error(
6679
- `${TAG17} append-type message ${msg.key.id ?? "?"} dispatch skipped from=${skippedSenderPhone}${msg.pushName ? ` name=${msg.pushName}` : ""} account=${conn.accountId} (persistence not confirmed here)`
6785
+ `${TAG18} append-type message ${msg.key.id ?? "?"} dispatch skipped from=${skippedSenderPhone}${msg.pushName ? ` name=${msg.pushName}` : ""} account=${conn.accountId} (persistence not confirmed here)`
6680
6786
  );
6681
6787
  continue;
6682
6788
  }
6683
6789
  await handleInboundMessage(conn, msg);
6684
6790
  } catch (err) {
6685
- console.error(`${TAG17} inbound handler error account=${conn.accountId}: ${String(err)}`);
6791
+ console.error(`${TAG18} inbound handler error account=${conn.accountId}: ${String(err)}`);
6686
6792
  }
6687
6793
  }
6688
6794
  });
@@ -6738,31 +6844,31 @@ async function handleInboundMessage(conn, msg) {
6738
6844
  const remoteJid = msg.key.remoteJid;
6739
6845
  if (!remoteJid) return;
6740
6846
  if (remoteJid === "status@broadcast") {
6741
- console.error(`${TAG17} drop: status broadcast account=${conn.accountId}`);
6847
+ console.error(`${TAG18} drop: status broadcast account=${conn.accountId}`);
6742
6848
  return;
6743
6849
  }
6744
6850
  if (!msg.message) {
6745
- console.error(`${TAG17} drop: empty message account=${conn.accountId} from=${remoteJid}`);
6851
+ console.error(`${TAG18} drop: empty message account=${conn.accountId} from=${remoteJid}`);
6746
6852
  return;
6747
6853
  }
6748
6854
  const dedupKey = `${conn.accountId}:${remoteJid}:${msg.key.id}`;
6749
6855
  if (isDuplicateInbound(dedupKey)) {
6750
- console.error(`${TAG17} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
6856
+ console.error(`${TAG18} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
6751
6857
  return;
6752
6858
  }
6753
6859
  if (msg.key.fromMe) {
6754
6860
  if (msg.key.id && isAgentSentMessage(msg.key.id)) {
6755
- console.error(`${TAG17} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
6861
+ console.error(`${TAG18} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
6756
6862
  return;
6757
6863
  }
6758
6864
  const extracted2 = extractMessage(msg);
6759
6865
  if (!extracted2.text) {
6760
- console.error(`${TAG17} owner reply skipped \u2014 no text content account=${conn.accountId}`);
6866
+ console.error(`${TAG18} owner reply skipped \u2014 no text content account=${conn.accountId}`);
6761
6867
  return;
6762
6868
  }
6763
6869
  const isGroup2 = isGroupJid(remoteJid);
6764
6870
  const senderPhone2 = conn.selfPhone ?? "owner";
6765
- console.error(`${TAG17} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
6871
+ console.error(`${TAG18} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
6766
6872
  const reply2 = async (text) => {
6767
6873
  const currentSock = conn.sock;
6768
6874
  if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
@@ -6796,7 +6902,7 @@ async function handleInboundMessage(conn, msg) {
6796
6902
  }
6797
6903
  const extracted = extractMessage(msg);
6798
6904
  if (!extracted.text && !extracted.mediaType) {
6799
- console.error(`${TAG17} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
6905
+ console.error(`${TAG18} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
6800
6906
  return;
6801
6907
  }
6802
6908
  const isGroup = isGroupJid(remoteJid);
@@ -6820,7 +6926,7 @@ async function handleInboundMessage(conn, msg) {
6820
6926
  });
6821
6927
  }
6822
6928
  console.error(
6823
- `${TAG17} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
6929
+ `${TAG18} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
6824
6930
  );
6825
6931
  if (!accessResult.allowed && accessResult.reason === "account-manager-unresolved") {
6826
6932
  console.error(
@@ -6851,7 +6957,7 @@ async function handleInboundMessage(conn, msg) {
6851
6957
  maxBytes: maxMb * 1024 * 1024
6852
6958
  });
6853
6959
  if (!mediaResult) {
6854
- console.error(`${TAG17} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
6960
+ console.error(`${TAG18} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
6855
6961
  }
6856
6962
  }
6857
6963
  if (extracted.mediaType === "audio" && mediaResult?.path) {
@@ -6873,7 +6979,7 @@ async function handleInboundMessage(conn, msg) {
6873
6979
  }
6874
6980
  const reply = async (text) => {
6875
6981
  if (isGroupJid(remoteJid)) {
6876
- console.error(`${TAG17} op=group-reply-blocked jid=${remoteJid}`);
6982
+ console.error(`${TAG18} op=group-reply-blocked jid=${remoteJid}`);
6877
6983
  throw new WaReplyError("group reply blocked \u2014 observe-only", false);
6878
6984
  }
6879
6985
  const currentSock = conn.sock;
@@ -6920,15 +7026,15 @@ async function handleInboundMessage(conn, msg) {
6920
7026
  if (accessResult.agentType === "public") {
6921
7027
  const hoursResult = await isBusinessOpen(conn.accountId);
6922
7028
  if (!hoursResult.open) {
6923
- console.error(`${TAG17} [${conn.accountId}] dispatch skipped: business closed`);
7029
+ console.error(`${TAG18} [${conn.accountId}] dispatch skipped: business closed`);
6924
7030
  const afterHoursMessage = whatsAppConfig.accounts?.[conn.accountId]?.afterHoursMessage ?? whatsAppConfig.afterHoursMessage;
6925
7031
  if (afterHoursMessage) {
6926
7032
  try {
6927
7033
  await reply(afterHoursMessage);
6928
- console.error(`${TAG17} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
7034
+ console.error(`${TAG18} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
6929
7035
  } catch (err) {
6930
7036
  console.error(
6931
- `${TAG17} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
7037
+ `${TAG18} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
6932
7038
  );
6933
7039
  }
6934
7040
  }
@@ -7373,13 +7479,13 @@ function audioExtension(mimeType) {
7373
7479
  }
7374
7480
 
7375
7481
  // app/lib/stt/voice-note.ts
7376
- var TAG18 = "[voice]";
7482
+ var TAG19 = "[voice]";
7377
7483
  async function transcribeVoiceNote(file, source) {
7378
7484
  const startMs = Date.now();
7379
7485
  const bytes = file.size;
7380
7486
  const mimeType = file.type;
7381
7487
  console.error(
7382
- `${TAG18} recording send source=${source} duration_ms=unknown bytes=${bytes} format=${mimeType}`
7488
+ `${TAG19} recording send source=${source} duration_ms=unknown bytes=${bytes} format=${mimeType}`
7383
7489
  );
7384
7490
  let tempDir;
7385
7491
  let tempPath;
@@ -7391,7 +7497,7 @@ async function transcribeVoiceNote(file, source) {
7391
7497
  await writeFile3(tempPath, buffer);
7392
7498
  } catch (err) {
7393
7499
  const reason = err instanceof Error ? err.message : String(err);
7394
- console.error(`${TAG18} failed source=${source} error=temp-file-write: ${reason}`);
7500
+ console.error(`${TAG19} failed source=${source} error=temp-file-write: ${reason}`);
7395
7501
  return { ok: false, error: "Could not process voice note" };
7396
7502
  }
7397
7503
  try {
@@ -7399,7 +7505,7 @@ async function transcribeVoiceNote(file, source) {
7399
7505
  if (!sttResult) {
7400
7506
  const elapsed2 = Date.now() - startMs;
7401
7507
  console.error(
7402
- `${TAG18} failed source=${source} error=transcription-failed duration_ms=${elapsed2}`
7508
+ `${TAG19} failed source=${source} error=transcription-failed duration_ms=${elapsed2}`
7403
7509
  );
7404
7510
  return { ok: false, error: "Could not transcribe voice note. Please try again or type your message." };
7405
7511
  }
@@ -7407,7 +7513,7 @@ async function transcribeVoiceNote(file, source) {
7407
7513
  const elapsed = Date.now() - startMs;
7408
7514
  const words = rawText.split(/\s+/).filter(Boolean).length;
7409
7515
  console.error(
7410
- `${TAG18} transcribed source=${source} duration_ms=${elapsed} stt_ms=${sttResult.durationMs} words=${words}`
7516
+ `${TAG19} transcribed source=${source} duration_ms=${elapsed} stt_ms=${sttResult.durationMs} words=${words}`
7411
7517
  );
7412
7518
  return {
7413
7519
  ok: true,
@@ -7417,7 +7523,7 @@ async function transcribeVoiceNote(file, source) {
7417
7523
  const elapsed = Date.now() - startMs;
7418
7524
  const reason = err instanceof Error ? err.message : String(err);
7419
7525
  console.error(
7420
- `${TAG18} failed source=${source} error=${reason} duration_ms=${elapsed}`
7526
+ `${TAG19} failed source=${source} error=${reason} duration_ms=${elapsed}`
7421
7527
  );
7422
7528
  return { ok: false, error: "Voice note transcription failed. Please try again or type your message." };
7423
7529
  } finally {
@@ -7464,7 +7570,7 @@ function composePublicSessionTitle(input) {
7464
7570
  }
7465
7571
 
7466
7572
  // app/lib/webchat/persist-customer-inbound.ts
7467
- var TAG19 = "[channel-house]";
7573
+ var TAG20 = "[channel-house]";
7468
7574
  async function persistCustomerWebchatInbound(input) {
7469
7575
  if (!input.text) return null;
7470
7576
  try {
@@ -7480,7 +7586,7 @@ async function persistCustomerWebchatInbound(input) {
7480
7586
  );
7481
7587
  if (!conv.sessionId) {
7482
7588
  console.error(
7483
- `${TAG19} op=persist-skip reason=conversation-merge-failed accountId=${input.houseAccountId} key=${input.sessionKey}`
7589
+ `${TAG20} op=persist-skip reason=conversation-merge-failed accountId=${input.houseAccountId} key=${input.sessionKey}`
7484
7590
  );
7485
7591
  return null;
7486
7592
  }
@@ -7492,17 +7598,17 @@ async function persistCustomerWebchatInbound(input) {
7492
7598
  );
7493
7599
  if (!messageId) {
7494
7600
  console.error(
7495
- `${TAG19} op=persist-skip reason=message-write-failed accountId=${input.houseAccountId} sessionId=${conv.sessionId.slice(0, 8)}`
7601
+ `${TAG20} op=persist-skip reason=message-write-failed accountId=${input.houseAccountId} sessionId=${conv.sessionId.slice(0, 8)}`
7496
7602
  );
7497
7603
  return null;
7498
7604
  }
7499
7605
  console.error(
7500
- `${TAG19} op=persist accountId=${input.houseAccountId} sessionId=${conv.sessionId.slice(0, 8)} messageId=${messageId.slice(0, 8)} bytes=${Buffer.byteLength(input.text, "utf8")}`
7606
+ `${TAG20} op=persist accountId=${input.houseAccountId} sessionId=${conv.sessionId.slice(0, 8)} messageId=${messageId.slice(0, 8)} bytes=${Buffer.byteLength(input.text, "utf8")}`
7501
7607
  );
7502
7608
  return { sessionId: conv.sessionId, messageId };
7503
7609
  } catch (err) {
7504
7610
  console.error(
7505
- `${TAG19} op=persist-fail accountId=${input.houseAccountId} key=${input.sessionKey} reason=${err instanceof Error ? err.message : String(err)}`
7611
+ `${TAG20} op=persist-fail accountId=${input.houseAccountId} key=${input.sessionKey} reason=${err instanceof Error ? err.message : String(err)}`
7506
7612
  );
7507
7613
  return null;
7508
7614
  }
@@ -7810,7 +7916,7 @@ function parseScheduleProvenance(v) {
7810
7916
  }
7811
7917
 
7812
7918
  // server/routes/channel/schedule-inject.ts
7813
- var TAG20 = "[schedule-inject]";
7919
+ var TAG21 = "[schedule-inject]";
7814
7920
  function isLoopbackAddr(addr) {
7815
7921
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
7816
7922
  }
@@ -7820,7 +7926,7 @@ function createScheduleInjectRoutes(deps) {
7820
7926
  const env = c.env;
7821
7927
  const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
7822
7928
  if (!isLoopbackAddr(remoteAddr)) {
7823
- console.error(`${TAG20} reject reason=non-loopback remoteAddr=${remoteAddr}`);
7929
+ console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
7824
7930
  return c.json({ ok: false, error: "schedule-inject-loopback-only" }, 403);
7825
7931
  }
7826
7932
  const xffHeader = env?.incoming?.headers?.["x-forwarded-for"];
@@ -7828,7 +7934,7 @@ function createScheduleInjectRoutes(deps) {
7828
7934
  if (xffRaw.length > 0) {
7829
7935
  const offender = xffRaw.split(",").map((t) => t.trim()).filter(Boolean).find((t) => !isLoopbackAddr(t));
7830
7936
  if (offender !== void 0) {
7831
- console.error(`${TAG20} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
7937
+ console.error(`${TAG21} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
7832
7938
  return c.json({ ok: false, error: "schedule-inject-loopback-only" }, 403);
7833
7939
  }
7834
7940
  }
@@ -7844,23 +7950,23 @@ function createScheduleInjectRoutes(deps) {
7844
7950
  const eventId = typeof body.eventId === "string" ? body.eventId : "";
7845
7951
  const scheduleProvenance = parseScheduleProvenance(body.scheduleProvenance);
7846
7952
  if (channel !== "whatsapp" && channel !== "telegram" || !destination || !prompt) {
7847
- console.error(`${TAG20} reject reason=bad-request channel=${String(channel)} hasDestination=${Boolean(destination)} hasPrompt=${Boolean(prompt)}`);
7953
+ console.error(`${TAG21} reject reason=bad-request channel=${String(channel)} hasDestination=${Boolean(destination)} hasPrompt=${Boolean(prompt)}`);
7848
7954
  return c.json({ ok: false, error: "schedule-inject-bad-request" }, 400);
7849
7955
  }
7850
7956
  const account = deps.resolveAccount();
7851
7957
  if (!account) {
7852
- console.error(`${TAG20} reject reason=no-account eventId=${eventId}`);
7958
+ console.error(`${TAG21} reject reason=no-account eventId=${eventId}`);
7853
7959
  return c.json({ ok: false, error: "no-account" }, 500);
7854
7960
  }
7855
7961
  const houseAccountId = account.accountId;
7856
- console.error(`${TAG20} op=received eventId=${eventId} channel=${channel} destination=${destination} account=${houseAccountId}`);
7962
+ console.error(`${TAG21} op=received eventId=${eventId} channel=${channel} destination=${destination} account=${houseAccountId}`);
7857
7963
  if (channel === "whatsapp") {
7858
7964
  const effectiveAccount2 = deps.effectiveAccountFor(houseAccountId, account.accountDir, destination);
7859
7965
  if (effectiveAccount2 === null) {
7860
- console.error(`${TAG20} op=schedule-account-manager-reject eventId=${eventId} destination=${destination} reason=unresolved-effective-account`);
7966
+ console.error(`${TAG21} op=schedule-account-manager-reject eventId=${eventId} destination=${destination} reason=unresolved-effective-account`);
7861
7967
  return c.json({ ok: false, error: "account-manager-unresolved" }, 403);
7862
7968
  }
7863
- console.error(`${TAG20} op=effective-account eventId=${eventId} effectiveAccount=${effectiveAccount2}`);
7969
+ console.error(`${TAG21} op=effective-account eventId=${eventId} effectiveAccount=${effectiveAccount2}`);
7864
7970
  const sessionId2 = adminSessionIdFor(effectiveAccount2, normalizeTarget(destination) ?? destination);
7865
7971
  const reply2 = (text) => deps.sendWhatsAppText(houseAccountId, destination, text);
7866
7972
  try {
@@ -7882,17 +7988,17 @@ function createScheduleInjectRoutes(deps) {
7882
7988
  reply: reply2
7883
7989
  });
7884
7990
  } catch (err) {
7885
- console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId2} result=inject-error status=${err instanceof Error ? err.message : String(err)}`);
7991
+ console.error(`${TAG21} op=inject-spawn eventId=${eventId} sessionId=${sessionId2} result=inject-error status=${err instanceof Error ? err.message : String(err)}`);
7886
7992
  return c.json({ ok: false, error: "inject-error" }, 502);
7887
7993
  }
7888
- console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId2} result=ok status=-`);
7994
+ console.error(`${TAG21} op=inject-spawn eventId=${eventId} sessionId=${sessionId2} result=ok status=-`);
7889
7995
  return c.json({ ok: true }, 200);
7890
7996
  }
7891
7997
  const effectiveAccount = houseAccountId;
7892
- console.error(`${TAG20} op=effective-account eventId=${eventId} effectiveAccount=${effectiveAccount}`);
7998
+ console.error(`${TAG21} op=effective-account eventId=${eventId} effectiveAccount=${effectiveAccount}`);
7893
7999
  const botToken = account.config.telegram?.adminBotToken;
7894
8000
  if (!botToken) {
7895
- console.error(`${TAG20} reject reason=no-admin-bot-token eventId=${eventId}`);
8001
+ console.error(`${TAG21} reject reason=no-admin-bot-token eventId=${eventId}`);
7896
8002
  return c.json({ ok: false, error: "no-admin-bot-token" }, 400);
7897
8003
  }
7898
8004
  const chatId = Number(destination);
@@ -7911,10 +8017,10 @@ function createScheduleInjectRoutes(deps) {
7911
8017
  reply
7912
8018
  });
7913
8019
  } catch (err) {
7914
- console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=inject-error status=${err instanceof Error ? err.message : String(err)}`);
8020
+ console.error(`${TAG21} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=inject-error status=${err instanceof Error ? err.message : String(err)}`);
7915
8021
  return c.json({ ok: false, error: "inject-error" }, 502);
7916
8022
  }
7917
- console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
8023
+ console.error(`${TAG21} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
7918
8024
  return c.json({ ok: true }, 200);
7919
8025
  });
7920
8026
  return app70;
@@ -7971,7 +8077,7 @@ import { randomUUID as randomUUID6 } from "crypto";
7971
8077
  // app/lib/whatsapp/config-persist.ts
7972
8078
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "fs";
7973
8079
  import { resolve as resolve9, join as join10, dirname as dirname2, basename as basename2 } from "path";
7974
- var TAG21 = "[whatsapp:config]";
8080
+ var TAG22 = "[whatsapp:config]";
7975
8081
  function configPath(accountDir) {
7976
8082
  return resolve9(accountDir, "account.json");
7977
8083
  }
@@ -7988,9 +8094,9 @@ function reloadManagerConfig(accountDir) {
7988
8094
  try {
7989
8095
  const config = readConfig(accountDir);
7990
8096
  reloadConfig(config);
7991
- console.error(`${TAG21} reloaded manager config`);
8097
+ console.error(`${TAG22} reloaded manager config`);
7992
8098
  } catch (err) {
7993
- console.error(`${TAG21} manager config reload failed: ${String(err)}`);
8099
+ console.error(`${TAG22} manager config reload failed: ${String(err)}`);
7994
8100
  }
7995
8101
  }
7996
8102
  var E164_PATTERN = /^\+\d{7,15}$/;
@@ -8016,25 +8122,25 @@ function persistAfterPairing(accountDir, accountId, selfPhone) {
8016
8122
  const adminPhones = wa.adminPhones;
8017
8123
  if (!adminPhones.includes(normalized)) {
8018
8124
  adminPhones.push(normalized);
8019
- console.error(`${TAG21} added selfPhone=${normalized} to adminPhones`);
8125
+ console.error(`${TAG22} added selfPhone=${normalized} to adminPhones`);
8020
8126
  }
8021
8127
  } else {
8022
- console.error(`${TAG21} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
8128
+ console.error(`${TAG22} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
8023
8129
  }
8024
8130
  const parsed = WhatsAppConfigSchema.safeParse(wa);
8025
8131
  if (!parsed.success) {
8026
8132
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
8027
- console.error(`${TAG21} validation failed after pairing: ${msg}`);
8133
+ console.error(`${TAG22} validation failed after pairing: ${msg}`);
8028
8134
  return { ok: false, error: `Validation failed: ${msg}` };
8029
8135
  }
8030
8136
  config.whatsapp = parsed.data;
8031
8137
  writeConfig(accountDir, config);
8032
- console.error(`${TAG21} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
8138
+ console.error(`${TAG22} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
8033
8139
  reloadManagerConfig(accountDir);
8034
8140
  return { ok: true };
8035
8141
  } catch (err) {
8036
8142
  const msg = err instanceof Error ? err.message : String(err);
8037
- console.error(`${TAG21} persist failed account=${accountId}: ${msg}`);
8143
+ console.error(`${TAG22} persist failed account=${accountId}: ${msg}`);
8038
8144
  return { ok: false, error: msg };
8039
8145
  }
8040
8146
  }
@@ -8048,7 +8154,7 @@ function addAdminPhone(accountDir, phone) {
8048
8154
  const targetId = typeof config.accountId === "string" && config.accountId ? config.accountId : basename2(resolve9(accountDir));
8049
8155
  const socketOwner = resolveHouseOrSoleAccountId(dirname2(resolve9(accountDir)));
8050
8156
  if (targetId !== socketOwner) {
8051
- console.error(`${TAG21} add-admin-phone rejected accountId=${targetId} reason=not-socket-account`);
8157
+ console.error(`${TAG22} add-admin-phone rejected accountId=${targetId} reason=not-socket-account`);
8052
8158
  return {
8053
8159
  ok: false,
8054
8160
  reason: "not-socket-account",
@@ -8077,12 +8183,12 @@ function addAdminPhone(accountDir, phone) {
8077
8183
  }
8078
8184
  config.whatsapp = parsed.data;
8079
8185
  writeConfig(accountDir, config);
8080
- console.error(`${TAG21} added admin phone=${normalized}`);
8186
+ console.error(`${TAG22} added admin phone=${normalized}`);
8081
8187
  reloadManagerConfig(accountDir);
8082
8188
  return { ok: true, message: `Added ${normalized} as admin phone. Messages from this number will route to the admin agent.` };
8083
8189
  } catch (err) {
8084
8190
  const msg = err instanceof Error ? err.message : String(err);
8085
- console.error(`${TAG21} addAdminPhone failed: ${msg}`);
8191
+ console.error(`${TAG22} addAdminPhone failed: ${msg}`);
8086
8192
  return { ok: false, error: msg };
8087
8193
  }
8088
8194
  }
@@ -8110,12 +8216,12 @@ function removeAdminPhone(accountDir, phone) {
8110
8216
  }
8111
8217
  config.whatsapp = parsed.data;
8112
8218
  writeConfig(accountDir, config);
8113
- console.error(`${TAG21} removed admin phone=${normalized}`);
8219
+ console.error(`${TAG22} removed admin phone=${normalized}`);
8114
8220
  reloadManagerConfig(accountDir);
8115
8221
  return { ok: true, message: `Removed ${normalized} from admin phones. Messages from this number will now route to the public agent.` };
8116
8222
  } catch (err) {
8117
8223
  const msg = err instanceof Error ? err.message : String(err);
8118
- console.error(`${TAG21} removeAdminPhone failed: ${msg}`);
8224
+ console.error(`${TAG22} removeAdminPhone failed: ${msg}`);
8119
8225
  return { ok: false, error: msg };
8120
8226
  }
8121
8227
  }
@@ -8210,13 +8316,13 @@ function setAccountManager(accountDir, phone, subAccountId, mode = "active") {
8210
8316
  }
8211
8317
  config.whatsapp = parsed.data;
8212
8318
  writeConfig(accountDir, config);
8213
- console.error(`${TAG21} bound account manager phone=${normalized} managesAccount=${sub} mode=${mode}`);
8319
+ console.error(`${TAG22} bound account manager phone=${normalized} managesAccount=${sub} mode=${mode}`);
8214
8320
  reloadManagerConfig(accountDir);
8215
8321
  const behaviour = mode === "passive" ? `Their WhatsApp messages will each file one task scoped to that sub-account; the agent sends nothing back.` : `Their WhatsApp messages will reach that sub-account's admin agent; replies still go out over this account's WhatsApp device.`;
8216
8322
  return { ok: true, message: `Bound ${normalized} as ${mode} account manager for sub-account ${sub}. ${behaviour}` };
8217
8323
  } catch (err) {
8218
8324
  const msg = err instanceof Error ? err.message : String(err);
8219
- console.error(`${TAG21} setAccountManager failed: ${msg}`);
8325
+ console.error(`${TAG22} setAccountManager failed: ${msg}`);
8220
8326
  return { ok: false, error: msg };
8221
8327
  }
8222
8328
  }
@@ -8253,12 +8359,12 @@ function setDispatchInbound(accountDir, accountId, value) {
8253
8359
  }
8254
8360
  config.whatsapp = parsed.data;
8255
8361
  writeConfig(accountDir, config);
8256
- console.error(`${TAG21} set dispatchInbound account=${id} value=${value}`);
8362
+ console.error(`${TAG22} set dispatchInbound account=${id} value=${value}`);
8257
8363
  reloadManagerConfig(accountDir);
8258
8364
  return { ok: true };
8259
8365
  } catch (err) {
8260
8366
  const msg = err instanceof Error ? err.message : String(err);
8261
- console.error(`${TAG21} setDispatchInbound failed: ${msg}`);
8367
+ console.error(`${TAG22} setDispatchInbound failed: ${msg}`);
8262
8368
  return { ok: false, error: msg };
8263
8369
  }
8264
8370
  }
@@ -8283,12 +8389,12 @@ function clearAccountManager(accountDir, phone) {
8283
8389
  }
8284
8390
  config.whatsapp = parsed.data;
8285
8391
  writeConfig(accountDir, config);
8286
- console.error(`${TAG21} cleared account manager phone=${normalized}`);
8392
+ console.error(`${TAG22} cleared account manager phone=${normalized}`);
8287
8393
  reloadManagerConfig(accountDir);
8288
8394
  return { ok: true, message: `Cleared the account-manager binding for ${normalized}.` };
8289
8395
  } catch (err) {
8290
8396
  const msg = err instanceof Error ? err.message : String(err);
8291
- console.error(`${TAG21} clearAccountManager failed: ${msg}`);
8397
+ console.error(`${TAG22} clearAccountManager failed: ${msg}`);
8292
8398
  return { ok: false, error: msg };
8293
8399
  }
8294
8400
  }
@@ -8335,12 +8441,12 @@ function setPublicAgent(accountDir, slug) {
8335
8441
  }
8336
8442
  config.whatsapp = parsed.data;
8337
8443
  writeConfig(accountDir, config);
8338
- console.error(`${TAG21} publicAgent set to ${trimmed}`);
8444
+ console.error(`${TAG22} publicAgent set to ${trimmed}`);
8339
8445
  reloadManagerConfig(accountDir);
8340
8446
  return { ok: true, message: `Public agent set to "${trimmed}". WhatsApp messages from non-admin phones will be handled by this agent.` };
8341
8447
  } catch (err) {
8342
8448
  const msg = err instanceof Error ? err.message : String(err);
8343
- console.error(`${TAG21} setPublicAgent failed: ${msg}`);
8449
+ console.error(`${TAG22} setPublicAgent failed: ${msg}`);
8344
8450
  return { ok: false, error: msg };
8345
8451
  }
8346
8452
  }
@@ -8381,17 +8487,17 @@ function updateConfig(accountDir, fields) {
8381
8487
  const parsed = WhatsAppConfigSchema.safeParse(wa);
8382
8488
  if (!parsed.success) {
8383
8489
  const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
8384
- console.error(`${TAG21} update validation failed: ${msg}`);
8490
+ console.error(`${TAG22} update validation failed: ${msg}`);
8385
8491
  return { ok: false, error: `Validation failed: ${msg}` };
8386
8492
  }
8387
8493
  config.whatsapp = parsed.data;
8388
8494
  writeConfig(accountDir, config);
8389
- console.error(`${TAG21} updated fields=[${fieldNames.join(",")}]`);
8495
+ console.error(`${TAG22} updated fields=[${fieldNames.join(",")}]`);
8390
8496
  reloadManagerConfig(accountDir);
8391
8497
  return { ok: true, message: `Updated WhatsApp config: ${fieldNames.join(", ")}.` };
8392
8498
  } catch (err) {
8393
8499
  const msg = err instanceof Error ? err.message : String(err);
8394
- console.error(`${TAG21} updateConfig failed: ${msg}`);
8500
+ console.error(`${TAG22} updateConfig failed: ${msg}`);
8395
8501
  return { ok: false, error: msg };
8396
8502
  }
8397
8503
  }
@@ -8428,17 +8534,17 @@ function migrateRemovedConfigKeys(accountDir) {
8428
8534
  }
8429
8535
  writeConfig(accountDir, config);
8430
8536
  console.error(
8431
- `${TAG21} migration: stripped unknown keys=[${result.droppedKeys.join(",")}] from account.json`
8537
+ `${TAG22} migration: stripped unknown keys=[${result.droppedKeys.join(",")}] from account.json`
8432
8538
  );
8433
8539
  return { dropped: result.droppedKeys };
8434
8540
  } catch (err) {
8435
- console.error(`${TAG21} migration failed: ${String(err)}`);
8541
+ console.error(`${TAG22} migration failed: ${String(err)}`);
8436
8542
  return { dropped: [] };
8437
8543
  }
8438
8544
  }
8439
8545
 
8440
8546
  // app/lib/whatsapp/login.ts
8441
- var TAG22 = "[whatsapp:login]";
8547
+ var TAG23 = "[whatsapp:login]";
8442
8548
  function maskPhone(digits) {
8443
8549
  if (digits.length <= 4) return "*".repeat(digits.length);
8444
8550
  return digits.slice(0, 2) + "*".repeat(digits.length - 4) + digits.slice(-2);
@@ -8449,7 +8555,7 @@ function closeSocket(sock) {
8449
8555
  try {
8450
8556
  sock.ws?.close?.();
8451
8557
  } catch (err) {
8452
- console.warn(`${TAG22} socket close error during cleanup: ${String(err)}`);
8558
+ console.warn(`${TAG23} socket close error during cleanup: ${String(err)}`);
8453
8559
  }
8454
8560
  }
8455
8561
  function resetActiveLogin(accountId) {
@@ -8476,18 +8582,18 @@ async function runPostPairing(login) {
8476
8582
  const masked = selfPhone ? `${selfPhone.slice(0, 4)}***` : "null";
8477
8583
  console.error(`[whatsapp-persist] wa-persist-on-connect account=${login.accountId} phone=${masked}`);
8478
8584
  } else {
8479
- console.error(`${TAG22} wa-persist-on-connect FAILED account=${login.accountId}: ${result.error}`);
8585
+ console.error(`${TAG23} wa-persist-on-connect FAILED account=${login.accountId}: ${result.error}`);
8480
8586
  }
8481
8587
  } catch (err) {
8482
- console.error(`${TAG22} wa-persist-on-connect error account=${login.accountId}: ${String(err)}`);
8588
+ console.error(`${TAG23} wa-persist-on-connect error account=${login.accountId}: ${String(err)}`);
8483
8589
  }
8484
8590
  } else {
8485
- console.error(`${TAG22} wa-persist-on-connect skipped \u2014 no accountDir account=${login.accountId}`);
8591
+ console.error(`${TAG23} wa-persist-on-connect skipped \u2014 no accountDir account=${login.accountId}`);
8486
8592
  }
8487
8593
  try {
8488
8594
  await registerLoginSocket(login.accountId, login.sock, login.authDir);
8489
8595
  } catch (err) {
8490
- console.error(`${TAG22} registerLoginSocket failed account=${login.accountId}: ${String(err)}`);
8596
+ console.error(`${TAG23} registerLoginSocket failed account=${login.accountId}: ${String(err)}`);
8491
8597
  }
8492
8598
  }
8493
8599
  async function loginConnectionLoop(accountId, login) {
@@ -8496,7 +8602,7 @@ async function loginConnectionLoop(accountId, login) {
8496
8602
  const logTerminal = (outcome, errMsg) => {
8497
8603
  const fc = credsCensus(login.authDir);
8498
8604
  console.error(
8499
- `${TAG22} op=terminal cid=${cidShort} outcome=${outcome} credsFinal={registered=${fc.registered},account=${fc.hasAccountSignature},me=${fc.e164 ?? "null"}}` + (errMsg ? ` error="${errMsg}"` : "")
8605
+ `${TAG23} op=terminal cid=${cidShort} outcome=${outcome} credsFinal={registered=${fc.registered},account=${fc.hasAccountSignature},me=${fc.e164 ?? "null"}}` + (errMsg ? ` error="${errMsg}"` : "")
8500
8606
  );
8501
8607
  };
8502
8608
  while (true) {
@@ -8506,7 +8612,7 @@ async function loginConnectionLoop(accountId, login) {
8506
8612
  if (current?.id === login.id) {
8507
8613
  await runPostPairing(current);
8508
8614
  current.connected = true;
8509
- console.error(`${TAG22} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
8615
+ console.error(`${TAG23} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
8510
8616
  logTerminal("connected");
8511
8617
  }
8512
8618
  return;
@@ -8518,7 +8624,7 @@ async function loginConnectionLoop(accountId, login) {
8518
8624
  if (!preRetryCensus.hasAccountSignature) {
8519
8625
  current.error = "WhatsApp accepted the code but did not finish linking. This usually means the number has reached its linked-device limit or has a stale linked device. On the phone, open WhatsApp, Linked Devices, remove existing devices, then ask for a new code.";
8520
8626
  console.error(
8521
- `${TAG22} op=pairing-incomplete cid=${cidShort} closeKind=${closeKind(getStatusCode(err), false)} reason=no-account-signature`
8627
+ `${TAG23} op=pairing-incomplete cid=${cidShort} closeKind=${closeKind(getStatusCode(err), false)} reason=no-account-signature`
8522
8628
  );
8523
8629
  return;
8524
8630
  }
@@ -8526,7 +8632,7 @@ async function loginConnectionLoop(accountId, login) {
8526
8632
  if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
8527
8633
  if (attempt >= LOGIN_MAX_RECONNECTS) {
8528
8634
  console.error(
8529
- `${TAG22} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
8635
+ `${TAG23} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
8530
8636
  );
8531
8637
  current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
8532
8638
  } else {
@@ -8539,7 +8645,7 @@ async function loginConnectionLoop(accountId, login) {
8539
8645
  attempt++;
8540
8646
  const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
8541
8647
  console.error(
8542
- `${TAG22} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
8648
+ `${TAG23} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
8543
8649
  );
8544
8650
  closeSocket(current.sock);
8545
8651
  await new Promise((r) => setTimeout(r, delay));
@@ -8547,14 +8653,14 @@ async function loginConnectionLoop(accountId, login) {
8547
8653
  if (afterDelay?.id !== login.id) return;
8548
8654
  const rc = credsCensus(login.authDir);
8549
8655
  console.error(
8550
- `${TAG22} op=reconnect cid=${cidShort} attempt=${attempt}/${LOGIN_MAX_RECONNECTS} withRegistered=${rc.registered} withAccount=${rc.hasAccountSignature}`
8656
+ `${TAG23} op=reconnect cid=${cidShort} attempt=${attempt}/${LOGIN_MAX_RECONNECTS} withRegistered=${rc.registered} withAccount=${rc.hasAccountSignature}`
8551
8657
  );
8552
8658
  try {
8553
8659
  const newSock = await createWaSocket({ authDir: login.authDir, correlationId: cidShort, account: accountId });
8554
8660
  current.sock = newSock;
8555
8661
  } catch (sockErr) {
8556
8662
  console.error(
8557
- `${TAG22} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
8663
+ `${TAG23} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
8558
8664
  );
8559
8665
  current.error = `Reconnection failed: ${String(sockErr)}`;
8560
8666
  logTerminal("error", current.error);
@@ -8571,7 +8677,7 @@ async function startLogin(opts) {
8571
8677
  const hasAuth = await authExists(authDir);
8572
8678
  const selfId = readSelfId(authDir);
8573
8679
  console.error(
8574
- `${TAG22} op=start cid=${cid} account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
8680
+ `${TAG23} op=start cid=${cid} account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
8575
8681
  );
8576
8682
  if (hasAuth && !force) {
8577
8683
  const who = selfId.e164 ?? selfId.jid ?? "unknown";
@@ -8586,7 +8692,7 @@ async function startLogin(opts) {
8586
8692
  }
8587
8693
  const existing = activeLogins.get(accountId);
8588
8694
  if (existing && isLoginFresh(existing) && existing.pairingCode && !force) {
8589
- console.error(`${TAG22} startLogin account=${accountId} guard: returning existing pairing code (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
8695
+ console.error(`${TAG23} startLogin account=${accountId} guard: returning existing pairing code (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
8590
8696
  return {
8591
8697
  pairingCode: existing.pairingCode,
8592
8698
  phone: existing.phone,
@@ -8594,7 +8700,7 @@ async function startLogin(opts) {
8594
8700
  };
8595
8701
  }
8596
8702
  if (existing) {
8597
- console.error(`${TAG22} startLogin account=${accountId} ${force ? "force override" : "stale/no-code"}, resetting active login`);
8703
+ console.error(`${TAG23} startLogin account=${accountId} ${force ? "force override" : "stale/no-code"}, resetting active login`);
8598
8704
  }
8599
8705
  resetActiveLogin(accountId);
8600
8706
  await clearAuth(authDir);
@@ -8625,7 +8731,7 @@ async function startLogin(opts) {
8625
8731
  if (requested) return;
8626
8732
  requested = true;
8627
8733
  console.error(
8628
- `${TAG22} op=pairing-request cid=${cid} account=${accountId} qrRef=#1 sinceOpenMs=${socketOpenTs ? Date.now() - socketOpenTs : 0}`
8734
+ `${TAG23} op=pairing-request cid=${cid} account=${accountId} qrRef=#1 sinceOpenMs=${socketOpenTs ? Date.now() - socketOpenTs : 0}`
8629
8735
  );
8630
8736
  void sock.requestPairingCode(digits).then((code) => {
8631
8737
  clearTimeout(codeTimer);
@@ -8634,7 +8740,7 @@ async function startLogin(opts) {
8634
8740
  if (current?.id !== login.id) return;
8635
8741
  if (!current.pairingCode) current.pairingCode = code;
8636
8742
  console.error(
8637
- `${TAG22} op=code-issued cid=${cid} account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length} sinceOpenMs=${socketOpenTs ? codeIssuedTs - socketOpenTs : 0}`
8743
+ `${TAG23} op=code-issued cid=${cid} account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length} sinceOpenMs=${socketOpenTs ? codeIssuedTs - socketOpenTs : 0}`
8638
8744
  );
8639
8745
  resolveCode?.(code);
8640
8746
  }).catch((err) => {
@@ -8665,7 +8771,7 @@ async function startLogin(opts) {
8665
8771
  const ttlTimer = setTimeout(() => {
8666
8772
  const current = activeLogins.get(accountId);
8667
8773
  if (current?.id === login.id && !current.connected) {
8668
- console.error(`${TAG22} pairing-window-elapsed account=${accountId} (ttl sweep)`);
8774
+ console.error(`${TAG23} pairing-window-elapsed account=${accountId} (ttl sweep)`);
8669
8775
  resetActiveLogin(accountId);
8670
8776
  }
8671
8777
  }, ACTIVE_LOGIN_TTL_MS);
@@ -8673,7 +8779,7 @@ async function startLogin(opts) {
8673
8779
  ttlTimer.unref();
8674
8780
  }
8675
8781
  loginConnectionLoop(accountId, login).catch((err) => {
8676
- console.error(`${TAG22} loginConnectionLoop unexpected error: ${String(err)}`);
8782
+ console.error(`${TAG23} loginConnectionLoop unexpected error: ${String(err)}`);
8677
8783
  const current = activeLogins.get(accountId);
8678
8784
  if (current?.id === login.id) {
8679
8785
  current.error = `Unexpected login error: ${String(err)}`;
@@ -8698,13 +8804,13 @@ async function waitForLogin(opts) {
8698
8804
  const { accountId, timeoutMs = 6e4 } = opts;
8699
8805
  const login = activeLogins.get(accountId);
8700
8806
  console.error(
8701
- `${TAG22} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasCode=${!!login.pairingCode}}` : " login=none")
8807
+ `${TAG23} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasCode=${!!login.pairingCode}}` : " login=none")
8702
8808
  );
8703
8809
  if (!login) {
8704
8810
  return { connected: false, message: "No active WhatsApp login in progress.", configPersisted: false };
8705
8811
  }
8706
8812
  if (!isLoginFresh(login)) {
8707
- console.error(`${TAG22} pairing-window-elapsed account=${accountId}`);
8813
+ console.error(`${TAG23} pairing-window-elapsed account=${accountId}`);
8708
8814
  resetActiveLogin(accountId);
8709
8815
  return { connected: false, message: "The pairing window expired. Ask me to generate a new code.", configPersisted: false };
8710
8816
  }
@@ -8712,8 +8818,8 @@ async function waitForLogin(opts) {
8712
8818
  while (Date.now() < deadline) {
8713
8819
  if (login.connected) {
8714
8820
  const selfId = readSelfId(login.authDir);
8715
- console.error(`${TAG22} pairing-connected account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
8716
- console.error(`${TAG22} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"} configPersisted=${login.configPersisted}`);
8821
+ console.error(`${TAG23} pairing-connected account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
8822
+ console.error(`${TAG23} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"} configPersisted=${login.configPersisted}`);
8717
8823
  const configPersisted = login.configPersisted;
8718
8824
  activeLogins.delete(accountId);
8719
8825
  return {
@@ -8731,7 +8837,7 @@ async function waitForLogin(opts) {
8731
8837
  await new Promise((r) => setTimeout(r, 1e3));
8732
8838
  }
8733
8839
  const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
8734
- console.error(`${TAG22} waitForLogin poll timeout account=${accountId} elapsed=${elapsed}s \u2014 login kept alive (pairing code still valid)`);
8840
+ console.error(`${TAG23} waitForLogin poll timeout account=${accountId} elapsed=${elapsed}s \u2014 login kept alive (pairing code still valid)`);
8735
8841
  return { connected: false, message: "Still waiting for you to enter the pairing code. The code is still valid \u2014 ask me to keep waiting, or request a new code.", configPersisted: false };
8736
8842
  }
8737
8843
  function listActiveLoginAccountIds() {
@@ -8753,7 +8859,7 @@ function reconcileMessageStoreAccountKeys(input) {
8753
8859
  import { realpathSync as realpathSync3 } from "fs";
8754
8860
  import { readFile, stat as stat2 } from "fs/promises";
8755
8861
  import { resolve as resolve10, basename as basename3 } from "path";
8756
- var TAG23 = "[whatsapp:outbound]";
8862
+ var TAG24 = "[whatsapp:outbound]";
8757
8863
  var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
8758
8864
  var lastRouteDocumentOutboundAt = /* @__PURE__ */ new Map();
8759
8865
  function normalizeJid2(to) {
@@ -8786,10 +8892,10 @@ async function sendWhatsAppDocument(input) {
8786
8892
  } catch (err) {
8787
8893
  const code = err.code;
8788
8894
  if (code === "ENOENT") {
8789
- console.error(`${TAG23} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
8895
+ console.error(`${TAG24} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
8790
8896
  return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
8791
8897
  }
8792
- console.error(`${TAG23} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
8898
+ console.error(`${TAG24} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
8793
8899
  return { ok: false, status: 500, error: String(err) };
8794
8900
  }
8795
8901
  let resolvedPath;
@@ -8798,15 +8904,15 @@ async function sendWhatsAppDocument(input) {
8798
8904
  } catch (err) {
8799
8905
  const code = err.code;
8800
8906
  if (code === "ENOENT") {
8801
- console.error(`${TAG23} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
8907
+ console.error(`${TAG24} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
8802
8908
  return { ok: false, status: 404, error: `File not found: ${filePath}` };
8803
8909
  }
8804
- console.error(`${TAG23} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
8910
+ console.error(`${TAG24} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
8805
8911
  return { ok: false, status: 500, error: String(err) };
8806
8912
  }
8807
8913
  if (!resolvedPath.startsWith(accountResolved + "/")) {
8808
8914
  const sanitised = filePath.replace(accountDir, "<account>/");
8809
- console.error(`${TAG23} document REJECTED path=${sanitised} reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
8915
+ console.error(`${TAG24} document REJECTED path=${sanitised} reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
8810
8916
  return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
8811
8917
  }
8812
8918
  const fileStat = await stat2(resolvedPath);
@@ -8822,7 +8928,7 @@ async function sendWhatsAppDocument(input) {
8822
8928
  const res = resolveSocket(accountId);
8823
8929
  if (!res.ok) {
8824
8930
  const reason = formatSocketResolutionReason(res);
8825
- console.error(`${TAG23} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=false reason=${reason}`);
8931
+ console.error(`${TAG24} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=false reason=${reason}`);
8826
8932
  return { ok: false, status: 503, error: formatSocketResolutionMessage(res, accountId) };
8827
8933
  }
8828
8934
  const sock = res.sock;
@@ -8835,7 +8941,7 @@ async function sendWhatsAppDocument(input) {
8835
8941
  { accountId: res.accountId }
8836
8942
  );
8837
8943
  console.error(
8838
- `${TAG23} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
8944
+ `${TAG24} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
8839
8945
  );
8840
8946
  if (result.success) {
8841
8947
  recordDocumentOutbound(to);
@@ -8955,7 +9061,7 @@ function serializeWhatsAppSchema() {
8955
9061
  // app/lib/whatsapp/status-reconcile.ts
8956
9062
  import { readdirSync as readdirSync6 } from "fs";
8957
9063
  import { join as join11 } from "path";
8958
- var TAG24 = "[whatsapp:reconcile]";
9064
+ var TAG25 = "[whatsapp:reconcile]";
8959
9065
  var HALF_REGISTERED_MIN_AGE_MS = 5 * 6e4;
8960
9066
  function listCredsAccountIds(credsRoot) {
8961
9067
  try {
@@ -8981,14 +9087,14 @@ function reconcileCredsOnDisk(opts) {
8981
9087
  const ageMs2 = getAuthAgeMs(authDir);
8982
9088
  const abandoned = !inFlight3 && ageMs2 !== null && ageMs2 >= HALF_REGISTERED_MIN_AGE_MS;
8983
9089
  if (!abandoned) {
8984
- console.error(`${TAG24} op=half-registered account=${accountId} registered=true hasAccount=false inFlight=${inFlight3} ageMs=${ageMs2 ?? "null"}`);
9090
+ console.error(`${TAG25} op=half-registered account=${accountId} registered=true hasAccount=false inFlight=${inFlight3} ageMs=${ageMs2 ?? "null"}`);
8985
9091
  entries2.push({ accountId, connected: false, linkedUnconfigured: true });
8986
9092
  continue;
8987
9093
  }
8988
- console.error(`${TAG24} op=discard-half-registered account=${accountId} registered=true hasAccount=false ageMs=${ageMs2}`);
9094
+ console.error(`${TAG25} op=discard-half-registered account=${accountId} registered=true hasAccount=false ageMs=${ageMs2}`);
8989
9095
  const removed = discardAuthDirSync(authDir);
8990
9096
  if (!removed) {
8991
- console.error(`${TAG24} op=discard-half-registered-failed account=${accountId} \u2014 residue persists`);
9097
+ console.error(`${TAG25} op=discard-half-registered-failed account=${accountId} \u2014 residue persists`);
8992
9098
  entries2.push({ accountId, connected: false, linkedUnconfigured: true });
8993
9099
  }
8994
9100
  continue;
@@ -8996,14 +9102,14 @@ function reconcileCredsOnDisk(opts) {
8996
9102
  const selfPhone = readSelfId(authDir).e164 ?? void 0;
8997
9103
  const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
8998
9104
  console.error(
8999
- `${TAG24} wa-link-unconfigured account=${accountId} creds=present config=${configured ? "present" : "absent"}`
9105
+ `${TAG25} wa-link-unconfigured account=${accountId} creds=present config=${configured ? "present" : "absent"}`
9000
9106
  );
9001
9107
  if (!configured && accountDir) {
9002
9108
  const result = persistAfterPairing(accountDir, accountId, selfPhone ?? null);
9003
9109
  if (result.ok) {
9004
- console.error(`${TAG24} self-healed account=${accountId}`);
9110
+ console.error(`${TAG25} self-healed account=${accountId}`);
9005
9111
  } else {
9006
- console.error(`${TAG24} self-heal FAILED account=${accountId}: ${result.error}`);
9112
+ console.error(`${TAG25} self-heal FAILED account=${accountId}: ${result.error}`);
9007
9113
  }
9008
9114
  }
9009
9115
  entries2.push({ accountId, selfPhone, connected: false, linkedUnconfigured: !configured });
@@ -9146,7 +9252,7 @@ function authorizeRecallRead(input) {
9146
9252
  }
9147
9253
 
9148
9254
  // server/routes/whatsapp.ts
9149
- var TAG25 = "[whatsapp:api]";
9255
+ var TAG26 = "[whatsapp:api]";
9150
9256
  var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT || "";
9151
9257
  function recallAttachment(storeAccountId, attachmentId) {
9152
9258
  if (!attachmentId) return void 0;
@@ -9191,16 +9297,16 @@ function houseSocketScopeDenial(c, op) {
9191
9297
  const houseAccountId = resolveAccount()?.accountId ?? "";
9192
9298
  const { decision, callerAccountId, houseAdminScope } = evaluateCallerScope(c, houseAccountId);
9193
9299
  if (decision.authorized) return null;
9194
- console.error(`${TAG25} op=authz-deny route=${op} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9300
+ console.error(`${TAG26} op=authz-deny route=${op} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9195
9301
  return c.json({ ok: false, error: "Not authorized. The WhatsApp connection and its settings are house-scoped; this session may only act on its own account." }, 403);
9196
9302
  }
9197
9303
  function selfOrHouseScopeDenial(c, targetAccountId, op) {
9198
9304
  const { decision, callerAccountId, houseAdminScope } = evaluateCallerScope(c, targetAccountId);
9199
9305
  if (decision.authorized) {
9200
- console.error(`${TAG25} op=authz-ok route=${op} target=${targetAccountId} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9306
+ console.error(`${TAG26} op=authz-ok route=${op} target=${targetAccountId} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9201
9307
  return null;
9202
9308
  }
9203
- console.error(`${TAG25} op=authz-deny route=${op} target=${targetAccountId} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9309
+ console.error(`${TAG26} op=authz-deny route=${op} target=${targetAccountId} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`);
9204
9310
  return c.json({ ok: false, error: "Not authorized. This session may only pair or manage its own account." }, 403);
9205
9311
  }
9206
9312
  var app2 = new Hono();
@@ -9220,7 +9326,7 @@ app2.get("/status", (c) => {
9220
9326
  dispatchInbound: shouldDispatchInbound(cfg, a.accountId)
9221
9327
  }));
9222
9328
  const summary = accounts.map((a) => `${a.accountId}:${a.connected ? "up" : a.linkedUnconfigured ? "linked-unconfigured" : "down"}:${a.dispatchInbound ? "dispatch" : "observe"}`).join(", ");
9223
- console.error(`${TAG25} status accounts=${accounts.length} [${summary}]`);
9329
+ console.error(`${TAG26} status accounts=${accounts.length} [${summary}]`);
9224
9330
  const reachableAccountIds = [
9225
9331
  .../* @__PURE__ */ new Set([...listStoredAccountIds(), ...listConnectionPlatformAccountIds()])
9226
9332
  ];
@@ -9229,11 +9335,11 @@ app2.get("/status", (c) => {
9229
9335
  reachableAccountIds
9230
9336
  });
9231
9337
  if (!storeKeyReconcile.ok) {
9232
- console.warn(`${TAG25} store-key-drift orphanLiveKeys=[${storeKeyReconcile.orphanLiveKeys.join(",")}] \u2014 in-memory cache keyed by a value with no disk account; read tools will miss`);
9338
+ console.warn(`${TAG26} store-key-drift orphanLiveKeys=[${storeKeyReconcile.orphanLiveKeys.join(",")}] \u2014 in-memory cache keyed by a value with no disk account; read tools will miss`);
9233
9339
  }
9234
9340
  return c.json({ accounts, storeKeyReconcile });
9235
9341
  } catch (err) {
9236
- console.error(`${TAG25} status error: ${String(err)}`);
9342
+ console.error(`${TAG26} status error: ${String(err)}`);
9237
9343
  return c.json({ error: String(err) }, 500);
9238
9344
  }
9239
9345
  });
@@ -9251,10 +9357,10 @@ app2.post("/login/start", async (c) => {
9251
9357
  const authDir = join12(MAXY_DIR, "credentials", "whatsapp", accountId);
9252
9358
  const accountDir = resolveAccount()?.accountDir ?? null;
9253
9359
  const result = await startLogin({ accountId, authDir, phone, accountDir, force });
9254
- console.error(`${TAG25} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
9360
+ console.error(`${TAG26} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
9255
9361
  return c.json(result);
9256
9362
  } catch (err) {
9257
- console.error(`${TAG25} login/start error: ${String(err)}`);
9363
+ console.error(`${TAG26} login/start error: ${String(err)}`);
9258
9364
  return c.json({ error: String(err) }, 500);
9259
9365
  }
9260
9366
  });
@@ -9266,7 +9372,7 @@ app2.post("/login/wait", async (c) => {
9266
9372
  if (denial) return denial;
9267
9373
  const timeoutMs = body.timeoutMs ?? 6e4;
9268
9374
  const result = await waitForLogin({ accountId, timeoutMs });
9269
- console.error(`${TAG25} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${result.configPersisted}`);
9375
+ console.error(`${TAG26} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${result.configPersisted}`);
9270
9376
  return c.json({
9271
9377
  connected: result.connected,
9272
9378
  message: result.message,
@@ -9274,7 +9380,7 @@ app2.post("/login/wait", async (c) => {
9274
9380
  configPersisted: result.configPersisted
9275
9381
  });
9276
9382
  } catch (err) {
9277
- console.error(`${TAG25} login/wait error: ${String(err)}`);
9383
+ console.error(`${TAG26} login/wait error: ${String(err)}`);
9278
9384
  return c.json({ error: String(err) }, 500);
9279
9385
  }
9280
9386
  });
@@ -9287,7 +9393,7 @@ app2.post("/disconnect", async (c) => {
9287
9393
  await stopConnection(accountId);
9288
9394
  return c.json({ disconnected: true, accountId });
9289
9395
  } catch (err) {
9290
- console.error(`${TAG25} disconnect error: ${String(err)}`);
9396
+ console.error(`${TAG26} disconnect error: ${String(err)}`);
9291
9397
  return c.json({ error: String(err) }, 500);
9292
9398
  }
9293
9399
  });
@@ -9300,7 +9406,7 @@ app2.post("/reconnect", async (c) => {
9300
9406
  await startConnection(accountId);
9301
9407
  return c.json({ reconnecting: true, accountId });
9302
9408
  } catch (err) {
9303
- console.error(`${TAG25} reconnect error: ${String(err)}`);
9409
+ console.error(`${TAG26} reconnect error: ${String(err)}`);
9304
9410
  return c.json({ error: String(err) }, 500);
9305
9411
  }
9306
9412
  });
@@ -9324,7 +9430,7 @@ app2.post("/config", async (c) => {
9324
9430
  const acct = resolveAccount();
9325
9431
  if (!acct) return c.json({ ok: false, error: "No account configured." }, 500);
9326
9432
  const result = setDispatchInbound(acct.accountDir, target, body.dispatchInbound);
9327
- console.error(`${TAG25} config action=set-dispatch-inbound account=${target} dispatchInbound=${body.dispatchInbound} ok=${result.ok}`);
9433
+ console.error(`${TAG26} config action=set-dispatch-inbound account=${target} dispatchInbound=${body.dispatchInbound} ok=${result.ok}`);
9328
9434
  return c.json(result, result.ok ? 200 : 400);
9329
9435
  }
9330
9436
  const denial = houseSocketScopeDenial(c, `config action=${action}`);
@@ -9340,7 +9446,7 @@ app2.post("/config", async (c) => {
9340
9446
  }
9341
9447
  const result = addAdminPhone(account.accountDir, phone);
9342
9448
  const reasonTail = !result.ok && result.reason ? ` reason=${result.reason}` : "";
9343
- console.error(`${TAG25} config action=add-admin-phone accountId=${account.accountId} phone=${phone} ok=${result.ok}${reasonTail}`);
9449
+ console.error(`${TAG26} config action=add-admin-phone accountId=${account.accountId} phone=${phone} ok=${result.ok}${reasonTail}`);
9344
9450
  return c.json(result, result.ok ? 200 : 400);
9345
9451
  }
9346
9452
  case "remove-admin-phone": {
@@ -9348,12 +9454,12 @@ app2.post("/config", async (c) => {
9348
9454
  return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
9349
9455
  }
9350
9456
  const result = removeAdminPhone(account.accountDir, phone);
9351
- console.error(`${TAG25} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
9457
+ console.error(`${TAG26} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
9352
9458
  return c.json(result, result.ok ? 200 : 400);
9353
9459
  }
9354
9460
  case "list-admin-phones": {
9355
9461
  const phones = readAdminPhones(account.accountDir);
9356
- console.error(`${TAG25} config action=list-admin-phones count=${phones.length}`);
9462
+ console.error(`${TAG26} config action=list-admin-phones count=${phones.length}`);
9357
9463
  return c.json({ ok: true, phones });
9358
9464
  }
9359
9465
  case "add-account-manager": {
@@ -9365,7 +9471,7 @@ app2.post("/config", async (c) => {
9365
9471
  }
9366
9472
  const managerMode = mode === "passive" ? "passive" : "active";
9367
9473
  const result = setAccountManager(account.accountDir, phone, managesAccount, managerMode);
9368
- console.error(`${TAG25} config action=add-account-manager phone=${phone} managesAccount=${managesAccount} mode=${managerMode} ok=${result.ok}`);
9474
+ console.error(`${TAG26} config action=add-account-manager phone=${phone} managesAccount=${managesAccount} mode=${managerMode} ok=${result.ok}`);
9369
9475
  return c.json(result, result.ok ? 200 : 400);
9370
9476
  }
9371
9477
  case "remove-account-manager": {
@@ -9373,12 +9479,12 @@ app2.post("/config", async (c) => {
9373
9479
  return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
9374
9480
  }
9375
9481
  const result = clearAccountManager(account.accountDir, phone);
9376
- console.error(`${TAG25} config action=remove-account-manager phone=${phone} ok=${result.ok}`);
9482
+ console.error(`${TAG26} config action=remove-account-manager phone=${phone} ok=${result.ok}`);
9377
9483
  return c.json(result, result.ok ? 200 : 400);
9378
9484
  }
9379
9485
  case "list-account-managers": {
9380
9486
  const accountManagers = readAccountManagers(account.accountDir);
9381
- console.error(`${TAG25} config action=list-account-managers count=${Object.keys(accountManagers).length}`);
9487
+ console.error(`${TAG26} config action=list-account-managers count=${Object.keys(accountManagers).length}`);
9382
9488
  return c.json({ ok: true, accountManagers });
9383
9489
  }
9384
9490
  case "set-public-agent": {
@@ -9386,13 +9492,13 @@ app2.post("/config", async (c) => {
9386
9492
  return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
9387
9493
  }
9388
9494
  const result = setPublicAgent(account.accountDir, slug);
9389
- console.error(`${TAG25} config action=set-public-agent slug=${slug} ok=${result.ok}`);
9495
+ console.error(`${TAG26} config action=set-public-agent slug=${slug} ok=${result.ok}`);
9390
9496
  return c.json(result, result.ok ? 200 : 400);
9391
9497
  }
9392
9498
  case "get-public-agent": {
9393
9499
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
9394
9500
  const resolved = resolvePublicAgent(account.accountDir, { accountId: targetAccount });
9395
- console.error(`${TAG25} config action=get-public-agent accountId=${targetAccount} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
9501
+ console.error(`${TAG26} config action=get-public-agent accountId=${targetAccount} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
9396
9502
  return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
9397
9503
  }
9398
9504
  case "list-public-agents": {
@@ -9409,26 +9515,26 @@ app2.post("/config", async (c) => {
9409
9515
  const config = JSON.parse(readFileSync14(configPath2, "utf-8"));
9410
9516
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
9411
9517
  } catch {
9412
- console.error(`${TAG25} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
9518
+ console.error(`${TAG26} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
9413
9519
  }
9414
9520
  }
9415
9521
  } catch (err) {
9416
- console.error(`${TAG25} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
9522
+ console.error(`${TAG26} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
9417
9523
  }
9418
9524
  }
9419
- console.error(`${TAG25} config action=list-public-agents count=${agents.length}`);
9525
+ console.error(`${TAG26} config action=list-public-agents count=${agents.length}`);
9420
9526
  return c.json({ ok: true, agents });
9421
9527
  }
9422
9528
  case "schema": {
9423
9529
  const text = serializeWhatsAppSchema();
9424
- console.error(`${TAG25} config action=schema`);
9530
+ console.error(`${TAG26} config action=schema`);
9425
9531
  return c.json({ ok: true, text });
9426
9532
  }
9427
9533
  case "list-groups": {
9428
9534
  const groupAccountId = accountId ?? "default";
9429
9535
  const groupRes = resolveSocket(groupAccountId);
9430
9536
  if (!groupRes.ok) {
9431
- console.error(`${TAG25} config action=list-groups error="${formatSocketResolutionReason(groupRes)}" accountId=${groupAccountId}`);
9537
+ console.error(`${TAG26} config action=list-groups error="${formatSocketResolutionReason(groupRes)}" accountId=${groupAccountId}`);
9432
9538
  return c.json({ ok: false, error: formatSocketResolutionMessage(groupRes, groupAccountId) });
9433
9539
  }
9434
9540
  const sock = groupRes.sock;
@@ -9439,10 +9545,10 @@ app2.post("/config", async (c) => {
9439
9545
  name: g.subject ?? g.id,
9440
9546
  participantCount: Array.isArray(g.participants) ? g.participants.length : 0
9441
9547
  }));
9442
- console.error(`${TAG25} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
9548
+ console.error(`${TAG26} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
9443
9549
  return c.json({ ok: true, groups });
9444
9550
  } catch (err) {
9445
- console.error(`${TAG25} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
9551
+ console.error(`${TAG26} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
9446
9552
  return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
9447
9553
  }
9448
9554
  }
@@ -9452,12 +9558,12 @@ app2.post("/config", async (c) => {
9452
9558
  }
9453
9559
  const result = updateConfig(account.accountDir, fields);
9454
9560
  const fieldNames = Object.keys(fields);
9455
- console.error(`${TAG25} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
9561
+ console.error(`${TAG26} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
9456
9562
  return c.json(result, result.ok ? 200 : 400);
9457
9563
  }
9458
9564
  case "get-config": {
9459
9565
  const waConfig = getConfig(account.accountDir);
9460
- console.error(`${TAG25} config action=get-config`);
9566
+ console.error(`${TAG26} config action=get-config`);
9461
9567
  return c.json({ ok: true, config: waConfig });
9462
9568
  }
9463
9569
  default:
@@ -9467,7 +9573,7 @@ app2.post("/config", async (c) => {
9467
9573
  );
9468
9574
  }
9469
9575
  } catch (err) {
9470
- console.error(`${TAG25} config error: ${String(err)}`);
9576
+ console.error(`${TAG26} config error: ${String(err)}`);
9471
9577
  return c.json({ ok: false, error: String(err) }, 500);
9472
9578
  }
9473
9579
  });
@@ -9488,7 +9594,7 @@ app2.post("/send-document", async (c) => {
9488
9594
  recordRouteDocumentOutbound(to, filePath);
9489
9595
  return c.json({ success: true, messageId: result.messageId });
9490
9596
  } catch (err) {
9491
- console.error(`${TAG25} send-document error: ${String(err)}`);
9597
+ console.error(`${TAG26} send-document error: ${String(err)}`);
9492
9598
  return c.json({ error: String(err) }, 500);
9493
9599
  }
9494
9600
  });
@@ -9533,7 +9639,7 @@ app2.post("/send-admin", async (c) => {
9533
9639
  console.error(`[whatsapp:outbound] op=send-admin-ok via=${via} to=${phone}`);
9534
9640
  return c.json({ success: true, messageId: result.messageId });
9535
9641
  } catch (err) {
9536
- console.error(`${TAG25} send-admin error: ${String(err)}`);
9642
+ console.error(`${TAG26} send-admin error: ${String(err)}`);
9537
9643
  return c.json({ error: String(err) }, 500);
9538
9644
  }
9539
9645
  });
@@ -9592,7 +9698,7 @@ app2.post("/reply", async (c) => {
9592
9698
  console.error(`[whatsapp:observe] op=reply-sent sendId=${sendId} account=${accountId} socket=${res.accountId} waMessageId=${sent.messageId ?? ""}`);
9593
9699
  return c.json({ success: true, messageId: sent.messageId });
9594
9700
  } catch (err) {
9595
- console.error(`${TAG25} reply error: ${String(err)}`);
9701
+ console.error(`${TAG26} reply error: ${String(err)}`);
9596
9702
  return c.json({ error: String(err) }, 500);
9597
9703
  }
9598
9704
  });
@@ -9602,11 +9708,11 @@ app2.get("/activity", (c) => {
9602
9708
  const result = getChannelActivity(accountId);
9603
9709
  const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
9604
9710
  console.error(
9605
- `${TAG25} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
9711
+ `${TAG26} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
9606
9712
  );
9607
9713
  return c.json(result);
9608
9714
  } catch (err) {
9609
- console.error(`${TAG25} activity error: ${String(err)}`);
9715
+ console.error(`${TAG26} activity error: ${String(err)}`);
9610
9716
  return c.json({ error: String(err) }, 500);
9611
9717
  }
9612
9718
  });
@@ -9634,10 +9740,10 @@ app2.get("/conversations", (c) => {
9634
9740
  };
9635
9741
  });
9636
9742
  conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
9637
- console.error(`${TAG25} conversations requested=${requestedAccountId} caller=${callerAccountId ?? "none"} account=${storeAccountId} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${allConversations.size > 0} count=${conversations.length}`);
9743
+ console.error(`${TAG26} conversations requested=${requestedAccountId} caller=${callerAccountId ?? "none"} account=${storeAccountId} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${allConversations.size > 0} count=${conversations.length}`);
9638
9744
  return c.json({ conversations });
9639
9745
  } catch (err) {
9640
- console.error(`${TAG25} conversations error: ${String(err)}`);
9746
+ console.error(`${TAG26} conversations error: ${String(err)}`);
9641
9747
  return c.json({ error: String(err) }, 500);
9642
9748
  }
9643
9749
  });
@@ -9690,10 +9796,10 @@ app2.get("/messages", (c) => {
9690
9796
  ...reactions && reactions.length > 0 ? { reactions } : {}
9691
9797
  };
9692
9798
  });
9693
- console.error(`${TAG25} messages requested=${requestedAccountId} caller=${callerAccountId ?? "none"} account=${storeAccountId} jid=${jid} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${storeMessages.length > 0} limit=${effectiveLimit ?? "all"} returned=${messages.length} withAttachments=${withAttachments}`);
9799
+ console.error(`${TAG26} messages requested=${requestedAccountId} caller=${callerAccountId ?? "none"} account=${storeAccountId} jid=${jid} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${storeMessages.length > 0} limit=${effectiveLimit ?? "all"} returned=${messages.length} withAttachments=${withAttachments}`);
9694
9800
  return c.json({ messages });
9695
9801
  } catch (err) {
9696
- console.error(`${TAG25} messages error: ${String(err)}`);
9802
+ console.error(`${TAG26} messages error: ${String(err)}`);
9697
9803
  return c.json({ error: String(err) }, 500);
9698
9804
  }
9699
9805
  });
@@ -9795,7 +9901,7 @@ app2.get("/conversation-graph-state", async (c) => {
9795
9901
  ms
9796
9902
  });
9797
9903
  } catch (err) {
9798
- console.error(`${TAG25} conversation-graph-state error: ${String(err)}`);
9904
+ console.error(`${TAG26} conversation-graph-state error: ${String(err)}`);
9799
9905
  return c.json({ error: String(err) }, 500);
9800
9906
  }
9801
9907
  });
@@ -9807,12 +9913,12 @@ app2.get("/group-info", async (c) => {
9807
9913
  return c.json({ error: "Missing required parameter: jid" }, 400);
9808
9914
  }
9809
9915
  if (!isGroupJid(jid)) {
9810
- console.error(`${TAG25} group-info error="not a group JID" jid=${jid} account=${accountId}`);
9916
+ console.error(`${TAG26} group-info error="not a group JID" jid=${jid} account=${accountId}`);
9811
9917
  return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
9812
9918
  }
9813
9919
  const res = resolveSocket(accountId);
9814
9920
  if (!res.ok) {
9815
- console.error(`${TAG25} group-info error="${formatSocketResolutionReason(res)}" account=${accountId}`);
9921
+ console.error(`${TAG26} group-info error="${formatSocketResolutionReason(res)}" account=${accountId}`);
9816
9922
  return c.json({ error: formatSocketResolutionMessage(res, accountId) }, 400);
9817
9923
  }
9818
9924
  const sock = res.sock;
@@ -9826,10 +9932,10 @@ app2.get("/group-info", async (c) => {
9826
9932
  participantCount: meta.participants.length,
9827
9933
  participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
9828
9934
  };
9829
- console.error(`${TAG25} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
9935
+ console.error(`${TAG26} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
9830
9936
  return c.json(result);
9831
9937
  } catch (err) {
9832
- console.error(`${TAG25} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
9938
+ console.error(`${TAG26} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
9833
9939
  return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
9834
9940
  }
9835
9941
  });
@@ -10033,12 +10139,12 @@ app3.post("/pages/deploy", pagesDeployBodyLimit, async (c) => {
10033
10139
  console.error(
10034
10140
  `[pages-broker] op=project-ensure pub=${pub} project=${project} existed=${existed} created=${!existed}`
10035
10141
  );
10036
- const started = Date.now();
10142
+ const started2 = Date.now();
10037
10143
  const { url, excluded, uploadDir, uploadDirSource } = await exec.pagesDeploy(dir, project, branch);
10038
10144
  console.error(
10039
10145
  `[pages-broker] op=stage pub=${pub} upload=${uploadDir} uploadFrom=${uploadDirSource} excluded=${excluded.length > 0 ? excluded.join(",") : "none"}`
10040
10146
  );
10041
- console.error(`[pages-broker] op=deploy pub=${pub} ranMs=${Date.now() - started} url=${url}`);
10147
+ console.error(`[pages-broker] op=deploy pub=${pub} ranMs=${Date.now() - started2} url=${url}`);
10042
10148
  const httpStatus = await verifyDeployed(url);
10043
10149
  const verified = httpStatus === 200;
10044
10150
  console.error(
@@ -10697,7 +10803,7 @@ function resolveExposedDirs(schemaText, exposeFolders = []) {
10697
10803
  }
10698
10804
 
10699
10805
  // server/portal-uploads-pull.ts
10700
- var TAG26 = "[portal-pull]";
10806
+ var TAG27 = "[portal-pull]";
10701
10807
  var PORTAL_UPLOADS_PULL_INTERVAL_MS = 6e4;
10702
10808
  var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10703
10809
  function safeSegment(s) {
@@ -10758,17 +10864,17 @@ async function pullAccount(opts) {
10758
10864
  }
10759
10865
  const dest = resolveDestination(accountDir, row, exposed);
10760
10866
  const idField = dest.ok || dest.reason !== "bad-fileid" ? ` fileId=${row.fileId}` : "";
10761
- const head = `${TAG26} op=claim account=${accountId}${idField} bytes=${row.size}`;
10867
+ const head = `${TAG27} op=claim account=${accountId}${idField} bytes=${row.size}`;
10762
10868
  if (!dest.ok) {
10763
10869
  failed++;
10764
10870
  log2(
10765
- `${TAG26} op=route account=${accountId}${idField} target="${row.targetPath}" result=refused reason=${dest.reason}`
10871
+ `${TAG27} op=route account=${accountId}${idField} target="${row.targetPath}" result=refused reason=${dest.reason}`
10766
10872
  );
10767
10873
  log2(`${head} result=${dest.reason}`);
10768
10874
  continue;
10769
10875
  }
10770
10876
  log2(
10771
- `${TAG26} op=route account=${accountId}${idField} target="${row.targetPath}" result=${row.targetPath ? "exposed" : "default"}`
10877
+ `${TAG27} op=route account=${accountId}${idField} target="${row.targetPath}" result=${row.targetPath ? "exposed" : "default"}`
10772
10878
  );
10773
10879
  let bytes;
10774
10880
  try {
@@ -10781,7 +10887,7 @@ async function pullAccount(opts) {
10781
10887
  const finalPath = nextFreePath(dest.final);
10782
10888
  if (finalPath !== dest.final) {
10783
10889
  log2(
10784
- `${TAG26} op=collision account=${accountId}${idField} suffix="${basename4(finalPath)}" result=suffixed`
10890
+ `${TAG27} op=collision account=${accountId}${idField} suffix="${basename4(finalPath)}" result=suffixed`
10785
10891
  );
10786
10892
  }
10787
10893
  const relPath = relative2(resolve13(accountDir), finalPath).split(sep3).join("/");
@@ -10825,7 +10931,7 @@ async function pullAccount(opts) {
10825
10931
  deleteErr = err instanceof Error ? err.message : String(err);
10826
10932
  }
10827
10933
  log2(
10828
- `${TAG26} op=move account=${accountId}${idField} r2Deleted=${r2Deleted}` + (deleteErr ? ` err="${deleteErr}"` : "")
10934
+ `${TAG27} op=move account=${accountId}${idField} r2Deleted=${r2Deleted}` + (deleteErr ? ` err="${deleteErr}"` : "")
10829
10935
  );
10830
10936
  pulled++;
10831
10937
  log2(`${head} result=written`);
@@ -10835,10 +10941,10 @@ async function pullAccount(opts) {
10835
10941
  async function withdrawRow(opts) {
10836
10942
  const { accountDir, accountId, dbName, exposed, row, cf, log: log2 } = opts;
10837
10943
  if (!UUID.test(row.fileId)) {
10838
- log2(`${TAG26} op=delete-propagate account=${accountId} result=bad-fileid`);
10944
+ log2(`${TAG27} op=delete-propagate account=${accountId} result=bad-fileid`);
10839
10945
  return false;
10840
10946
  }
10841
- const head = `${TAG26} op=delete-propagate account=${accountId} fileId=${row.fileId}`;
10947
+ const head = `${TAG27} op=delete-propagate account=${accountId} fileId=${row.fileId}`;
10842
10948
  const segments = row.devicePath.split("/");
10843
10949
  if (!row.devicePath || !segments.every(safeSegment) || !exposedOrOwnUploads(segments, exposed, row.ownerId)) {
10844
10950
  log2(`${head} removed=false result=bad-path`);
@@ -10937,7 +11043,7 @@ async function runPortalUploadsPull(root) {
10937
11043
  await cf.d1Query(portal.portalDbName, PENDING_SELECT)
10938
11044
  );
10939
11045
  if (malformed > 0) {
10940
- console.error(`${TAG26} op=malformed account=${portal.accountId} rows=${malformed}`);
11046
+ console.error(`${TAG27} op=malformed account=${portal.accountId} rows=${malformed}`);
10941
11047
  }
10942
11048
  if (rows.length === 0) continue;
10943
11049
  const accountDir = join14(accountsRoot, portal.accountId);
@@ -10957,12 +11063,12 @@ async function runPortalUploadsPull(root) {
10957
11063
  failedTotal += r.failed;
10958
11064
  withdrawnTotal += r.withdrawn;
10959
11065
  console.error(
10960
- `${TAG26} op=done account=${portal.accountId} pulled=${r.pulled} withdrawn=${r.withdrawn} failed=${r.failed}`
11066
+ `${TAG27} op=done account=${portal.accountId} pulled=${r.pulled} withdrawn=${r.withdrawn} failed=${r.failed}`
10961
11067
  );
10962
11068
  } catch (err) {
10963
11069
  failedTotal++;
10964
11070
  console.error(
10965
- `${TAG26} op=failed account=${portal.accountId} err="${err instanceof Error ? err.message : String(err)}"`
11071
+ `${TAG27} op=failed account=${portal.accountId} err="${err instanceof Error ? err.message : String(err)}"`
10966
11072
  );
10967
11073
  }
10968
11074
  }
@@ -11037,7 +11143,7 @@ function createD1Client(opts) {
11037
11143
  }
11038
11144
 
11039
11145
  // ../plugins/cloudflare/bin/portal-index-push.mjs
11040
- var TAG27 = "[portal-index]";
11146
+ var TAG28 = "[portal-index]";
11041
11147
  function readEnvFile(path3) {
11042
11148
  const out = {};
11043
11149
  if (!existsSync11(path3)) return out;
@@ -11102,17 +11208,17 @@ async function pushAccount(opts) {
11102
11208
  const exposeFolders = Array.isArray(opts.exposeFolders) ? opts.exposeFolders : [];
11103
11209
  const r = resolveExposedDirs(schemaText, exposeFolders);
11104
11210
  log2(
11105
- `${TAG27} op=resolve account=${accountId} schemaPresent=${r.schemaPresent} allowed=${r.allowed.length} domainBuckets=${r.domainBuckets.join(",") || "none"} extraFolders=${exposeFolders.length} exposed=${r.exposed.join(",") || "none"}`
11211
+ `${TAG28} op=resolve account=${accountId} schemaPresent=${r.schemaPresent} allowed=${r.allowed.length} domainBuckets=${r.domainBuckets.join(",") || "none"} extraFolders=${exposeFolders.length} exposed=${r.exposed.join(",") || "none"}`
11106
11212
  );
11107
11213
  for (const c of r.collisions) {
11108
- log2(`${TAG27} op=collision account=${accountId} dir=${c} claimedBy=plugin-owned`);
11214
+ log2(`${TAG28} op=collision account=${accountId} dir=${c} claimedBy=plugin-owned`);
11109
11215
  }
11110
11216
  if (opts.previousExposed) {
11111
11217
  const added = r.exposed.filter((d) => !opts.previousExposed.includes(d));
11112
11218
  const removed = opts.previousExposed.filter((d) => !r.exposed.includes(d));
11113
11219
  if (added.length || removed.length) {
11114
11220
  log2(
11115
- `${TAG27} op=exposed-changed account=${accountId} added=${added.join(",") || "none"} removed=${removed.join(",") || "none"}`
11221
+ `${TAG28} op=exposed-changed account=${accountId} added=${added.join(",") || "none"} removed=${removed.join(",") || "none"}`
11116
11222
  );
11117
11223
  }
11118
11224
  }
@@ -11136,7 +11242,7 @@ async function pushAccount(opts) {
11136
11242
  accountId,
11137
11243
  next
11138
11244
  ]);
11139
- log2(`${TAG27} op=stage-clear account=${accountId} generation=${next} cleared=${orphanCount}`);
11245
+ log2(`${TAG28} op=stage-clear account=${accountId} generation=${next} cleared=${orphanCount}`);
11140
11246
  }
11141
11247
  for (const row of rows) {
11142
11248
  await client.query(
@@ -11144,12 +11250,12 @@ async function pushAccount(opts) {
11144
11250
  [accountId, row.relPath, row.sizeBytes, row.modifiedAt, nowIso, row.isDir ? 1 : 0, next]
11145
11251
  );
11146
11252
  }
11147
- log2(`${TAG27} op=stage account=${accountId} generation=${next} inserted=${rows.length}`);
11253
+ log2(`${TAG28} op=stage account=${accountId} generation=${next} inserted=${rows.length}`);
11148
11254
  await client.query(
11149
11255
  "INSERT INTO directory_state (accountId, currentGeneration) VALUES (?, ?) ON CONFLICT (accountId) DO UPDATE SET currentGeneration = excluded.currentGeneration",
11150
11256
  [accountId, next]
11151
11257
  );
11152
- log2(`${TAG27} op=flip account=${accountId} generation=${next}`);
11258
+ log2(`${TAG28} op=flip account=${accountId} generation=${next}`);
11153
11259
  try {
11154
11260
  await client.query("DELETE FROM directory WHERE accountId = ? AND generation != ?", [
11155
11261
  accountId,
@@ -11157,7 +11263,7 @@ async function pushAccount(opts) {
11157
11263
  ]);
11158
11264
  } catch (err) {
11159
11265
  log2(
11160
- `${TAG27} op=sweep account=${accountId} generation=${next} result=failed err="${err instanceof Error ? err.message : String(err)}"`
11266
+ `${TAG28} op=sweep account=${accountId} generation=${next} result=failed err="${err instanceof Error ? err.message : String(err)}"`
11161
11267
  );
11162
11268
  }
11163
11269
  const check = await client.query(
@@ -11165,7 +11271,7 @@ async function pushAccount(opts) {
11165
11271
  [accountId]
11166
11272
  );
11167
11273
  const after = Number(check[0]?.n ?? -1);
11168
- log2(`${TAG27} op=verify account=${accountId} rowsAfter=${after} expected=${rows.length}`);
11274
+ log2(`${TAG28} op=verify account=${accountId} rowsAfter=${after} expected=${rows.length}`);
11169
11275
  return { exposed: r.exposed, rows: rows.length, schemaPresent: true, generation: next };
11170
11276
  }
11171
11277
  function stateFilePath(platformRoot5) {
@@ -11186,7 +11292,7 @@ function recordSuccess(platformRoot5, accountId, entry) {
11186
11292
  writeFileSync6(path3, JSON.stringify(state, null, 1));
11187
11293
  } catch (err) {
11188
11294
  console.error(
11189
- `${TAG27} op=state-write-failed account=${accountId} path="${path3}" err="${err instanceof Error ? err.message : String(err)}"`
11295
+ `${TAG28} op=state-write-failed account=${accountId} path="${path3}" err="${err instanceof Error ? err.message : String(err)}"`
11190
11296
  );
11191
11297
  }
11192
11298
  }
@@ -11210,7 +11316,7 @@ async function portalAccounts(accountsRoot) {
11210
11316
  const exposeFolders = Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
11211
11317
  out.push({ accountDir, accountId, dbName: cfg.portalDbName, exposeFolders });
11212
11318
  } else {
11213
- console.error(`${TAG27} op=skip account=${accountId} reason=no-portalDbName`);
11319
+ console.error(`${TAG28} op=skip account=${accountId} reason=no-portalDbName`);
11214
11320
  }
11215
11321
  } catch {
11216
11322
  }
@@ -11238,7 +11344,7 @@ function resolveCloudflareCredentials(platformRoot5) {
11238
11344
  async function pushAllAccounts(platformRoot5) {
11239
11345
  const accountsRoot = resolve14(platformRoot5, "..", "data", "accounts");
11240
11346
  const targets = await portalAccounts(accountsRoot);
11241
- console.error(`${TAG27} op=enumerate accountsRoot="${accountsRoot}" accounts=${targets.length}`);
11347
+ console.error(`${TAG28} op=enumerate accountsRoot="${accountsRoot}" accounts=${targets.length}`);
11242
11348
  if (targets.length === 0) return { accounts: 0, pushed: 0, failed: 0 };
11243
11349
  const cred = resolveCloudflareCredentials(platformRoot5);
11244
11350
  if ("error" in cred) {
@@ -11272,11 +11378,11 @@ async function runTargets(platformRoot5, cred, targets) {
11272
11378
  });
11273
11379
  }
11274
11380
  pushed++;
11275
- console.error(`${TAG27} op=done account=${t.accountId} rows=${r.rows}`);
11381
+ console.error(`${TAG28} op=done account=${t.accountId} rows=${r.rows}`);
11276
11382
  } catch (err) {
11277
11383
  failed++;
11278
11384
  console.error(
11279
- `${TAG27} op=failed account=${t.accountId} err="${err instanceof Error ? err.message : String(err)}"`
11385
+ `${TAG28} op=failed account=${t.accountId} err="${err instanceof Error ? err.message : String(err)}"`
11280
11386
  );
11281
11387
  }
11282
11388
  }
@@ -11285,7 +11391,7 @@ async function runTargets(platformRoot5, cred, targets) {
11285
11391
  async function main() {
11286
11392
  const platformRoot5 = process.env.PLATFORM_ROOT;
11287
11393
  if (!platformRoot5) {
11288
- console.error(`${TAG27} op=usage reason=no-platform-root PLATFORM_ROOT is required`);
11394
+ console.error(`${TAG28} op=usage reason=no-platform-root PLATFORM_ROOT is required`);
11289
11395
  process.exit(1);
11290
11396
  }
11291
11397
  if (process.argv.includes("--all-accounts")) {
@@ -11293,7 +11399,7 @@ async function main() {
11293
11399
  const r2 = await pushAllAccounts(platformRoot5);
11294
11400
  if (r2.failed > 0) process.exit(1);
11295
11401
  } catch (err) {
11296
- console.error(`${TAG27} op=skip reason=${err instanceof Error ? err.message : String(err)}`);
11402
+ console.error(`${TAG28} op=skip reason=${err instanceof Error ? err.message : String(err)}`);
11297
11403
  process.exit(1);
11298
11404
  }
11299
11405
  return;
@@ -11302,12 +11408,12 @@ async function main() {
11302
11408
  const accountId = arg("--account");
11303
11409
  const dbName = arg("--db");
11304
11410
  if (!accountDir || !accountId || !dbName) {
11305
- console.error(`${TAG27} op=usage --account-dir <dir> --account <id> --db <name>`);
11411
+ console.error(`${TAG28} op=usage --account-dir <dir> --account <id> --db <name>`);
11306
11412
  process.exit(1);
11307
11413
  }
11308
11414
  const cred = resolveCloudflareCredentials(platformRoot5);
11309
11415
  if ("error" in cred) {
11310
- console.error(`${TAG27} op=skip reason=${cred.error}`);
11416
+ console.error(`${TAG28} op=skip reason=${cred.error}`);
11311
11417
  process.exit(1);
11312
11418
  }
11313
11419
  const r = await runTargets(platformRoot5, cred, [
@@ -13529,7 +13635,7 @@ function resolveOpenVisitorSession(rows, visitorId, agentSlug) {
13529
13635
 
13530
13636
  // server/routes/public-reader.ts
13531
13637
  var app6 = new Hono();
13532
- var TAG28 = "[public-webchat]";
13638
+ var TAG29 = "[public-webchat]";
13533
13639
  function parseAccessSessionId(cookieHeader) {
13534
13640
  if (!cookieHeader) return null;
13535
13641
  const part = cookieHeader.split(";").map((p) => p.trim()).find((p) => p.startsWith("__access_session="));
@@ -13577,7 +13683,7 @@ function enumeratePublicRows() {
13577
13683
  app6.get("/session", (c) => {
13578
13684
  const visitor = resolveVisitor(c);
13579
13685
  if (!visitor) {
13580
- console.error(`${TAG28} op=reader-refused reason=no-anchor path=/session`);
13686
+ console.error(`${TAG29} op=reader-refused reason=no-anchor path=/session`);
13581
13687
  return c.json({ error: "gate-required" }, 401);
13582
13688
  }
13583
13689
  const rows = enumeratePublicRows();
@@ -13596,11 +13702,11 @@ app6.get("/session", (c) => {
13596
13702
  found = effectiveSlug ? resolveOpenVisitorSession(rows, visitor.visitorId, effectiveSlug) : null;
13597
13703
  }
13598
13704
  if (found) {
13599
- console.log(`${TAG28} op=session-resume anchor=${visitor.kind} key=${(found.senderId ?? "").slice(0, 8)} sessionId=${found.sessionId.slice(0, 8)}`);
13705
+ console.log(`${TAG29} op=session-resume anchor=${visitor.kind} key=${(found.senderId ?? "").slice(0, 8)} sessionId=${found.sessionId.slice(0, 8)}`);
13600
13706
  return c.json({ sessionId: found.sessionId, projectDir: found.projectDir, sessionKey: found.senderId });
13601
13707
  }
13602
13708
  const sessionKey = crypto.randomUUID();
13603
- console.log(`${TAG28} op=session-new anchor=${visitor.kind} key=${sessionKey.slice(0, 8)}`);
13709
+ console.log(`${TAG29} op=session-new anchor=${visitor.kind} key=${sessionKey.slice(0, 8)}`);
13604
13710
  return c.json({ sessionId: null, projectDir: null, sessionKey });
13605
13711
  });
13606
13712
  function publicUploadsDir(accountId, sessionId) {
@@ -13629,7 +13735,7 @@ function readFrom2(path3, from) {
13629
13735
  app6.get("/stream", (c) => {
13630
13736
  const visitor = resolveVisitor(c);
13631
13737
  if (!visitor) {
13632
- console.error(`${TAG28} op=reader-refused reason=no-anchor path=/stream`);
13738
+ console.error(`${TAG29} op=reader-refused reason=no-anchor path=/stream`);
13633
13739
  return c.json({ error: "gate-required" }, 401);
13634
13740
  }
13635
13741
  const sessionId = c.req.query("sessionId") ?? "";
@@ -13647,12 +13753,12 @@ app6.get("/stream", (c) => {
13647
13753
  const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
13648
13754
  const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
13649
13755
  if (!(isPublicWebchat && owns)) {
13650
- console.error(`${TAG28} op=reader-refused reason=not-owner anchor=${visitor.kind} sessionId=${sessionId.slice(0, 8)}`);
13756
+ console.error(`${TAG29} op=reader-refused reason=not-owner anchor=${visitor.kind} sessionId=${sessionId.slice(0, 8)}`);
13651
13757
  return c.json({ error: "forbidden" }, 403);
13652
13758
  }
13653
13759
  const senderShort = (meta.senderId ?? "").slice(0, 8);
13654
13760
  const encoder = new TextEncoder();
13655
- console.log(`${TAG28} op=reader-open anchor=${visitor.kind} key=${senderShort} mode=delivered-only sessionId=${sessionId.slice(0, 8)}`);
13761
+ console.log(`${TAG29} op=reader-open anchor=${visitor.kind} key=${senderShort} mode=delivered-only sessionId=${sessionId.slice(0, 8)}`);
13656
13762
  const send = (controller, turn, id) => controller.enqueue(encoder.encode(`id: ${id}
13657
13763
  data: ${JSON.stringify(turn)}
13658
13764
 
@@ -13667,7 +13773,7 @@ data: ${JSON.stringify(turn)}
13667
13773
  const { turns, dropped } = filterDeliveredFrames(lines);
13668
13774
  if (uploadsDir) enrichPublicAttachments(turns, listSessionAttachmentsInDir(uploadsDir), attachmentCursor);
13669
13775
  for (const turn of turns) send(controller, turn, offset);
13670
- if (dropped > 0) console.log(`${TAG28} op=reader-filtered key=${senderShort} dropped=${dropped}`);
13776
+ if (dropped > 0) console.log(`${TAG29} op=reader-filtered key=${senderShort} dropped=${dropped}`);
13671
13777
  };
13672
13778
  try {
13673
13779
  const { buf, end } = readFrom2(jsonlPath, 0);
@@ -13702,7 +13808,7 @@ data: ${JSON.stringify(turn)}
13702
13808
  watcher?.close();
13703
13809
  clearInterval(poll);
13704
13810
  clearInterval(heartbeat);
13705
- console.log(`${TAG28} op=reader-close key=${senderShort}`);
13811
+ console.log(`${TAG29} op=reader-close key=${senderShort}`);
13706
13812
  try {
13707
13813
  controller.close();
13708
13814
  } catch {
@@ -14684,7 +14790,7 @@ app7.get("/", requireAdminSession, async (c) => {
14684
14790
  console.error("[webchat:greeting] op=read-failed reason=no-account-for-session");
14685
14791
  return c.json({ ok: false });
14686
14792
  }
14687
- const started = Date.now();
14793
+ const started2 = Date.now();
14688
14794
  let session;
14689
14795
  try {
14690
14796
  session = getSession();
@@ -14730,7 +14836,7 @@ app7.get("/", requireAdminSession, async (c) => {
14730
14836
  console.error(`[webchat:greeting] op=specialists-read-failed reason=${detail}`);
14731
14837
  }
14732
14838
  console.log(
14733
- `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} specialists=${specialists.length} ms=${Date.now() - started}`
14839
+ `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} specialists=${specialists.length} ms=${Date.now() - started2}`
14734
14840
  );
14735
14841
  return c.json({ ok: true, events, tasks, specialists });
14736
14842
  } catch (err) {
@@ -14809,7 +14915,7 @@ function routeTelegramUpdate(input) {
14809
14915
  }
14810
14916
 
14811
14917
  // server/routes/telegram.ts
14812
- var TAG29 = "[telegram-inbound]";
14918
+ var TAG30 = "[telegram-inbound]";
14813
14919
  function configDirName() {
14814
14920
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
14815
14921
  const brandPath = join27(platformRoot5, "config", "brand.json");
@@ -14830,18 +14936,18 @@ app8.post("/", async (c) => {
14830
14936
  const botParam = c.req.query("bot");
14831
14937
  const botType = botParam === "admin" ? "admin" : botParam === "public" ? "public" : null;
14832
14938
  if (!botType) {
14833
- console.error(`${TAG29} op=reject reason=missing-bot-param`);
14939
+ console.error(`${TAG30} op=reject reason=missing-bot-param`);
14834
14940
  return c.json({ ok: false }, 400);
14835
14941
  }
14836
14942
  const sp = secretPath(botType);
14837
14943
  if (!existsSync21(sp)) {
14838
- console.error(`${TAG29} op=reject reason=no-secret-file botType=${botType}`);
14944
+ console.error(`${TAG30} op=reject reason=no-secret-file botType=${botType}`);
14839
14945
  return c.json({ ok: false }, 401);
14840
14946
  }
14841
14947
  const expected = readFileSync27(sp, "utf-8").trim();
14842
14948
  const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
14843
14949
  if (got !== expected) {
14844
- console.error(`${TAG29} op=reject reason=bad-secret botType=${botType}`);
14950
+ console.error(`${TAG30} op=reject reason=bad-secret botType=${botType}`);
14845
14951
  return c.json({ ok: false }, 401);
14846
14952
  }
14847
14953
  let update;
@@ -14852,40 +14958,40 @@ app8.post("/", async (c) => {
14852
14958
  }
14853
14959
  const account = resolveAccount();
14854
14960
  if (!account) {
14855
- console.error(`${TAG29} op=reject reason=no-account`);
14961
+ console.error(`${TAG30} op=reject reason=no-account`);
14856
14962
  return c.json({ ok: true }, 200);
14857
14963
  }
14858
14964
  const decision = routeTelegramUpdate({ update, botType, config: account.config.telegram ?? {} });
14859
14965
  if (decision.kind === "ignore") {
14860
- console.error(`${TAG29} op=ignore reason=${decision.reason}`);
14966
+ console.error(`${TAG30} op=ignore reason=${decision.reason}`);
14861
14967
  return c.json({ ok: true }, 200);
14862
14968
  }
14863
14969
  if (decision.kind === "denied") {
14864
- console.error(`${TAG29} op=denied reason=${decision.reason} agentType=${decision.agentType}`);
14970
+ console.error(`${TAG30} op=denied reason=${decision.reason} agentType=${decision.agentType}`);
14865
14971
  return c.json({ ok: true }, 200);
14866
14972
  }
14867
14973
  const role = decision.agentType === "admin" ? "admin" : "public";
14868
14974
  const agentSlug = role === "admin" ? "admin" : resolveDefaultAgentSlug(account.accountDir);
14869
14975
  if (!agentSlug) {
14870
- console.error(`${TAG29} op=reject reason=no-default-agent`);
14976
+ console.error(`${TAG30} op=reject reason=no-default-agent`);
14871
14977
  return c.json({ ok: true }, 200);
14872
14978
  }
14873
- console.error(`${TAG29} op=update accountId=${account.accountId} from=${decision.senderId}`);
14979
+ console.error(`${TAG30} op=update accountId=${account.accountId} from=${decision.senderId}`);
14874
14980
  const botToken = botType === "admin" ? account.config.telegram?.adminBotToken : account.config.telegram?.publicBotToken;
14875
14981
  const { senderId, chatId, text } = decision;
14876
14982
  const gateway = getTelegramGateway();
14877
14983
  if (!gateway) {
14878
- console.error(`${TAG29} op=reject reason=gateway-not-ready from=${senderId}`);
14984
+ console.error(`${TAG30} op=reject reason=gateway-not-ready from=${senderId}`);
14879
14985
  return c.json({ ok: true }, 200);
14880
14986
  }
14881
14987
  const reply = async (replyText) => {
14882
14988
  if (!botToken) {
14883
14989
  const reason = account.config.telegram ? "no-bot-token" : "no-telegram-config";
14884
- console.error(`${TAG29} op=reply-dropped reason=${reason} botType=${botType} from=${senderId}`);
14990
+ console.error(`${TAG30} op=reply-dropped reason=${reason} botType=${botType} from=${senderId}`);
14885
14991
  return;
14886
14992
  }
14887
14993
  const sent = await sendTelegramText(botToken, chatId, replyText);
14888
- console.error(`${TAG29} op=reply-sent from=${senderId} ok=${sent.ok}${sent.ok ? "" : ` error=${sent.error}`}`);
14994
+ console.error(`${TAG30} op=reply-sent from=${senderId} ok=${sent.ok}${sent.ok ? "" : ` error=${sent.error}`}`);
14889
14995
  };
14890
14996
  void gateway.handleInbound({
14891
14997
  accountId: account.accountId,
@@ -14903,7 +15009,7 @@ var telegram_default = app8;
14903
15009
  // server/routes/quickbooks.ts
14904
15010
  import { join as join28 } from "path";
14905
15011
  import { existsSync as existsSync22, readFileSync as readFileSync28, writeFileSync as writeFileSync10, mkdirSync as mkdirSync5, rmSync, renameSync as renameSync5 } from "fs";
14906
- var TAG30 = "[quickbooks]";
15012
+ var TAG31 = "[quickbooks]";
14907
15013
  var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
14908
15014
  var STATE_RE = /^[A-Za-z0-9_-]+$/;
14909
15015
  function pendingPath(accountDir, state) {
@@ -14916,14 +15022,14 @@ async function completeConsent(args) {
14916
15022
  const { accountDir, code, realmId } = args;
14917
15023
  const state = args.state;
14918
15024
  if (!state || !STATE_RE.test(state) || !existsSync22(pendingPath(accountDir, state))) {
14919
- console.error(`${TAG30} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
15025
+ console.error(`${TAG31} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
14920
15026
  return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
14921
15027
  }
14922
15028
  const claimFile = `${pendingPath(accountDir, state)}.claimed`;
14923
15029
  try {
14924
15030
  renameSync5(pendingPath(accountDir, state), claimFile);
14925
15031
  } catch {
14926
- console.error(`${TAG30} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
15032
+ console.error(`${TAG31} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
14927
15033
  return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
14928
15034
  }
14929
15035
  try {
@@ -14931,14 +15037,14 @@ async function completeConsent(args) {
14931
15037
  try {
14932
15038
  pending = JSON.parse(readFileSync28(claimFile, "utf-8"));
14933
15039
  } catch {
14934
- console.error(`${TAG30} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
15040
+ console.error(`${TAG31} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
14935
15041
  return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
14936
15042
  }
14937
15043
  if (Date.now() > pending.expiresAt) {
14938
- console.error(`${TAG30} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
15044
+ console.error(`${TAG31} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
14939
15045
  return { ok: false, status: 400, message: "Authorization request expired. Generate a new consent link.", stateValid: false };
14940
15046
  }
14941
- console.error(`${TAG30} op=callback state=${state} stateValid=true realmId=${realmId ?? ""}`);
15047
+ console.error(`${TAG31} op=callback state=${state} stateValid=true realmId=${realmId ?? ""}`);
14942
15048
  if (!code || !realmId) {
14943
15049
  return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
14944
15050
  }
@@ -14962,12 +15068,12 @@ async function completeConsent(args) {
14962
15068
  });
14963
15069
  const text = await res.text();
14964
15070
  if (!res.ok) {
14965
- console.error(`${TAG30} op=token-exchange realmId=${realmId} persisted=false`);
15071
+ console.error(`${TAG31} op=token-exchange realmId=${realmId} persisted=false`);
14966
15072
  return { ok: false, status: 502, message: `Token exchange failed (${res.status}). Generate a new consent link to retry.`, stateValid: true };
14967
15073
  }
14968
15074
  const body = JSON.parse(text);
14969
15075
  if (!body.refresh_token) {
14970
- console.error(`${TAG30} op=token-exchange realmId=${realmId} persisted=false`);
15076
+ console.error(`${TAG31} op=token-exchange realmId=${realmId} persisted=false`);
14971
15077
  return { ok: false, status: 502, message: "Token exchange returned no refresh token.", stateValid: true };
14972
15078
  }
14973
15079
  const now = Date.now();
@@ -14980,7 +15086,7 @@ async function completeConsent(args) {
14980
15086
  mkdirSync5(join28(accountDir, "secrets"), { recursive: true });
14981
15087
  writeFileSync10(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
14982
15088
  const persisted = JSON.parse(readFileSync28(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
14983
- console.error(`${TAG30} op=token-exchange realmId=${realmId} persisted=${persisted}`);
15089
+ console.error(`${TAG31} op=token-exchange realmId=${realmId} persisted=${persisted}`);
14984
15090
  return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
14985
15091
  } finally {
14986
15092
  rmSync(claimFile, { force: true });
@@ -14993,7 +15099,7 @@ var app9 = new Hono();
14993
15099
  app9.get("/callback", async (c) => {
14994
15100
  const account = resolveAccount();
14995
15101
  if (!account) {
14996
- console.error(`${TAG30} op=callback stateValid=false realmId= reason=no-account`);
15102
+ console.error(`${TAG31} op=callback stateValid=false realmId= reason=no-account`);
14997
15103
  return c.html(page("QuickBooks", "This install has no account configured."), 500);
14998
15104
  }
14999
15105
  const result = await completeConsent({
@@ -16769,7 +16875,7 @@ async function purgeAdminConversationJsonls(args) {
16769
16875
 
16770
16876
  // app/lib/admin-conversation-cascade.ts
16771
16877
  async function cascadeAdminConversationDelete(args) {
16772
- const started = Date.now();
16878
+ const started2 = Date.now();
16773
16879
  const fetchImpl = args.fetchImpl ?? fetch;
16774
16880
  const log2 = args.logger ?? ((line) => console.log(line));
16775
16881
  const id82 = args.sessionId.slice(0, 8);
@@ -16820,7 +16926,7 @@ async function cascadeAdminConversationDelete(args) {
16820
16926
  if (!found) {
16821
16927
  return { ok: false, reason: "conversation-not-found" };
16822
16928
  }
16823
- const ms = Date.now() - started;
16929
+ const ms = Date.now() - started2;
16824
16930
  const csv = purged.map((s) => s.slice(0, 8)).join(",");
16825
16931
  log2(`[admin-conversation-delete] sessionId=${id82} claudeSessionIds=${csv} ms=${ms}`);
16826
16932
  return { ok: true, claudeSessionIds: purged, ms };
@@ -17744,7 +17850,7 @@ function resolveTunnelUrl() {
17744
17850
  if (!state) return null;
17745
17851
  return `https://${hostname2}.${state.domain}`;
17746
17852
  }
17747
- var TAG31 = "[claude-session-manager:wrapper]";
17853
+ var TAG32 = "[claude-session-manager:wrapper]";
17748
17854
  async function refuseIfClaudeAuthDead(c, route, sessionId) {
17749
17855
  const auth = await ensureAuth();
17750
17856
  if (auth.status !== "dead" && auth.status !== "missing") return null;
@@ -17762,12 +17868,12 @@ async function performSpawnWithInitialMessage(args) {
17762
17868
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
17763
17869
  const ownerMs = Date.now() - ownerStart;
17764
17870
  const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
17765
- console.log(`${TAG31} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
17871
+ console.log(`${TAG32} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
17766
17872
  const dormantPlugins = computeDormantPlugins(args.senderId);
17767
17873
  const activePlugins = computeActivePlugins(args.senderId);
17768
17874
  const specialistDomains = computeSpecialistDomains(args.senderId);
17769
17875
  const tunnelUrl = resolveTunnelUrl();
17770
- console.log(`${TAG31} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
17876
+ console.log(`${TAG32} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
17771
17877
  const upstreamPayload = JSON.stringify({
17772
17878
  senderId: args.senderId,
17773
17879
  // Task 205 — pass userId through to the manager so it lands as
@@ -17794,24 +17900,24 @@ async function performSpawnWithInitialMessage(args) {
17794
17900
  // unshapely values.
17795
17901
  conversationNodeId: args.conversationNodeId
17796
17902
  });
17797
- console.log(`${TAG31} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
17903
+ console.log(`${TAG32} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
17798
17904
  const forwardStart = Date.now();
17799
17905
  const upstream = await fetch(`${managerBase("claude-session-manager:wrapper")}/public-spawn`, {
17800
17906
  method: "POST",
17801
17907
  headers: { "content-type": "application/json" },
17802
17908
  body: upstreamPayload
17803
17909
  }).catch((err) => {
17804
- console.error(`${TAG31} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
17910
+ console.error(`${TAG32} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
17805
17911
  return null;
17806
17912
  });
17807
17913
  if (!upstream) return {
17808
17914
  response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
17809
17915
  claudeSessionId: null
17810
17916
  };
17811
- console.log(`${TAG31} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
17917
+ console.log(`${TAG32} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
17812
17918
  if (args.initialMessage) {
17813
17919
  const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
17814
- console.log(`${TAG31} initial-message-inlined bytes=${inputBytes}`);
17920
+ console.log(`${TAG32} initial-message-inlined bytes=${inputBytes}`);
17815
17921
  }
17816
17922
  const bodyText = await upstream.text().catch(() => "");
17817
17923
  let claudeSessionId = null;
@@ -17846,7 +17952,7 @@ app20.post("/", async (c) => {
17846
17952
  if (refusal) return refusal;
17847
17953
  const senderId = getAccountIdForSession(cacheKey) ?? "";
17848
17954
  if (!senderId) {
17849
- console.error(`${TAG31} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
17955
+ console.error(`${TAG32} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
17850
17956
  return c.json({ error: "admin-account-not-resolved" }, 500);
17851
17957
  }
17852
17958
  const userId = getUserIdForSession(cacheKey) ?? void 0;
@@ -17855,7 +17961,7 @@ app20.post("/", async (c) => {
17855
17961
  const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
17856
17962
  const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
17857
17963
  const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
17858
- console.log(`${TAG31} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
17964
+ console.log(`${TAG32} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
17859
17965
  const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
17860
17966
  const { response, claudeSessionId } = await performSpawnWithInitialMessage({
17861
17967
  senderId,
@@ -17874,13 +17980,13 @@ app20.post("/", async (c) => {
17874
17980
  claudeSessionId,
17875
17981
  senderId
17876
17982
  );
17877
- console.log(`${TAG31} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
17983
+ console.log(`${TAG32} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
17878
17984
  return response;
17879
17985
  });
17880
17986
  var claude_sessions_default = app20;
17881
17987
 
17882
17988
  // server/routes/admin/log-ingest.ts
17883
- var TAG32 = "[log-ingest]";
17989
+ var TAG33 = "[log-ingest]";
17884
17990
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
17885
17991
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
17886
17992
  var MAX_LINE_BYTES = 4096;
@@ -17891,7 +17997,7 @@ function isLoopbackAddr2(addr) {
17891
17997
  app21.post("/", async (c) => {
17892
17998
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
17893
17999
  if (!isLoopbackAddr2(remoteAddr)) {
17894
- console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
18000
+ console.error(`${TAG33} reject reason=non-loopback remoteAddr=${remoteAddr}`);
17895
18001
  return c.json({ error: "log-ingest-loopback-only" }, 403);
17896
18002
  }
17897
18003
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -17900,7 +18006,7 @@ app21.post("/", async (c) => {
17900
18006
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
17901
18007
  const offender = tokens.find((t) => !isLoopbackAddr2(t));
17902
18008
  if (offender !== void 0) {
17903
- console.error(`${TAG32} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
18009
+ console.error(`${TAG33} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
17904
18010
  return c.json({ error: "log-ingest-loopback-only" }, 403);
17905
18011
  }
17906
18012
  }
@@ -17942,18 +18048,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
17942
18048
  ]);
17943
18049
  var app22 = new Hono();
17944
18050
  app22.post("/", async (c) => {
17945
- const TAG58 = "[admin:events]";
18051
+ const TAG59 = "[admin:events]";
17946
18052
  let body;
17947
18053
  try {
17948
18054
  body = await c.req.json();
17949
18055
  } catch (err) {
17950
18056
  const detail = err instanceof Error ? err.message : String(err);
17951
- console.error(`${TAG58} reject reason=body-not-json detail=${detail}`);
18057
+ console.error(`${TAG59} reject reason=body-not-json detail=${detail}`);
17952
18058
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
17953
18059
  }
17954
18060
  const event = typeof body.event === "string" ? body.event : "";
17955
18061
  if (!ALLOWED_EVENTS.has(event)) {
17956
- console.error(`${TAG58} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
18062
+ console.error(`${TAG59} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
17957
18063
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
17958
18064
  }
17959
18065
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
@@ -20800,7 +20906,7 @@ app24.get("/", requireAdminSession, async (c) => {
20800
20906
  if (labels.includes("FileArtifact")) {
20801
20907
  void reconcileFileIndexDebounced(accountId);
20802
20908
  }
20803
- const started = Date.now();
20909
+ const started2 = Date.now();
20804
20910
  const session = getSession();
20805
20911
  try {
20806
20912
  const res = await hybrid(session, embed, {
@@ -20811,7 +20917,7 @@ app24.get("/", requireAdminSession, async (c) => {
20811
20917
  degradeOnEmbedFailure: true,
20812
20918
  vectorThreshold
20813
20919
  });
20814
- const total = Date.now() - started;
20920
+ const total = Date.now() - started2;
20815
20921
  if (res.embedError) {
20816
20922
  console.error(`[graph-search] embed-unavailable err="${res.embedError}" \u2014 bm25-only`);
20817
20923
  console.error(`[graph-search] embed-degraded query="${q2}" results=${res.results.length}`);
@@ -20895,7 +21001,7 @@ app24.get("/", requireAdminSession, async (c) => {
20895
21001
  threshold: res.threshold
20896
21002
  });
20897
21003
  } catch (err) {
20898
- const elapsed = Date.now() - started;
21004
+ const elapsed = Date.now() - started2;
20899
21005
  const message = err instanceof Error ? err.message : String(err);
20900
21006
  console.error(`[graph-search] neo4j-unreachable query="${q2}" ms=${elapsed} err="${message}"`);
20901
21007
  return c.json({ error: `Graph search unavailable: ${message}` }, 503);
@@ -21212,7 +21318,7 @@ async function handleDefault(c, accountId) {
21212
21318
  );
21213
21319
  }
21214
21320
  }
21215
- const started = Date.now();
21321
+ const started2 = Date.now();
21216
21322
  const session = getSession();
21217
21323
  try {
21218
21324
  const countCypher = includeTrashed ? DEFAULT_COUNT_CYPHER_INCLUDE_TRASHED : DEFAULT_COUNT_CYPHER;
@@ -21231,7 +21337,7 @@ async function handleDefault(c, accountId) {
21231
21337
  const rawEdges = record?.get("edges") ?? [];
21232
21338
  return { overLimit: false, matched, rawNodes, rawEdges };
21233
21339
  });
21234
- const elapsed = Date.now() - started;
21340
+ const elapsed = Date.now() - started2;
21235
21341
  if (result.overLimit) {
21236
21342
  console.error(
21237
21343
  `[graph-page] load rejected reason=ceiling-exceeded account=${accountId} labels=${labels.join(",")} matched=${result.matched} ceiling=${CEILING} ms=${elapsed}`
@@ -21254,7 +21360,7 @@ async function handleDefault(c, accountId) {
21254
21360
  );
21255
21361
  return c.json({ nodes, edges });
21256
21362
  } catch (err) {
21257
- const elapsed = Date.now() - started;
21363
+ const elapsed = Date.now() - started2;
21258
21364
  const message = err instanceof Error ? err.message : String(err);
21259
21365
  console.error(`[graph-page] error stage=fetch reason="${message}" ms=${elapsed}`);
21260
21366
  return c.json({ error: `Graph data unavailable: ${message}` }, 503);
@@ -21269,7 +21375,7 @@ async function handleDefaultTopLevel(c, accountId, flags) {
21269
21375
  const { includeTrashed, includeAgentActions } = flags;
21270
21376
  const labels = [...getTopLevelLabelAllowlist()].filter((l) => !HIDDEN_BY_DEFAULT_LABELS.has(l));
21271
21377
  const agentActionLabels = [...AGENT_ACTION_LABELS];
21272
- const started = Date.now();
21378
+ const started2 = Date.now();
21273
21379
  const session = getSession();
21274
21380
  try {
21275
21381
  const countCypher = includeTrashed ? DEFAULT_COUNT_CYPHER_INCLUDE_TRASHED : DEFAULT_COUNT_CYPHER;
@@ -21290,7 +21396,7 @@ async function handleDefaultTopLevel(c, accountId, flags) {
21290
21396
  const rawEdges = record?.get("edges") ?? [];
21291
21397
  return { total, rawNodes, rawEdges };
21292
21398
  });
21293
- const elapsed = Date.now() - started;
21399
+ const elapsed = Date.now() - started2;
21294
21400
  const warnedClasses = /* @__PURE__ */ new Set();
21295
21401
  const conversationWarnings = { loggedMissingMessageCount: false };
21296
21402
  const nodes = result.rawNodes.map((n) => pruneNode(n, warnedClasses, conversationWarnings));
@@ -21307,7 +21413,7 @@ async function handleDefaultTopLevel(c, accountId, flags) {
21307
21413
  );
21308
21414
  return c.json({ nodes, edges, total: result.total, truncated });
21309
21415
  } catch (err) {
21310
- const elapsed = Date.now() - started;
21416
+ const elapsed = Date.now() - started2;
21311
21417
  const message = err instanceof Error ? err.message : String(err);
21312
21418
  console.error(`[graph-page] error stage=fetch-top-level reason="${message}" ms=${elapsed}`);
21313
21419
  return c.json({ error: `Graph data unavailable: ${message}` }, 503);
@@ -21341,7 +21447,7 @@ async function handleNeighbourhood(c, accountId) {
21341
21447
  const rawLimit = c.req.query("limit");
21342
21448
  const parsedLimit = rawLimit ? parseInt(rawLimit, 10) : NEIGHBOURHOOD_SEARCH_DEFAULT_LIMIT;
21343
21449
  const searchLimit = Number.isFinite(parsedLimit) && parsedLimit > 0 ? Math.min(parsedLimit, NEIGHBOURHOOD_SEARCH_MAX_LIMIT) : NEIGHBOURHOOD_SEARCH_DEFAULT_LIMIT;
21344
- const started = Date.now();
21450
+ const started2 = Date.now();
21345
21451
  const session = getSession();
21346
21452
  try {
21347
21453
  let allowedIds = null;
@@ -21393,7 +21499,7 @@ async function handleNeighbourhood(c, accountId) {
21393
21499
  const record = result.records[0];
21394
21500
  const rawNodes = record?.get("nodes") ?? [];
21395
21501
  const rawEdges = record?.get("edges") ?? [];
21396
- const elapsed = Date.now() - started;
21502
+ const elapsed = Date.now() - started2;
21397
21503
  if (rawNodes.length === 0) {
21398
21504
  console.error(
21399
21505
  `[graph-page] load rejected reason=not-found account=${accountId} elementId=${elementId} ms=${elapsed}`
@@ -21435,7 +21541,7 @@ async function handleNeighbourhood(c, accountId) {
21435
21541
  }
21436
21542
  return c.json({ nodes, edges });
21437
21543
  } catch (err) {
21438
- const elapsed = Date.now() - started;
21544
+ const elapsed = Date.now() - started2;
21439
21545
  const message = err instanceof Error ? err.message : String(err);
21440
21546
  console.error(`[graph-page] error stage=fetch reason="${message}" ms=${elapsed}`);
21441
21547
  return c.json({ error: `Graph data unavailable: ${message}` }, 503);
@@ -21855,7 +21961,7 @@ app26.post("/", requireAdminSession, async (c) => {
21855
21961
  }
21856
21962
  by = body.by;
21857
21963
  }
21858
- const started = Date.now();
21964
+ const started2 = Date.now();
21859
21965
  const session = getSession();
21860
21966
  try {
21861
21967
  const lookup = await session.run(
@@ -21865,7 +21971,7 @@ app26.post("/", requireAdminSession, async (c) => {
21865
21971
  { elementId, accountId }
21866
21972
  );
21867
21973
  if (lookup.records.length === 0) {
21868
- const elapsed2 = Date.now() - started;
21974
+ const elapsed2 = Date.now() - started2;
21869
21975
  console.error(
21870
21976
  `[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels= route=trash result=not-found ms=${elapsed2}`
21871
21977
  );
@@ -21875,7 +21981,7 @@ app26.post("/", requireAdminSession, async (c) => {
21875
21981
  const sessionId = lookup.records[0].get("sessionId");
21876
21982
  if (preflightLabels.includes("AdminConversation")) {
21877
21983
  if (!sessionId) {
21878
- const elapsed3 = Date.now() - started;
21984
+ const elapsed3 = Date.now() - started2;
21879
21985
  console.error(
21880
21986
  `[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels=${preflightLabels.join(",")} route=cascade result=error ms=${elapsed3} err="AdminConversation node has no sessionId"`
21881
21987
  );
@@ -21891,7 +21997,7 @@ app26.post("/", requireAdminSession, async (c) => {
21891
21997
  accountId,
21892
21998
  managerBase: managerBaseUrl
21893
21999
  });
21894
- const elapsed2 = Date.now() - started;
22000
+ const elapsed2 = Date.now() - started2;
21895
22001
  const labelSummary2 = preflightLabels.join(",");
21896
22002
  if (outcome.ok) {
21897
22003
  console.error(
@@ -21968,7 +22074,7 @@ app26.post("/", requireAdminSession, async (c) => {
21968
22074
  elementId,
21969
22075
  by
21970
22076
  });
21971
- const elapsed = Date.now() - started;
22077
+ const elapsed = Date.now() - started2;
21972
22078
  const labelSummary = (result.labels.length > 0 ? result.labels : preflightLabels).join(",");
21973
22079
  console.error(
21974
22080
  `[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels=${labelSummary} route=trash result=ok ms=${elapsed}`
@@ -21982,7 +22088,7 @@ app26.post("/", requireAdminSession, async (c) => {
21982
22088
  };
21983
22089
  return c.json(response);
21984
22090
  } catch (err) {
21985
- const elapsed = Date.now() - started;
22091
+ const elapsed = Date.now() - started2;
21986
22092
  const message = err instanceof Error ? err.message : String(err);
21987
22093
  console.error(
21988
22094
  `[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels= result=error ms=${elapsed} err="${message}"`
@@ -22014,7 +22120,7 @@ app27.post("/", requireAdminSession, async (c) => {
22014
22120
  if (!elementId) {
22015
22121
  return c.json({ error: "elementId required" }, 400);
22016
22122
  }
22017
- const started = Date.now();
22123
+ const started2 = Date.now();
22018
22124
  const session = getSession();
22019
22125
  try {
22020
22126
  const lookup = await session.run(
@@ -22024,7 +22130,7 @@ app27.post("/", requireAdminSession, async (c) => {
22024
22130
  { elementId, accountId }
22025
22131
  );
22026
22132
  if (lookup.records.length === 0) {
22027
- const elapsed2 = Date.now() - started;
22133
+ const elapsed2 = Date.now() - started2;
22028
22134
  console.error(
22029
22135
  `[graph-page] restore account=${accountId} elementId=${elementId} labels= result=not-found ms=${elapsed2}`
22030
22136
  );
@@ -22032,7 +22138,7 @@ app27.post("/", requireAdminSession, async (c) => {
22032
22138
  }
22033
22139
  const preflightLabels = (lookup.records[0].get("labels") ?? []).filter((l) => l !== "Trashed");
22034
22140
  const result = await restoreNode({ session, accountId, elementId });
22035
- const elapsed = Date.now() - started;
22141
+ const elapsed = Date.now() - started2;
22036
22142
  const labelSummary = (result.labels.length > 0 ? result.labels : preflightLabels).join(",");
22037
22143
  console.error(
22038
22144
  `[graph-page] restore account=${accountId} elementId=${elementId} labels=${labelSummary} result=ok ms=${elapsed}`
@@ -22044,7 +22150,7 @@ app27.post("/", requireAdminSession, async (c) => {
22044
22150
  };
22045
22151
  return c.json(response);
22046
22152
  } catch (err) {
22047
- const elapsed = Date.now() - started;
22153
+ const elapsed = Date.now() - started2;
22048
22154
  const message = err instanceof Error ? err.message : String(err);
22049
22155
  if (message.includes("already holds")) {
22050
22156
  console.error(
@@ -22075,7 +22181,7 @@ app28.get("/", requireAdminSession, async (c) => {
22075
22181
  return c.json({ error: "Account not found for session" }, 401);
22076
22182
  }
22077
22183
  const includeAgentActions = c.req.query("includeAgentActions") === "1";
22078
- const started = Date.now();
22184
+ const started2 = Date.now();
22079
22185
  const session = getSession();
22080
22186
  try {
22081
22187
  const allowedSet = new Set(getTopLevelLabelAllowlist());
@@ -22094,14 +22200,14 @@ app28.get("/", requireAdminSession, async (c) => {
22094
22200
  if (b.relDegree !== a.relDegree) return b.relDegree - a.relDegree;
22095
22201
  return a.label.localeCompare(b.label);
22096
22202
  });
22097
- const elapsed = Date.now() - started;
22203
+ const elapsed = Date.now() - started2;
22098
22204
  const summary = labels.map((l) => `${l.label}:${l.nodeCount}:${l.relDegree}`).join(",");
22099
22205
  console.error(
22100
22206
  `[graph-page] labels-in-graph account=${accountId} agentActions=${includeAgentActions} labels=${summary} ms=${elapsed}`
22101
22207
  );
22102
22208
  return c.json({ labels });
22103
22209
  } catch (err) {
22104
- const elapsed = Date.now() - started;
22210
+ const elapsed = Date.now() - started2;
22105
22211
  const message = err instanceof Error ? err.message : String(err);
22106
22212
  console.error(
22107
22213
  `[graph-page] labels-in-graph-rejected account=${accountId} reason="${message}" ms=${elapsed}`
@@ -22145,7 +22251,7 @@ app29.get("/", requireAdminSession, async (c) => {
22145
22251
  console.error('[graph-page] default-view-rejected reason="missing account or user context"');
22146
22252
  return c.json({ error: "Account and user context required for default view" }, 401);
22147
22253
  }
22148
- const started = Date.now();
22254
+ const started2 = Date.now();
22149
22255
  const session = getSession();
22150
22256
  try {
22151
22257
  const result = await session.executeRead(async (tx) => {
@@ -22156,13 +22262,13 @@ app29.get("/", requireAdminSession, async (c) => {
22156
22262
  const rawIncludeTrashed = record?.get("includeTrashed");
22157
22263
  const labels = Array.isArray(rawLabels) ? rawLabels : [];
22158
22264
  const includeTrashed = rawIncludeTrashed === true;
22159
- const elapsed = Date.now() - started;
22265
+ const elapsed = Date.now() - started2;
22160
22266
  console.error(
22161
22267
  `[graph-page] default-view-load account=${accountId} labels=${labels.join(",")} includeTrashed=${includeTrashed ? 1 : 0} ms=${elapsed}`
22162
22268
  );
22163
22269
  return c.json({ labels, includeTrashed });
22164
22270
  } catch (err) {
22165
- const elapsed = Date.now() - started;
22271
+ const elapsed = Date.now() - started2;
22166
22272
  const message = err instanceof Error ? err.message : String(err);
22167
22273
  console.error(
22168
22274
  `[graph-page] default-view-rejected op=load account=${accountId} reason="${message}" ms=${elapsed}`
@@ -23126,7 +23232,7 @@ async function sample() {
23126
23232
  }
23127
23233
  var app38 = new Hono();
23128
23234
  app38.get("/", async (c) => {
23129
- const started = Date.now();
23235
+ const started2 = Date.now();
23130
23236
  if (!inflight) {
23131
23237
  inflight = sample().finally(() => {
23132
23238
  inflight = null;
@@ -23134,7 +23240,7 @@ app38.get("/", async (c) => {
23134
23240
  }
23135
23241
  try {
23136
23242
  const snap = await inflight;
23137
- const ms = Date.now() - started;
23243
+ const ms = Date.now() - started2;
23138
23244
  const fmt = (n) => n === null ? "null" : n.toFixed(3);
23139
23245
  console.log(
23140
23246
  `[system-stats] poll cpuPct=${fmt(snap.cpuPct)} memUsedPct=${fmt(snap.memUsedPct)} loadAvg1=${snap.loadAvg1.toFixed(2)} swapUsedPct=${fmt(snap.swapUsedPct)} platform=${snap.platform} ms=${ms}`
@@ -23347,7 +23453,7 @@ function managerLogFollowUrl(sessionId, opts) {
23347
23453
  }
23348
23454
 
23349
23455
  // server/routes/admin/linkedin-ingest.ts
23350
- var TAG33 = "[linkedin-ingest-route]";
23456
+ var TAG34 = "[linkedin-ingest-route]";
23351
23457
  var UUID4 = /^[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}$/;
23352
23458
  var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
23353
23459
  var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
@@ -23451,29 +23557,29 @@ app40.post("/", requireAdminSession, async (c) => {
23451
23557
  try {
23452
23558
  body = await c.req.json();
23453
23559
  } catch {
23454
- console.error(TAG33 + " rejected status=400 reason=schema:body-not-json");
23560
+ console.error(TAG34 + " rejected status=400 reason=schema:body-not-json");
23455
23561
  return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
23456
23562
  }
23457
23563
  const v = validate(body);
23458
23564
  if (!v.ok) {
23459
- console.error(TAG33 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
23565
+ console.error(TAG34 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
23460
23566
  return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
23461
23567
  }
23462
23568
  const envelope = v.envelope;
23463
23569
  const cacheKey = c.var.cacheKey ?? "";
23464
23570
  const senderId = getAccountIdForSession(cacheKey) ?? "";
23465
23571
  if (!senderId) {
23466
- console.error(TAG33 + " rejected status=500 reason=admin-account-not-resolved");
23572
+ console.error(TAG34 + " rejected status=500 reason=admin-account-not-resolved");
23467
23573
  return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
23468
23574
  }
23469
23575
  const payloadBytes = JSON.stringify(envelope).length;
23470
23576
  console.log(
23471
- TAG33 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
23577
+ TAG34 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
23472
23578
  );
23473
23579
  const initialMessage = buildInitialMessage(envelope);
23474
23580
  const spawnStart = Date.now();
23475
23581
  const sessionId = randomUUID13();
23476
- console.log(TAG33 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
23582
+ console.log(TAG34 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
23477
23583
  const spawned = await managerRcSpawn({
23478
23584
  sessionId,
23479
23585
  initialMessage,
@@ -23482,12 +23588,12 @@ app40.post("/", requireAdminSession, async (c) => {
23482
23588
  });
23483
23589
  if ("error" in spawned) {
23484
23590
  console.error(
23485
- TAG33 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
23591
+ TAG34 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
23486
23592
  );
23487
23593
  return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
23488
23594
  }
23489
23595
  console.log(
23490
- TAG33 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
23596
+ TAG34 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
23491
23597
  );
23492
23598
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
23493
23599
  });
@@ -23495,7 +23601,7 @@ var linkedin_ingest_default = app40;
23495
23601
 
23496
23602
  // server/routes/admin/post-turn-context.ts
23497
23603
  import neo4j3 from "neo4j-driver";
23498
- var TAG34 = "[post-turn-context]";
23604
+ var TAG35 = "[post-turn-context]";
23499
23605
  var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
23500
23606
  "embedding",
23501
23607
  "passwordHash",
@@ -23537,7 +23643,7 @@ var app41 = new Hono();
23537
23643
  app41.get("/", async (c) => {
23538
23644
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23539
23645
  if (!isLoopbackAddr3(remoteAddr)) {
23540
- console.error(`${TAG34} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23646
+ console.error(`${TAG35} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23541
23647
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
23542
23648
  }
23543
23649
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -23546,7 +23652,7 @@ app41.get("/", async (c) => {
23546
23652
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
23547
23653
  const offender = tokens.find((t) => !isLoopbackAddr3(t));
23548
23654
  if (offender !== void 0) {
23549
- console.error(`${TAG34} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23655
+ console.error(`${TAG35} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23550
23656
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
23551
23657
  }
23552
23658
  }
@@ -23555,7 +23661,7 @@ app41.get("/", async (c) => {
23555
23661
  if (!sessionId) return c.json({ error: "sessionId required" }, 400);
23556
23662
  if (!accountId) return c.json({ error: "accountId required" }, 400);
23557
23663
  const session = getSession();
23558
- const started = Date.now();
23664
+ const started2 = Date.now();
23559
23665
  try {
23560
23666
  const cypher = `
23561
23667
  MATCH (c:Conversation {sessionId: $sessionId, accountId: $accountId})
@@ -23576,18 +23682,18 @@ app41.get("/", async (c) => {
23576
23682
  sortKey: String(r.get("sortKey") ?? "")
23577
23683
  }));
23578
23684
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
23579
- const total = Date.now() - started;
23685
+ const total = Date.now() - started2;
23580
23686
  console.log(
23581
- `${TAG34} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
23687
+ `${TAG35} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
23582
23688
  );
23583
23689
  return c.json({
23584
23690
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
23585
23691
  });
23586
23692
  } catch (err) {
23587
- const elapsed = Date.now() - started;
23693
+ const elapsed = Date.now() - started2;
23588
23694
  const message = err instanceof Error ? err.message : String(err);
23589
23695
  console.error(
23590
- `${TAG34} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
23696
+ `${TAG35} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
23591
23697
  );
23592
23698
  return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
23593
23699
  } finally {
@@ -23700,7 +23806,7 @@ function formatPreviousContext(writes) {
23700
23806
  }
23701
23807
 
23702
23808
  // server/routes/admin/public-session-context.ts
23703
- var TAG35 = "[public-session-context]";
23809
+ var TAG36 = "[public-session-context]";
23704
23810
  function isLoopbackAddr4(addr) {
23705
23811
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23706
23812
  }
@@ -23708,7 +23814,7 @@ var app42 = new Hono();
23708
23814
  app42.get("/", async (c) => {
23709
23815
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23710
23816
  if (!isLoopbackAddr4(remoteAddr)) {
23711
- console.error(`${TAG35} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23817
+ console.error(`${TAG36} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23712
23818
  return c.json({ error: "public-session-context-loopback-only" }, 403);
23713
23819
  }
23714
23820
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -23717,7 +23823,7 @@ app42.get("/", async (c) => {
23717
23823
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
23718
23824
  const offender = tokens.find((t) => !isLoopbackAddr4(t));
23719
23825
  if (offender !== void 0) {
23720
- console.error(`${TAG35} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23826
+ console.error(`${TAG36} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23721
23827
  return c.json({ error: "public-session-context-loopback-only" }, 403);
23722
23828
  }
23723
23829
  }
@@ -23726,19 +23832,19 @@ app42.get("/", async (c) => {
23726
23832
  if (!sliceToken) return c.json({ error: "sliceToken required" }, 400);
23727
23833
  if (!accountId) return c.json({ error: "accountId required" }, 400);
23728
23834
  const session = getSession();
23729
- const started = Date.now();
23835
+ const started2 = Date.now();
23730
23836
  try {
23731
23837
  const writes = await fetchSliceWrites(session, sliceToken, accountId);
23732
- const total = Date.now() - started;
23838
+ const total = Date.now() - started2;
23733
23839
  console.log(
23734
- `${TAG35} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
23840
+ `${TAG36} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
23735
23841
  );
23736
23842
  return c.json({ writes });
23737
23843
  } catch (err) {
23738
- const elapsed = Date.now() - started;
23844
+ const elapsed = Date.now() - started2;
23739
23845
  const message = err instanceof Error ? err.message : String(err);
23740
23846
  console.error(
23741
- `${TAG35} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
23847
+ `${TAG36} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
23742
23848
  );
23743
23849
  return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
23744
23850
  } finally {
@@ -23757,7 +23863,7 @@ function getWebchatGateway() {
23757
23863
  }
23758
23864
 
23759
23865
  // server/routes/admin/public-session-exit.ts
23760
- var TAG36 = "[public-session-exit-route]";
23866
+ var TAG37 = "[public-session-exit-route]";
23761
23867
  function isLoopbackAddr5(addr) {
23762
23868
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23763
23869
  }
@@ -23765,7 +23871,7 @@ var app43 = new Hono();
23765
23871
  app43.post("/", async (c) => {
23766
23872
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23767
23873
  if (!isLoopbackAddr5(remoteAddr)) {
23768
- console.error(`${TAG36} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23874
+ console.error(`${TAG37} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23769
23875
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
23770
23876
  }
23771
23877
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -23774,7 +23880,7 @@ app43.post("/", async (c) => {
23774
23880
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
23775
23881
  const offender = tokens.find((t) => !isLoopbackAddr5(t));
23776
23882
  if (offender !== void 0) {
23777
- console.error(`${TAG36} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23883
+ console.error(`${TAG37} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23778
23884
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
23779
23885
  }
23780
23886
  }
@@ -23788,7 +23894,7 @@ app43.post("/", async (c) => {
23788
23894
  if (!sessionId) return c.json({ error: "sessionId required" }, 400);
23789
23895
  const gateway = getWebchatGateway();
23790
23896
  if (!gateway) {
23791
- console.error(`${TAG36} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
23897
+ console.error(`${TAG37} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
23792
23898
  return c.json({ error: "webchat-gateway-unset" }, 503);
23793
23899
  }
23794
23900
  gateway.handlePublicSessionExit(sessionId);
@@ -23797,7 +23903,7 @@ app43.post("/", async (c) => {
23797
23903
  var public_session_exit_default = app43;
23798
23904
 
23799
23905
  // server/routes/admin/access-session-evict.ts
23800
- var TAG37 = "[access-session-evict]";
23906
+ var TAG38 = "[access-session-evict]";
23801
23907
  function isLoopbackAddr6(addr) {
23802
23908
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23803
23909
  }
@@ -23805,7 +23911,7 @@ var app44 = new Hono();
23805
23911
  app44.post("/", async (c) => {
23806
23912
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23807
23913
  if (!isLoopbackAddr6(remoteAddr)) {
23808
- console.error(`${TAG37} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23914
+ console.error(`${TAG38} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23809
23915
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
23810
23916
  }
23811
23917
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -23814,7 +23920,7 @@ app44.post("/", async (c) => {
23814
23920
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
23815
23921
  const offender = tokens.find((t) => !isLoopbackAddr6(t));
23816
23922
  if (offender !== void 0) {
23817
- console.error(`${TAG37} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23923
+ console.error(`${TAG38} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23818
23924
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
23819
23925
  }
23820
23926
  }
@@ -23827,13 +23933,13 @@ app44.post("/", async (c) => {
23827
23933
  const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
23828
23934
  if (!grantId) return c.json({ error: "grantId required" }, 400);
23829
23935
  const dropped = evictAccessSessionsByGrant(grantId);
23830
- console.log(`${TAG37} grantId=${grantId} dropped=${dropped}`);
23936
+ console.log(`${TAG38} grantId=${grantId} dropped=${dropped}`);
23831
23937
  return c.json({ ok: true, dropped });
23832
23938
  });
23833
23939
  var access_session_evict_default = app44;
23834
23940
 
23835
23941
  // server/routes/admin/enrol-person.ts
23836
- var TAG38 = "[enrol]";
23942
+ var TAG39 = "[enrol]";
23837
23943
  function isLoopbackAddr7(addr) {
23838
23944
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
23839
23945
  }
@@ -23842,7 +23948,7 @@ var app45 = new Hono();
23842
23948
  app45.post("/", async (c) => {
23843
23949
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
23844
23950
  if (!isLoopbackAddr7(remoteAddr)) {
23845
- console.error(`${TAG38} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23951
+ console.error(`${TAG39} reject reason=non-loopback remoteAddr=${remoteAddr}`);
23846
23952
  return c.json({ error: "enrol-person-loopback-only" }, 403);
23847
23953
  }
23848
23954
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -23851,7 +23957,7 @@ app45.post("/", async (c) => {
23851
23957
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
23852
23958
  const offender = tokens.find((t) => !isLoopbackAddr7(t));
23853
23959
  if (offender !== void 0) {
23854
- console.error(`${TAG38} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23960
+ console.error(`${TAG39} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
23855
23961
  return c.json({ error: "enrol-person-loopback-only" }, 403);
23856
23962
  }
23857
23963
  }
@@ -23876,7 +23982,7 @@ app45.post("/", async (c) => {
23876
23982
  }
23877
23983
  const accountId = process.env.ACCOUNT_ID ?? "";
23878
23984
  if (!accountId) {
23879
- console.error(`${TAG38} op=person result=no-account-id`);
23985
+ console.error(`${TAG39} op=person result=no-account-id`);
23880
23986
  return c.json({ error: "no-account-id" }, 500);
23881
23987
  }
23882
23988
  let personId;
@@ -23884,7 +23990,7 @@ app45.post("/", async (c) => {
23884
23990
  personId = await enrolPerson({ accountId, phone, email, agentSlug });
23885
23991
  } catch (err) {
23886
23992
  console.error(
23887
- `${TAG38} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
23993
+ `${TAG39} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
23888
23994
  );
23889
23995
  return c.json({ error: "enrol-failed" }, 500);
23890
23996
  }
@@ -23894,11 +24000,11 @@ app45.post("/", async (c) => {
23894
24000
  if (g) grant = { grantId: g.grantId, status: g.status, contactValue: g.contactValue };
23895
24001
  } catch (err) {
23896
24002
  console.error(
23897
- `${TAG38} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
24003
+ `${TAG39} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
23898
24004
  );
23899
24005
  }
23900
24006
  console.log(
23901
- `${TAG38} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
24007
+ `${TAG39} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
23902
24008
  );
23903
24009
  return c.json({ personId, grant }, 200);
23904
24010
  });
@@ -24760,7 +24866,7 @@ function toNum(v) {
24760
24866
  }
24761
24867
 
24762
24868
  // server/routes/admin/tasks-list.ts
24763
- var TAG39 = "[task-timer]";
24869
+ var TAG40 = "[task-timer]";
24764
24870
  var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
24765
24871
  var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
24766
24872
  var app50 = new Hono();
@@ -24768,12 +24874,12 @@ app50.get("/", requireAdminSession, async (c) => {
24768
24874
  const cacheKey = c.var.cacheKey;
24769
24875
  const accountId = getAccountIdForSession(cacheKey);
24770
24876
  if (!accountId) {
24771
- console.error(`${TAG39} op=list auth-rejected reason="no account for session"`);
24877
+ console.error(`${TAG40} op=list auth-rejected reason="no account for session"`);
24772
24878
  return c.json({ error: "Account not found for session" }, 401);
24773
24879
  }
24774
24880
  const cacheStart = Date.now();
24775
24881
  const cached3 = await getOrCompute("tasks-list", accountId, () => computeTaskList(accountId));
24776
- console.log(`${TAG39} op=list-cache cache=${cached3.state} account=${accountId} ms=${Date.now() - cacheStart}`);
24882
+ console.log(`${TAG40} op=list-cache cache=${cached3.state} account=${accountId} ms=${Date.now() - cacheStart}`);
24777
24883
  if (cached3.value === null) {
24778
24884
  return c.json({ error: "tasks-list-failed" }, 500);
24779
24885
  }
@@ -24856,15 +24962,15 @@ async function computeTaskList(accountId) {
24856
24962
  const returned = result.records.length;
24857
24963
  if (returned < graphTotal) {
24858
24964
  console.error(
24859
- `${TAG39} op=list row-count-shortfall account=${accountId} returned=${returned} graphTotal=${graphTotal} missing=${graphTotal - returned}`
24965
+ `${TAG40} op=list row-count-shortfall account=${accountId} returned=${returned} graphTotal=${graphTotal} missing=${graphTotal - returned}`
24860
24966
  );
24861
24967
  }
24862
24968
  console.log(
24863
- `${TAG39} op=list account=${accountId} returned=${returned} graphTotal=${graphTotal} open=${open.length} completed=${completed.length} missingTaskId=${missingTaskId} missingCreatedAt=${missingCreatedAt} assigned=${assigned}`
24969
+ `${TAG40} op=list account=${accountId} returned=${returned} graphTotal=${graphTotal} open=${open.length} completed=${completed.length} missingTaskId=${missingTaskId} missingCreatedAt=${missingCreatedAt} assigned=${assigned}`
24864
24970
  );
24865
24971
  return { open, completed };
24866
24972
  } catch (err) {
24867
- console.error(`${TAG39} op=list error="${err instanceof Error ? err.message : String(err)}"`);
24973
+ console.error(`${TAG40} op=list error="${err instanceof Error ? err.message : String(err)}"`);
24868
24974
  return null;
24869
24975
  } finally {
24870
24976
  await session.close();
@@ -24874,7 +24980,7 @@ var tasks_list_default = app50;
24874
24980
 
24875
24981
  // server/routes/admin/task-timer-start.ts
24876
24982
  import { randomUUID as randomUUID14 } from "crypto";
24877
- var TAG40 = "[task-timer]";
24983
+ var TAG41 = "[task-timer]";
24878
24984
  var app51 = new Hono();
24879
24985
  app51.post("/", requireAdminSession, async (c) => {
24880
24986
  const cacheKey = c.var.cacheKey;
@@ -24889,7 +24995,7 @@ app51.post("/", requireAdminSession, async (c) => {
24889
24995
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
24890
24996
  if (!taskId) {
24891
24997
  const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
24892
- console.error(`${TAG40} op=timer-start rejected reason=${reason} account=${accountId}`);
24998
+ console.error(`${TAG41} op=timer-start rejected reason=${reason} account=${accountId}`);
24893
24999
  return c.json({ error: "taskId required" }, 400);
24894
25000
  }
24895
25001
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -24900,7 +25006,7 @@ app51.post("/", requireAdminSession, async (c) => {
24900
25006
  { taskId, accountId }
24901
25007
  );
24902
25008
  if (target.records.length === 0) {
24903
- console.error(`${TAG40} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
25009
+ console.error(`${TAG41} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
24904
25010
  return c.json({ error: "task-not-found" }, 404);
24905
25011
  }
24906
25012
  const open = await session.run(
@@ -24912,7 +25018,7 @@ app51.post("/", requireAdminSession, async (c) => {
24912
25018
  const priorEntryId = open.records[0]?.get("entryId");
24913
25019
  const priorStartedAt = open.records[0]?.get("startedAt");
24914
25020
  if (priorEntryId) {
24915
- console.log(`${TAG40} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
25021
+ console.log(`${TAG41} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
24916
25022
  invalidate("tasks-list", accountId);
24917
25023
  return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
24918
25024
  }
@@ -24923,11 +25029,11 @@ app51.post("/", requireAdminSession, async (c) => {
24923
25029
  CREATE (te)-[:LOGGED_AGAINST]->(t)`,
24924
25030
  { taskId, accountId, entryId, now }
24925
25031
  );
24926
- console.log(`${TAG40} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
25032
+ console.log(`${TAG41} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
24927
25033
  invalidate("tasks-list", accountId);
24928
25034
  return c.json({ ok: true, running: true, entryId, startedAt: now });
24929
25035
  } catch (err) {
24930
- console.error(`${TAG40} op=start error="${err instanceof Error ? err.message : String(err)}"`);
25036
+ console.error(`${TAG41} op=start error="${err instanceof Error ? err.message : String(err)}"`);
24931
25037
  return c.json({ error: "task-timer-start-failed" }, 500);
24932
25038
  } finally {
24933
25039
  await session.close();
@@ -24937,7 +25043,7 @@ var task_timer_start_default = app51;
24937
25043
 
24938
25044
  // server/routes/admin/task-timer-stop.ts
24939
25045
  import neo4j5 from "neo4j-driver";
24940
- var TAG41 = "[task-timer]";
25046
+ var TAG42 = "[task-timer]";
24941
25047
  var app52 = new Hono();
24942
25048
  app52.post("/", requireAdminSession, async (c) => {
24943
25049
  const cacheKey = c.var.cacheKey;
@@ -24952,7 +25058,7 @@ app52.post("/", requireAdminSession, async (c) => {
24952
25058
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
24953
25059
  if (!taskId) {
24954
25060
  const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
24955
- console.error(`${TAG41} op=timer-stop rejected reason=${reason} account=${accountId}`);
25061
+ console.error(`${TAG42} op=timer-stop rejected reason=${reason} account=${accountId}`);
24956
25062
  return c.json({ error: "taskId required" }, 400);
24957
25063
  }
24958
25064
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -24973,7 +25079,7 @@ app52.post("/", requireAdminSession, async (c) => {
24973
25079
  { taskId, accountId }
24974
25080
  );
24975
25081
  const secondsLogged2 = toNum(cur.records[0]?.get("secondsLogged"));
24976
- console.log(`${TAG41} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
25082
+ console.log(`${TAG42} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
24977
25083
  invalidate("tasks-list", accountId);
24978
25084
  return c.json({ ok: true, running: false, seconds: 0, secondsLogged: secondsLogged2 });
24979
25085
  }
@@ -24997,12 +25103,12 @@ app52.post("/", requireAdminSession, async (c) => {
24997
25103
  const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
24998
25104
  const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
24999
25105
  const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
25000
- console.log(`${TAG41} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
25001
- console.log(`${TAG41} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
25106
+ console.log(`${TAG42} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
25107
+ console.log(`${TAG42} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
25002
25108
  invalidate("tasks-list", accountId);
25003
25109
  return c.json({ ok: true, running: false, seconds, secondsLogged });
25004
25110
  } catch (err) {
25005
- console.error(`${TAG41} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
25111
+ console.error(`${TAG42} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
25006
25112
  return c.json({ error: "task-timer-stop-failed" }, 500);
25007
25113
  } finally {
25008
25114
  await session.close();
@@ -25011,7 +25117,7 @@ app52.post("/", requireAdminSession, async (c) => {
25011
25117
  var task_timer_stop_default = app52;
25012
25118
 
25013
25119
  // server/routes/admin/task-complete.ts
25014
- var TAG42 = "[task-timer]";
25120
+ var TAG43 = "[task-timer]";
25015
25121
  var app53 = new Hono();
25016
25122
  app53.post("/", requireAdminSession, async (c) => {
25017
25123
  const cacheKey = c.var.cacheKey;
@@ -25026,7 +25132,7 @@ app53.post("/", requireAdminSession, async (c) => {
25026
25132
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
25027
25133
  if (!taskId) {
25028
25134
  const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
25029
- console.error(`${TAG42} op=complete rejected reason=${reason} account=${accountId}`);
25135
+ console.error(`${TAG43} op=complete rejected reason=${reason} account=${accountId}`);
25030
25136
  return c.json({ error: "taskId required" }, 400);
25031
25137
  }
25032
25138
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -25042,11 +25148,11 @@ app53.post("/", requireAdminSession, async (c) => {
25042
25148
  return c.json({ error: "task-not-found" }, 404);
25043
25149
  }
25044
25150
  const secondsLogged = toNum(result.records[0].get("secondsLogged"));
25045
- console.log(`${TAG42} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
25151
+ console.log(`${TAG43} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
25046
25152
  invalidate("tasks-list", accountId);
25047
25153
  return c.json({ ok: true, status: "completed", secondsLogged });
25048
25154
  } catch (err) {
25049
- console.error(`${TAG42} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
25155
+ console.error(`${TAG43} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
25050
25156
  return c.json({ error: "task-complete-failed" }, 500);
25051
25157
  } finally {
25052
25158
  await session.close();
@@ -25057,7 +25163,7 @@ var task_complete_default = app53;
25057
25163
  // server/routes/admin/task-time-adjust.ts
25058
25164
  import { randomUUID as randomUUID15 } from "crypto";
25059
25165
  import neo4j6 from "neo4j-driver";
25060
- var TAG43 = "[task-time-adjust]";
25166
+ var TAG44 = "[task-time-adjust]";
25061
25167
  var app54 = new Hono();
25062
25168
  app54.post("/", requireAdminSession, async (c) => {
25063
25169
  const cacheKey = c.var.cacheKey;
@@ -25067,23 +25173,23 @@ app54.post("/", requireAdminSession, async (c) => {
25067
25173
  try {
25068
25174
  body = await c.req.json();
25069
25175
  } catch {
25070
- console.error(`${TAG43} op=reject reason=bad-json`);
25176
+ console.error(`${TAG44} op=reject reason=bad-json`);
25071
25177
  return c.json({ error: "invalid-json" }, 400);
25072
25178
  }
25073
25179
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
25074
25180
  if (!taskId) {
25075
25181
  const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
25076
- console.error(`${TAG43} op=time-adjust rejected reason=${reason} account=${accountId}`);
25182
+ console.error(`${TAG44} op=time-adjust rejected reason=${reason} account=${accountId}`);
25077
25183
  return c.json({ error: "taskId required" }, 400);
25078
25184
  }
25079
25185
  const newSeconds = body.newSeconds;
25080
25186
  if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
25081
- console.error(`${TAG43} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
25187
+ console.error(`${TAG44} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
25082
25188
  return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
25083
25189
  }
25084
25190
  const adjustmentId = randomUUID15();
25085
25191
  const now = (/* @__PURE__ */ new Date()).toISOString();
25086
- console.log(`${TAG43} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
25192
+ console.log(`${TAG44} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
25087
25193
  const session = getSession();
25088
25194
  try {
25089
25195
  const guard = await session.run(
@@ -25093,12 +25199,12 @@ app54.post("/", requireAdminSession, async (c) => {
25093
25199
  { taskId, accountId }
25094
25200
  );
25095
25201
  if (guard.records.length === 0) {
25096
- console.error(`${TAG43} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
25202
+ console.error(`${TAG44} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
25097
25203
  return c.json({ error: "task-not-found" }, 404);
25098
25204
  }
25099
25205
  const openCount = toNum(guard.records[0].get("openCount"));
25100
25206
  if (openCount > 0) {
25101
- console.error(`${TAG43} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
25207
+ console.error(`${TAG44} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
25102
25208
  return c.json({ error: "task-timer-running" }, 409);
25103
25209
  }
25104
25210
  const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
@@ -25124,11 +25230,11 @@ app54.post("/", requireAdminSession, async (c) => {
25124
25230
  }
25125
25231
  );
25126
25232
  const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
25127
- console.log(`${TAG43} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
25233
+ console.log(`${TAG44} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
25128
25234
  invalidate("tasks-list", accountId);
25129
25235
  return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
25130
25236
  } catch (err) {
25131
- console.error(`${TAG43} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
25237
+ console.error(`${TAG44} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
25132
25238
  return c.json({ error: "task-time-adjust-failed" }, 500);
25133
25239
  } finally {
25134
25240
  await session.close();
@@ -25221,7 +25327,7 @@ async function resolveAssignableAdmins(accountId, accountsDir = ACCOUNTS_DIR) {
25221
25327
  }
25222
25328
 
25223
25329
  // server/routes/admin/task-assign.ts
25224
- var TAG44 = "[task-assign]";
25330
+ var TAG45 = "[task-assign]";
25225
25331
  var app55 = new Hono();
25226
25332
  app55.post("/", requireAdminSession, async (c) => {
25227
25333
  const cacheKey = c.var.cacheKey;
@@ -25236,7 +25342,7 @@ app55.post("/", requireAdminSession, async (c) => {
25236
25342
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
25237
25343
  if (!taskId) {
25238
25344
  const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
25239
- console.error(`${TAG44} op=assign rejected reason=${reason} account=${accountId}`);
25345
+ console.error(`${TAG45} op=assign rejected reason=${reason} account=${accountId}`);
25240
25346
  return c.json({ error: "taskId required" }, 400);
25241
25347
  }
25242
25348
  const rawAssignee = body.assigneeUserId;
@@ -25248,7 +25354,7 @@ app55.post("/", requireAdminSession, async (c) => {
25248
25354
  const { ids } = await resolveAllowedAssigneeIds(accountId);
25249
25355
  if (!ids.has(assigneeUserId)) {
25250
25356
  console.error(
25251
- `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=not-in-roster`
25357
+ `${TAG45} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=not-in-roster`
25252
25358
  );
25253
25359
  return c.json({ error: "assignee-not-in-roster" }, 403);
25254
25360
  }
@@ -25270,7 +25376,7 @@ app55.post("/", requireAdminSession, async (c) => {
25270
25376
  `MATCH (t:Task {taskId: $taskId, accountId: $accountId}) SET t.updatedAt = $now`,
25271
25377
  { taskId, accountId, now }
25272
25378
  );
25273
- console.log(`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=none assigned=false source=route`);
25379
+ console.log(`${TAG45} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=none assigned=false source=route`);
25274
25380
  invalidate("tasks-list", accountId);
25275
25381
  return c.json({ ok: true, assigneeUserId: null, assigneeName: null });
25276
25382
  }
@@ -25286,7 +25392,7 @@ app55.post("/", requireAdminSession, async (c) => {
25286
25392
  );
25287
25393
  if (set.records.length === 0) {
25288
25394
  console.error(
25289
- `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=no-adminuser-node`
25395
+ `${TAG45} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=no-adminuser-node`
25290
25396
  );
25291
25397
  return c.json({ error: "assignee-no-admin-node" }, 409);
25292
25398
  }
@@ -25294,12 +25400,12 @@ app55.post("/", requireAdminSession, async (c) => {
25294
25400
  const family = set.records[0].get("familyName") ?? null;
25295
25401
  const assigneeName = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
25296
25402
  console.log(
25297
- `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=true source=route`
25403
+ `${TAG45} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=true source=route`
25298
25404
  );
25299
25405
  invalidate("tasks-list", accountId);
25300
25406
  return c.json({ ok: true, assigneeUserId, assigneeName });
25301
25407
  } catch (err) {
25302
- console.error(`${TAG44} op=assign error="${err instanceof Error ? err.message : String(err)}"`);
25408
+ console.error(`${TAG45} op=assign error="${err instanceof Error ? err.message : String(err)}"`);
25303
25409
  return c.json({ error: "task-assign-failed" }, 500);
25304
25410
  } finally {
25305
25411
  await session.close();
@@ -25308,21 +25414,21 @@ app55.post("/", requireAdminSession, async (c) => {
25308
25414
  var task_assign_default = app55;
25309
25415
 
25310
25416
  // server/routes/admin/admin-users-list.ts
25311
- var TAG45 = "[admin-users]";
25417
+ var TAG46 = "[admin-users]";
25312
25418
  var app56 = new Hono();
25313
25419
  app56.get("/", requireAdminSession, async (c) => {
25314
25420
  const cacheKey = c.var.cacheKey;
25315
25421
  const accountId = getAccountIdForSession(cacheKey);
25316
25422
  if (!accountId) {
25317
- console.error(`${TAG45} op=list auth-rejected reason="no account for session"`);
25423
+ console.error(`${TAG46} op=list auth-rejected reason="no account for session"`);
25318
25424
  return c.json({ error: "Account not found for session" }, 401);
25319
25425
  }
25320
25426
  try {
25321
25427
  const users = await resolveAssignableAdmins(accountId);
25322
- console.log(`${TAG45} op=list account=${accountId} count=${users.length}`);
25428
+ console.log(`${TAG46} op=list account=${accountId} count=${users.length}`);
25323
25429
  return c.json({ ok: true, users });
25324
25430
  } catch (err) {
25325
- console.error(`${TAG45} op=list error="${err instanceof Error ? err.message : String(err)}"`);
25431
+ console.error(`${TAG46} op=list error="${err instanceof Error ? err.message : String(err)}"`);
25326
25432
  return c.json({ error: "admin-users-list-failed" }, 500);
25327
25433
  }
25328
25434
  });
@@ -25331,7 +25437,7 @@ var admin_users_list_default = app56;
25331
25437
  // server/routes/admin/activity.ts
25332
25438
  import { readdirSync as readdirSync26 } from "fs";
25333
25439
  var app57 = new Hono();
25334
- var TAG46 = "[activity]";
25440
+ var TAG47 = "[activity]";
25335
25441
  function resolveHouseAccountId(accounts) {
25336
25442
  const houses = accounts.filter((a) => a.config.role === "house");
25337
25443
  if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
@@ -25360,19 +25466,19 @@ app57.get("/", requireAdminSession, async (c) => {
25360
25466
  const house = resolveHouseAccountId(valid);
25361
25467
  const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
25362
25468
  console.log(
25363
- `${TAG46} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
25469
+ `${TAG47} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
25364
25470
  );
25365
25471
  if (!isHouse) {
25366
25472
  const reason = house.accountId === null ? house.reason : "not-house";
25367
25473
  console.error(
25368
- `${TAG46} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
25474
+ `${TAG47} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
25369
25475
  );
25370
25476
  return c.json({ error: "house-only" }, 403);
25371
25477
  }
25372
- console.log(`${TAG46} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
25478
+ console.log(`${TAG47} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
25373
25479
  const onDisk = countAccountDirsOnDisk();
25374
25480
  console.log(
25375
- `${TAG46} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
25481
+ `${TAG47} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
25376
25482
  );
25377
25483
  const start = Date.now();
25378
25484
  let res;
@@ -25388,17 +25494,17 @@ app57.get("/", requireAdminSession, async (c) => {
25388
25494
  });
25389
25495
  } catch (err) {
25390
25496
  console.error(
25391
- `${TAG46} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
25497
+ `${TAG47} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
25392
25498
  );
25393
25499
  return c.json({ error: "manager-unreachable" }, 502);
25394
25500
  }
25395
25501
  if (res.status !== 200) {
25396
- console.error(`${TAG46} op=manager-fail req=${req} reason=status status=${res.status}`);
25502
+ console.error(`${TAG47} op=manager-fail req=${req} reason=status status=${res.status}`);
25397
25503
  return c.json({ error: `manager-status-${res.status}` }, 502);
25398
25504
  }
25399
25505
  const body = await res.json().catch(() => null);
25400
25506
  if (!body || !Array.isArray(body.rows)) {
25401
- console.error(`${TAG46} op=manager-fail req=${req} reason=bad-json`);
25507
+ console.error(`${TAG47} op=manager-fail req=${req} reason=bad-json`);
25402
25508
  return c.json({ error: "manager-bad-json" }, 502);
25403
25509
  }
25404
25510
  const rows = body.rows;
@@ -25409,10 +25515,10 @@ app57.get("/", requireAdminSession, async (c) => {
25409
25515
  const ageNull = rows.filter((r) => r.ageMs === null).length;
25410
25516
  const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
25411
25517
  console.log(
25412
- `${TAG46} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
25518
+ `${TAG47} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
25413
25519
  );
25414
25520
  console.log(
25415
- `${TAG46} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
25521
+ `${TAG47} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
25416
25522
  );
25417
25523
  const names = {};
25418
25524
  await Promise.all(
@@ -25431,7 +25537,7 @@ app57.get("/", requireAdminSession, async (c) => {
25431
25537
  return acc;
25432
25538
  }, {});
25433
25539
  console.log(
25434
- `${TAG46} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
25540
+ `${TAG47} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
25435
25541
  );
25436
25542
  return c.json({
25437
25543
  rows,
@@ -25515,7 +25621,7 @@ app58.route("/activity", activity_default);
25515
25621
  var admin_default = app58;
25516
25622
 
25517
25623
  // server/routes/access/verify-token.ts
25518
- var TAG47 = "[access-verify]";
25624
+ var TAG48 = "[access-verify]";
25519
25625
  var MINT_TAG = "[access-session-mint]";
25520
25626
  var COOKIE_NAME = "__access_session";
25521
25627
  var app59 = new Hono();
@@ -25534,39 +25640,39 @@ app59.post("/", async (c) => {
25534
25640
  }
25535
25641
  const rateMsg = checkAccessRateLimit(ip, agentSlug);
25536
25642
  if (rateMsg) {
25537
- console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
25643
+ console.error(`${TAG48} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
25538
25644
  return c.json({ error: rateMsg }, 429);
25539
25645
  }
25540
25646
  const grant = await findGrantByMagicToken(token);
25541
25647
  if (!grant) {
25542
25648
  recordAccessFailedAttempt(ip, agentSlug);
25543
- console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
25649
+ console.error(`${TAG48} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
25544
25650
  return c.json({ error: "invalid-or-expired-link" }, 401);
25545
25651
  }
25546
25652
  if (grant.agentSlug !== agentSlug) {
25547
25653
  recordAccessFailedAttempt(ip, agentSlug);
25548
25654
  console.error(
25549
- `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
25655
+ `${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
25550
25656
  );
25551
25657
  return c.json({ error: "invalid-or-expired-link" }, 401);
25552
25658
  }
25553
25659
  if (grant.status === "expired" || grant.status === "revoked") {
25554
25660
  recordAccessFailedAttempt(ip, agentSlug);
25555
25661
  console.error(
25556
- `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
25662
+ `${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
25557
25663
  );
25558
25664
  return c.json({ error: "access-no-longer-valid" }, 401);
25559
25665
  }
25560
25666
  if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
25561
25667
  recordAccessFailedAttempt(ip, agentSlug);
25562
25668
  console.error(
25563
- `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
25669
+ `${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
25564
25670
  );
25565
25671
  return c.json({ error: "access-no-longer-valid" }, 401);
25566
25672
  }
25567
25673
  if (!grant.sliceToken) {
25568
25674
  console.error(
25569
- `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
25675
+ `${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
25570
25676
  );
25571
25677
  return c.json({ error: "grant-misconfigured" }, 500);
25572
25678
  }
@@ -25582,12 +25688,12 @@ app59.post("/", async (c) => {
25582
25688
  await consumeMagicTokenAndActivate(grant.grantId);
25583
25689
  } catch (err) {
25584
25690
  console.error(
25585
- `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
25691
+ `${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
25586
25692
  );
25587
25693
  return c.json({ error: "verification-failed" }, 500);
25588
25694
  }
25589
25695
  clearAccessRateLimit(ip, agentSlug);
25590
- console.log(`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
25696
+ console.log(`${TAG48} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
25591
25697
  console.log(
25592
25698
  `${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
25593
25699
  );
@@ -25663,7 +25769,7 @@ async function sendMagicLinkEmail(payload) {
25663
25769
  }
25664
25770
 
25665
25771
  // server/routes/access/request-magic-link.ts
25666
- var TAG48 = "[access-request-link]";
25772
+ var TAG49 = "[access-request-link]";
25667
25773
  var app60 = new Hono();
25668
25774
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
25669
25775
  app60.post("/", async (c) => {
@@ -25680,18 +25786,18 @@ app60.post("/", async (c) => {
25680
25786
  }
25681
25787
  const rateMsg = checkRequestLinkRateLimit(contactValue);
25682
25788
  if (rateMsg) {
25683
- console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=rate-limited`);
25789
+ console.error(`${TAG49} contactValue=${maskContact(contactValue)} result=rate-limited`);
25684
25790
  return c.json({ error: rateMsg }, 429);
25685
25791
  }
25686
25792
  recordRequestLinkAttempt(contactValue);
25687
25793
  const accountId = process.env.ACCOUNT_ID ?? "";
25688
25794
  if (!accountId) {
25689
- console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=no-account-id`);
25795
+ console.error(`${TAG49} contactValue=${maskContact(contactValue)} result=no-account-id`);
25690
25796
  return c.json({ message: VISITOR_MESSAGE }, 200);
25691
25797
  }
25692
25798
  const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
25693
25799
  if (!grant) {
25694
- console.log(`${TAG48} contactValue=${maskContact(contactValue)} result=notfound`);
25800
+ console.log(`${TAG49} contactValue=${maskContact(contactValue)} result=notfound`);
25695
25801
  return c.json({ message: VISITOR_MESSAGE }, 200);
25696
25802
  }
25697
25803
  let token;
@@ -25699,7 +25805,7 @@ app60.post("/", async (c) => {
25699
25805
  token = await generateNewMagicToken(grant.grantId);
25700
25806
  } catch (err) {
25701
25807
  console.error(
25702
- `${TAG48} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
25808
+ `${TAG49} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
25703
25809
  );
25704
25810
  return c.json({ message: VISITOR_MESSAGE }, 200);
25705
25811
  }
@@ -25731,12 +25837,12 @@ app60.post("/", async (c) => {
25731
25837
  });
25732
25838
  if (!sendResult.ok) {
25733
25839
  console.error(
25734
- `${TAG48} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
25840
+ `${TAG49} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
25735
25841
  );
25736
25842
  return c.json({ message: VISITOR_MESSAGE }, 200);
25737
25843
  }
25738
25844
  console.log(
25739
- `${TAG48} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
25845
+ `${TAG49} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
25740
25846
  );
25741
25847
  return c.json({ message: VISITOR_MESSAGE }, 200);
25742
25848
  });
@@ -26822,7 +26928,7 @@ import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
26822
26928
  import { join as join44, resolve as resolve38, sep as sep10 } from "path";
26823
26929
  import { Readable as Readable3 } from "stream";
26824
26930
  var app68 = new Hono();
26825
- var TAG49 = "[portal-fetch]";
26931
+ var TAG50 = "[portal-fetch]";
26826
26932
  async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
26827
26933
  if (!secret || !signature) return false;
26828
26934
  if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return false;
@@ -26877,14 +26983,14 @@ async function readAccountSecret(accountId) {
26877
26983
  try {
26878
26984
  text = await readFile9(path3, "utf8");
26879
26985
  } catch {
26880
- console.error(`${TAG49} op=no-secret account="${accountId}" path="${path3}"`);
26986
+ console.error(`${TAG50} op=no-secret account="${accountId}" path="${path3}"`);
26881
26987
  return "";
26882
26988
  }
26883
26989
  for (const line of text.split("\n")) {
26884
26990
  const m = line.match(/^PORTAL_FETCH_SECRET=(.*)$/);
26885
26991
  if (m) return m[1].trim();
26886
26992
  }
26887
- console.error(`${TAG49} op=no-secret account="${accountId}" reason=key-absent path="${path3}"`);
26993
+ console.error(`${TAG50} op=no-secret account="${accountId}" reason=key-absent path="${path3}"`);
26888
26994
  return "";
26889
26995
  }
26890
26996
  function isValidAccountId2(value) {
@@ -26944,16 +27050,16 @@ async function handle(c, headOnly) {
26944
27050
  const sig = c.req.query("sig") ?? "";
26945
27051
  const owner = c.req.query("owner") ?? "";
26946
27052
  console.log(
26947
- `${TAG49} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
27053
+ `${TAG50} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
26948
27054
  );
26949
27055
  if (!isValidAccountId2(accountId)) {
26950
- console.error(`${TAG49} op=denied account=${q(accountId)} reason=account-id`);
27056
+ console.error(`${TAG50} op=denied account=${q(accountId)} reason=account-id`);
26951
27057
  return c.json({ ok: false, error: "denied" }, 401);
26952
27058
  }
26953
27059
  const secret = await readAccountSecret(accountId);
26954
27060
  const verified = owner ? await verifyOwnUploadSignature(secret, accountId, owner, relPath, exp, sig, Date.now()) : await verifySignature(secret, accountId, relPath, exp, sig, Date.now());
26955
27061
  if (!verified) {
26956
- console.error(`${TAG49} op=denied account=${q(accountId)} reason=secret`);
27062
+ console.error(`${TAG50} op=denied account=${q(accountId)} reason=secret`);
26957
27063
  return c.json({ ok: false, error: "denied" }, 401);
26958
27064
  }
26959
27065
  const target = await resolveFetchTarget(
@@ -26963,14 +27069,14 @@ async function handle(c, headOnly) {
26963
27069
  );
26964
27070
  if (!target.ok) {
26965
27071
  const op = target.reason === "enoent" ? "miss" : "denied";
26966
- console.error(`${TAG49} op=${op} account=${accountId} reason=${target.reason}`);
27072
+ console.error(`${TAG50} op=${op} account=${accountId} reason=${target.reason}`);
26967
27073
  return c.json({ ok: false, error: "not found" }, 404);
26968
27074
  }
26969
27075
  if (headOnly) {
26970
- console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
27076
+ console.log(`${TAG50} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
26971
27077
  return c.body(null, 200);
26972
27078
  }
26973
- console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes}`);
27079
+ console.log(`${TAG50} op=served account=${accountId} bytes=${target.sizeBytes}`);
26974
27080
  return new Response(Readable3.toWeb(createReadStream3(target.absolute)), {
26975
27081
  status: 200,
26976
27082
  headers: {
@@ -26989,7 +27095,7 @@ app68.on("HEAD", "/fetch", (c) => handle(c, true));
26989
27095
  var portal_fetch_default = app68;
26990
27096
 
26991
27097
  // app/lib/timeentry-census.ts
26992
- var TAG50 = "[timeentry-census]";
27098
+ var TAG51 = "[timeentry-census]";
26993
27099
  function reconcileTimeEntries(rows, now, horizonMs) {
26994
27100
  const openEntries = rows.openEntries.length;
26995
27101
  let oldestOpenAgeMs = 0;
@@ -27029,12 +27135,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
27029
27135
  sumAdjustments: toNum(r.get("sumAdjustments"))
27030
27136
  }));
27031
27137
  const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
27032
- const line = `${TAG50} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
27138
+ const line = `${TAG51} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
27033
27139
  if (finding.alarm) console.error(`${line} alarm=true`);
27034
27140
  else console.log(line);
27035
27141
  return finding;
27036
27142
  } catch (err) {
27037
- console.error(`${TAG50} error="${err instanceof Error ? err.message : String(err)}"`);
27143
+ console.error(`${TAG51} error="${err instanceof Error ? err.message : String(err)}"`);
27038
27144
  return null;
27039
27145
  }
27040
27146
  }
@@ -27048,13 +27154,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
27048
27154
  try {
27049
27155
  session = openSession();
27050
27156
  } catch (err) {
27051
- console.error(`${TAG50} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
27157
+ console.error(`${TAG51} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
27052
27158
  return;
27053
27159
  }
27054
27160
  try {
27055
27161
  await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
27056
27162
  } catch (err) {
27057
- console.error(`${TAG50} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
27163
+ console.error(`${TAG51} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
27058
27164
  } finally {
27059
27165
  try {
27060
27166
  await session.close();
@@ -27115,7 +27221,7 @@ function formatCensusLine(f) {
27115
27221
  }
27116
27222
 
27117
27223
  // app/lib/ledger-census.ts
27118
- var TAG51 = "[ledger-census]";
27224
+ var TAG52 = "[ledger-census]";
27119
27225
  var DAY_MS = 864e5;
27120
27226
  function countWriteRejects24h(logDir, now) {
27121
27227
  let entries2;
@@ -27191,7 +27297,7 @@ async function runLedgerCensusOnce(session, now) {
27191
27297
  else console.log(line);
27192
27298
  return finding;
27193
27299
  } catch (err) {
27194
- console.error(`${TAG51} error="${err instanceof Error ? err.message : String(err)}"`);
27300
+ console.error(`${TAG52} error="${err instanceof Error ? err.message : String(err)}"`);
27195
27301
  return null;
27196
27302
  }
27197
27303
  }
@@ -27204,7 +27310,7 @@ function startLedgerCensus(openSession, opts = {}) {
27204
27310
  session = openSession();
27205
27311
  } catch (err) {
27206
27312
  console.error(
27207
- `${TAG51} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
27313
+ `${TAG52} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
27208
27314
  );
27209
27315
  return;
27210
27316
  }
@@ -27212,7 +27318,7 @@ function startLedgerCensus(openSession, opts = {}) {
27212
27318
  await runLedgerCensusOnce(session, Date.now());
27213
27319
  } catch (err) {
27214
27320
  console.error(
27215
- `${TAG51} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
27321
+ `${TAG52} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
27216
27322
  );
27217
27323
  } finally {
27218
27324
  try {
@@ -27230,7 +27336,7 @@ function startLedgerCensus(openSession, opts = {}) {
27230
27336
  }
27231
27337
 
27232
27338
  // app/lib/conversation-audit.ts
27233
- var TAG52 = "[conversation-audit]";
27339
+ var TAG53 = "[conversation-audit]";
27234
27340
  async function runConversationAudit() {
27235
27341
  const session = getSession();
27236
27342
  try {
@@ -27267,12 +27373,12 @@ async function runConversationAudit() {
27267
27373
  multiAnchored: Number(multiRec?.get("multiAnchored") ?? 0)
27268
27374
  };
27269
27375
  console.error(
27270
- `${TAG52} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
27376
+ `${TAG53} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
27271
27377
  );
27272
27378
  return result;
27273
27379
  } catch (err) {
27274
27380
  const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
27275
- console.error(`${TAG52} op=failed reason=${reason}`);
27381
+ console.error(`${TAG53} op=failed reason=${reason}`);
27276
27382
  return null;
27277
27383
  } finally {
27278
27384
  await session.close();
@@ -28769,10 +28875,12 @@ var WebchatGateway = class _WebchatGateway {
28769
28875
  resolve: (r) => {
28770
28876
  clearTimeout(timer);
28771
28877
  this.pendingPrompts.delete(k);
28878
+ this.deps.onPointerChange?.(p.key);
28772
28879
  resolve46(r);
28773
28880
  }
28774
28881
  });
28775
28882
  console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
28883
+ this.deps.onPointerChange?.(p.key);
28776
28884
  });
28777
28885
  }
28778
28886
  /** Task 940 — the operator's Allow/Deny answer for an open prompt. Returns
@@ -29147,7 +29255,7 @@ function toolResultText(content) {
29147
29255
  ).join("");
29148
29256
  }
29149
29257
  function startFollower(opts) {
29150
- const abort = new AbortController();
29258
+ const abort2 = new AbortController();
29151
29259
  const { entry, tag } = opts;
29152
29260
  void (async () => {
29153
29261
  try {
@@ -29159,14 +29267,14 @@ function startFollower(opts) {
29159
29267
  for (; ; ) {
29160
29268
  res = await fetch(
29161
29269
  managerLogFollowUrl(entry.sessionId, { boundary: opts.suppressResumeReplay === true }),
29162
- { signal: abort.signal }
29270
+ { signal: abort2.signal }
29163
29271
  );
29164
29272
  console.error(`${tag} follower-connect sessionId=${sid} status=${res.status}`);
29165
29273
  if (res.status === 202) {
29166
29274
  attempt += 1;
29167
29275
  await res.body?.cancel().catch(() => {
29168
29276
  });
29169
- if (abort.signal.aborted) return;
29277
+ if (abort2.signal.aborted) return;
29170
29278
  if (Date.now() >= deadline) {
29171
29279
  console.error(`${tag} follower-give-up sessionId=${sid} reason=pending-timeout attempts=${attempt}`);
29172
29280
  opts.onError?.("follow-pending-timeout");
@@ -29174,7 +29282,7 @@ function startFollower(opts) {
29174
29282
  }
29175
29283
  console.error(`${tag} follower-retry sessionId=${sid} attempt=${attempt} reason=pending`);
29176
29284
  await new Promise((r) => setTimeout(r, retryMs));
29177
- if (abort.signal.aborted) return;
29285
+ if (abort2.signal.aborted) return;
29178
29286
  continue;
29179
29287
  }
29180
29288
  break;
@@ -29194,7 +29302,7 @@ function startFollower(opts) {
29194
29302
  let suppressing = opts.suppressResumeReplay === true;
29195
29303
  let discardedTurns = 0;
29196
29304
  let discardedFileTools = 0;
29197
- while (!abort.signal.aborted) {
29305
+ while (!abort2.signal.aborted) {
29198
29306
  const { value, done } = await reader.read();
29199
29307
  if (done) break;
29200
29308
  buffered += decoder.decode(value, { stream: true });
@@ -29310,14 +29418,14 @@ function startFollower(opts) {
29310
29418
  }
29311
29419
  }
29312
29420
  } catch (err) {
29313
- if (!abort.signal.aborted) {
29421
+ if (!abort2.signal.aborted) {
29314
29422
  opts.onError?.(`follower-error: ${err instanceof Error ? err.message : String(err)}`);
29315
29423
  }
29316
29424
  } finally {
29317
29425
  opts.onClose();
29318
29426
  }
29319
29427
  })();
29320
- return abort;
29428
+ return abort2;
29321
29429
  }
29322
29430
  async function fanOut(subscribers, text, onError, tag) {
29323
29431
  const callbacks = Array.from(subscribers);
@@ -29425,14 +29533,14 @@ function makeFileDelivery(opts) {
29425
29533
  }
29426
29534
 
29427
29535
  // app/lib/webchat/file-delivery.ts
29428
- var TAG53 = "[webchat-adaptor]";
29536
+ var TAG54 = "[webchat-adaptor]";
29429
29537
  function platformRoot2() {
29430
29538
  return process.env.MAXY_PLATFORM_ROOT || "";
29431
29539
  }
29432
29540
  function makeWebchatSendFile(entry) {
29433
29541
  return async (filePath) => {
29434
29542
  if (!entry.accountId) {
29435
- console.error(`${TAG53} file-delivery reject reason=no-account sender=${entry.senderId}`);
29543
+ console.error(`${TAG54} file-delivery reject reason=no-account sender=${entry.senderId}`);
29436
29544
  return { ok: false, error: "no-account" };
29437
29545
  }
29438
29546
  const accountDir = resolve41(platformRoot2(), "..", "data/accounts", entry.accountId);
@@ -29440,14 +29548,14 @@ function makeWebchatSendFile(entry) {
29440
29548
  const resolved = realpathSync9(filePath);
29441
29549
  const accountResolved = realpathSync9(accountDir);
29442
29550
  if (!resolved.startsWith(accountResolved + "/")) {
29443
- console.error(`${TAG53} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
29551
+ console.error(`${TAG54} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
29444
29552
  return { ok: false, error: "outside-account" };
29445
29553
  }
29446
29554
  return { ok: true };
29447
29555
  } catch (err) {
29448
29556
  const code = err.code;
29449
29557
  console.error(
29450
- `${TAG53} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
29558
+ `${TAG54} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
29451
29559
  );
29452
29560
  return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
29453
29561
  }
@@ -29456,7 +29564,7 @@ function makeWebchatSendFile(entry) {
29456
29564
  function makeWebchatFileDelivery(entry) {
29457
29565
  return makeFileDelivery({
29458
29566
  entry,
29459
- tag: TAG53,
29567
+ tag: TAG54,
29460
29568
  channel: "webchat",
29461
29569
  sendFile: makeWebchatSendFile(entry),
29462
29570
  deferUntilVerdict: true
@@ -29518,7 +29626,7 @@ function buildPublicWebchatSpawnRequest(input) {
29518
29626
  }
29519
29627
 
29520
29628
  // app/lib/whatsapp/inbound/file-delivery-bridge.ts
29521
- var TAG54 = "[whatsapp-adaptor]";
29629
+ var TAG55 = "[whatsapp-adaptor]";
29522
29630
  var SEND_USER_FILE2 = "SendUserFile";
29523
29631
  var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
29524
29632
  function platformRoot3() {
@@ -29536,7 +29644,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
29536
29644
  });
29537
29645
  if (result.ok) return { ok: true };
29538
29646
  console.error(
29539
- `${TAG54} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
29647
+ `${TAG55} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
29540
29648
  );
29541
29649
  return { ok: false, error: result.error };
29542
29650
  };
@@ -29544,7 +29652,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
29544
29652
  function makeWhatsAppFileDelivery(entry, maxyAccountId) {
29545
29653
  const shared = makeFileDelivery({
29546
29654
  entry,
29547
- tag: TAG54,
29655
+ tag: TAG55,
29548
29656
  channel: "whatsapp",
29549
29657
  sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
29550
29658
  });
@@ -29579,7 +29687,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
29579
29687
  if (!delivered) {
29580
29688
  const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
29581
29689
  console.error(
29582
- `${TAG54} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
29690
+ `${TAG55} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
29583
29691
  );
29584
29692
  }
29585
29693
  }
@@ -30000,7 +30108,7 @@ function buildTelegramSpawnRequest(input) {
30000
30108
  import { realpathSync as realpathSync10 } from "fs";
30001
30109
  import { readFile as readFile11, stat as stat10 } from "fs/promises";
30002
30110
  import { resolve as resolve42, basename as basename13 } from "path";
30003
- var TAG55 = "[telegram:outbound]";
30111
+ var TAG56 = "[telegram:outbound]";
30004
30112
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
30005
30113
  async function sendTelegramDocument(input) {
30006
30114
  const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
@@ -30017,10 +30125,10 @@ async function sendTelegramDocument(input) {
30017
30125
  } catch (err) {
30018
30126
  const code = err.code;
30019
30127
  if (code === "ENOENT") {
30020
- console.error(`${TAG55} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
30128
+ console.error(`${TAG56} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
30021
30129
  return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
30022
30130
  }
30023
- console.error(`${TAG55} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
30131
+ console.error(`${TAG56} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
30024
30132
  return { ok: false, status: 500, error: String(err) };
30025
30133
  }
30026
30134
  let resolvedPath;
@@ -30029,14 +30137,14 @@ async function sendTelegramDocument(input) {
30029
30137
  } catch (err) {
30030
30138
  const code = err.code;
30031
30139
  if (code === "ENOENT") {
30032
- console.error(`${TAG55} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
30140
+ console.error(`${TAG56} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
30033
30141
  return { ok: false, status: 404, error: `File not found: ${filePath}` };
30034
30142
  }
30035
- console.error(`${TAG55} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
30143
+ console.error(`${TAG56} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
30036
30144
  return { ok: false, status: 500, error: String(err) };
30037
30145
  }
30038
30146
  if (!resolvedPath.startsWith(accountResolved + "/")) {
30039
- console.error(`${TAG55} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
30147
+ console.error(`${TAG56} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
30040
30148
  return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
30041
30149
  }
30042
30150
  const fileStat = await stat10(resolvedPath);
@@ -30069,13 +30177,13 @@ async function sendTelegramDocument(input) {
30069
30177
  error = e instanceof Error ? e.message : String(e);
30070
30178
  }
30071
30179
  console.error(
30072
- `${TAG55} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
30180
+ `${TAG56} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
30073
30181
  );
30074
30182
  return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
30075
30183
  }
30076
30184
 
30077
30185
  // app/lib/telegram/outbound/file-delivery.ts
30078
- var TAG56 = "[telegram:outbound]";
30186
+ var TAG57 = "[telegram:outbound]";
30079
30187
  function platformRoot4() {
30080
30188
  return process.env.MAXY_PLATFORM_ROOT || "";
30081
30189
  }
@@ -30087,11 +30195,11 @@ function makeTelegramSendFile(entry) {
30087
30195
  botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
30088
30196
  }
30089
30197
  if (!botToken) {
30090
- console.error(`${TAG56} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
30198
+ console.error(`${TAG57} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
30091
30199
  return { ok: false, error: "no-bot-token" };
30092
30200
  }
30093
30201
  if (entry.replyTarget == null) {
30094
- console.error(`${TAG56} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
30202
+ console.error(`${TAG57} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
30095
30203
  return { ok: false, error: "no-reply-target" };
30096
30204
  }
30097
30205
  const result = await sendTelegramDocument({
@@ -30108,7 +30216,7 @@ function makeTelegramSendFile(entry) {
30108
30216
  function makeTelegramFileDelivery(entry) {
30109
30217
  return makeFileDelivery({
30110
30218
  entry,
30111
- tag: TAG56,
30219
+ tag: TAG57,
30112
30220
  channel: "telegram",
30113
30221
  sendFile: makeTelegramSendFile(entry)
30114
30222
  });
@@ -30149,7 +30257,7 @@ function startTelegramNativeFileFollower(input) {
30149
30257
 
30150
30258
  // app/lib/channel-pty-bridge/public-session-end-review.ts
30151
30259
  import { randomUUID as randomUUID16 } from "crypto";
30152
- var TAG57 = "[public-session-review]";
30260
+ var TAG58 = "[public-session-review]";
30153
30261
  var CONSUMED_CAP = 500;
30154
30262
  var consumed = /* @__PURE__ */ new Set();
30155
30263
  function consumeOnce(sessionId) {
@@ -30176,7 +30284,7 @@ async function fetchJsonl(sessionId) {
30176
30284
  return await res.text();
30177
30285
  } catch (err) {
30178
30286
  console.error(
30179
- `${TAG57} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
30287
+ `${TAG58} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
30180
30288
  );
30181
30289
  return null;
30182
30290
  }
@@ -30200,7 +30308,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
30200
30308
  const res = await fetch(url);
30201
30309
  if (!res.ok) {
30202
30310
  console.error(
30203
- `${TAG57} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
30311
+ `${TAG58} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
30204
30312
  );
30205
30313
  return [];
30206
30314
  }
@@ -30208,7 +30316,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
30208
30316
  return Array.isArray(body.writes) ? body.writes : [];
30209
30317
  } catch (err) {
30210
30318
  console.error(
30211
- `${TAG57} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
30319
+ `${TAG58} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
30212
30320
  );
30213
30321
  return [];
30214
30322
  }
@@ -30237,7 +30345,7 @@ function composeInitialMessage(input) {
30237
30345
  }
30238
30346
  async function dispatchReviewer(input, initialMessage) {
30239
30347
  const sessionId = randomUUID16();
30240
- console.log(`${TAG57} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
30348
+ console.log(`${TAG58} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
30241
30349
  const spawned = await managerRcSpawn({
30242
30350
  sessionId,
30243
30351
  initialMessage,
@@ -30257,21 +30365,21 @@ async function firePublicSessionEndReview(input) {
30257
30365
  const dispatchedAt = Date.now();
30258
30366
  if (consumed.has(input.sessionId)) {
30259
30367
  console.log(
30260
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
30368
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
30261
30369
  );
30262
30370
  return;
30263
30371
  }
30264
30372
  const jsonl = await fetchJsonl(input.sessionId);
30265
30373
  if (!jsonl) {
30266
30374
  console.log(
30267
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
30375
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
30268
30376
  );
30269
30377
  return;
30270
30378
  }
30271
30379
  const operatorTurns = countOperatorTurns(jsonl);
30272
30380
  if (operatorTurns === 0) {
30273
30381
  console.log(
30274
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
30382
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
30275
30383
  );
30276
30384
  return;
30277
30385
  }
@@ -30285,19 +30393,19 @@ async function firePublicSessionEndReview(input) {
30285
30393
  });
30286
30394
  if (!consumeOnce(input.sessionId)) {
30287
30395
  console.log(
30288
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
30396
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
30289
30397
  );
30290
30398
  return;
30291
30399
  }
30292
30400
  const dispatched = await dispatchReviewer(input, initialMessage);
30293
30401
  if (!dispatched.ok) {
30294
30402
  console.error(
30295
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
30403
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
30296
30404
  );
30297
30405
  return;
30298
30406
  }
30299
30407
  console.log(
30300
- `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
30408
+ `${TAG58} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
30301
30409
  );
30302
30410
  }
30303
30411
 
@@ -30752,6 +30860,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
30752
30860
  console.log(`[alias-domains] reloaded ${updated.size} alias domain(s): ${[...updated].join(", ")}`);
30753
30861
  });
30754
30862
  attachRouteCacheWatchers();
30863
+ startManagerEventsSubscriber();
30755
30864
  function isPublicHost(host) {
30756
30865
  return host.startsWith("public.") || aliasDomains.has(host);
30757
30866
  }
@@ -30959,6 +31068,13 @@ registerLoop({
30959
31068
  });
30960
31069
  console.log("[1789-sequel] op=cluster-complete items=[1835,1836,1837,1839]");
30961
31070
  var webchatGateway = new WebchatGateway({
31071
+ // Task 1997 — a permission prompt opening or closing changes the pointer with
31072
+ // no filesystem event behind it, so it is pushed here. Scoped to the key's own
31073
+ // account; an unresolvable key is skipped rather than broadcast install-wide.
31074
+ onPointerChange: (key) => {
31075
+ const acct = getAccountIdForSession(key);
31076
+ if (acct) notify("webchat-pointer", acct);
31077
+ },
30962
31078
  fetchStandingRules: fetchAccountStandingRules,
30963
31079
  gatewayUrl: webchatGatewayUrl(),
30964
31080
  serverPath: webchatServerPath(),