@rubytech/create-maxy 1.0.801 → 1.0.802

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.
@@ -50,7 +50,7 @@ import {
50
50
  vncLog,
51
51
  waitForExit,
52
52
  writeChromiumWrapper
53
- } from "./chunk-SBHI2NMF.js";
53
+ } from "./chunk-3SCIVS2T.js";
54
54
  import {
55
55
  ACCOUNTS_DIR,
56
56
  GREETING_DIRECTIVE,
@@ -113,7 +113,7 @@ import {
113
113
  verifyAndGetConversationUpdatedAt,
114
114
  verifyConversationOwnership,
115
115
  writeAdminUserAndPerson
116
- } from "./chunk-WHF6YXJ5.js";
116
+ } from "./chunk-5ABJJQ5K.js";
117
117
  import {
118
118
  __commonJS,
119
119
  __toESM
@@ -3552,6 +3552,172 @@ async function sendMediaMessage(sock, to, media, opts) {
3552
3552
  }
3553
3553
  }
3554
3554
 
3555
+ // app/lib/whatsapp/persist-message.ts
3556
+ var TAG7 = "[whatsapp-persist]";
3557
+ var sessionWriteLocks = /* @__PURE__ */ new Map();
3558
+ async function persistWhatsAppMessage(input) {
3559
+ if (!input.body || !input.msgKeyId) return null;
3560
+ const messageId = `whatsapp-live:${input.accountId}:${input.remoteJid}:${input.msgKeyId}`;
3561
+ const senderTelephone = input.fromMe && input.selfPhone ? input.selfPhone : input.senderPhone;
3562
+ const dateSentIso = new Date(input.timestamp * 1e3).toISOString();
3563
+ const scope = deriveScope(input.sessionKey);
3564
+ const { givenName, familyName } = splitName(input.pushName);
3565
+ const prev = sessionWriteLocks.get(input.sessionKey);
3566
+ let release;
3567
+ const mine = new Promise((resolve25) => {
3568
+ release = resolve25;
3569
+ });
3570
+ const chained = (prev ?? Promise.resolve()).then(() => mine);
3571
+ sessionWriteLocks.set(input.sessionKey, chained);
3572
+ await prev;
3573
+ const t0 = Date.now();
3574
+ let session = null;
3575
+ try {
3576
+ session = getSession();
3577
+ const cypher = `
3578
+ MATCH (c:Conversation {sessionKey: $sessionKey})
3579
+ OPTIONAL MATCH (existingS:Person {telephone: $senderTelephone})
3580
+ OPTIONAL MATCH (existingM:Message {messageId: $messageId})
3581
+ WITH c,
3582
+ existingS IS NOT NULL AS senderReused,
3583
+ existingM IS NOT NULL AS messageExisted
3584
+ MERGE (s:Person {telephone: $senderTelephone})
3585
+ ON CREATE SET
3586
+ s.accountId = $accountId,
3587
+ s.givenName = $givenName,
3588
+ s.familyName = $familyName,
3589
+ s.source = 'whatsapp-live',
3590
+ s.scope = $scope,
3591
+ s.createdByAgent = 'whatsapp-live',
3592
+ s.createdBySource = 'whatsapp-live',
3593
+ s.createdAt = datetime()
3594
+ WITH c, senderReused, messageExisted, s
3595
+ MERGE (m:Message {messageId: $messageId})
3596
+ ON CREATE SET
3597
+ m:WhatsAppMessage,
3598
+ m.accountId = $accountId,
3599
+ m.conversationId = c.conversationId,
3600
+ m.source = 'whatsapp',
3601
+ m.createdByAgent = 'whatsapp-live',
3602
+ m.createdBySource = 'whatsapp-live',
3603
+ m.createdAt = datetime(),
3604
+ m.dateSent = datetime($dateSentIso),
3605
+ m.body = $body,
3606
+ m.fromMe = $fromMe,
3607
+ m.senderTelephone = $senderTelephone,
3608
+ m.senderName = $senderName,
3609
+ m.remoteJid = $remoteJid,
3610
+ m.msgKeyId = $msgKeyId,
3611
+ m.quotedId = $quotedId,
3612
+ m.quotedSender = $quotedSender,
3613
+ m.scope = $scope
3614
+ MERGE (m)-[:PART_OF]->(c)
3615
+ MERGE (s)-[sentRel:SENT]->(m)
3616
+ ON CREATE SET
3617
+ sentRel.source = 'whatsapp-live',
3618
+ sentRel.createdAt = datetime(),
3619
+ sentRel.selfSent = $fromMe
3620
+ WITH c, senderReused, messageExisted, m, s
3621
+ OPTIONAL MATCH (prior:Message:WhatsAppMessage)-[:PART_OF]->(c)
3622
+ WHERE prior.dateSent <= datetime($dateSentIso)
3623
+ AND prior.messageId <> $messageId
3624
+ WITH c, senderReused, messageExisted, m, s, prior
3625
+ ORDER BY prior.dateSent DESC, prior.messageId DESC
3626
+ LIMIT 1
3627
+ FOREACH (_ IN CASE WHEN prior IS NULL OR messageExisted THEN [] ELSE [1] END |
3628
+ MERGE (prior)-[nextRel:NEXT]->(m)
3629
+ ON CREATE SET
3630
+ nextRel.source = 'whatsapp-live',
3631
+ nextRel.createdAt = datetime()
3632
+ )
3633
+ RETURN
3634
+ m.messageId AS messageId,
3635
+ messageExisted AS existed,
3636
+ prior.messageId AS prevMessageId,
3637
+ elementId(s) AS senderElementId,
3638
+ 'Person' AS senderKind,
3639
+ senderReused AS senderReused
3640
+ `;
3641
+ const params = {
3642
+ sessionKey: input.sessionKey,
3643
+ messageId,
3644
+ accountId: input.accountId,
3645
+ senderTelephone,
3646
+ senderName: input.pushName ?? null,
3647
+ givenName,
3648
+ familyName,
3649
+ remoteJid: input.remoteJid,
3650
+ msgKeyId: input.msgKeyId,
3651
+ fromMe: input.fromMe,
3652
+ body: input.body,
3653
+ dateSentIso,
3654
+ quotedId: input.quoted?.id ?? null,
3655
+ quotedSender: input.quoted?.sender ?? null,
3656
+ scope
3657
+ };
3658
+ const result = await session.run(cypher, params);
3659
+ const ms = Date.now() - t0;
3660
+ if (result.records.length === 0) {
3661
+ console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.accountId} sessionKey=${input.sessionKey} messageId=${messageId}`);
3662
+ return null;
3663
+ }
3664
+ const rec = result.records[0];
3665
+ const existed = rec.get("existed") === true;
3666
+ const prevMessageId = rec.get("prevMessageId") ?? null;
3667
+ const senderElementId = rec.get("senderElementId");
3668
+ const senderReused = rec.get("senderReused") === true;
3669
+ if (existed) {
3670
+ console.error(`${TAG7} noop reason=existing-message messageId=${messageId}`);
3671
+ return { messageId, created: false, senderElementId };
3672
+ }
3673
+ console.error(
3674
+ `${TAG7} sender-resolved telephone=${senderTelephone} nodeKind=Person elementId=${senderElementId} reused=${senderReused}`
3675
+ );
3676
+ if (prevMessageId) {
3677
+ console.error(`${TAG7} next-merge prior=${prevMessageId} next=${messageId}`);
3678
+ } else {
3679
+ console.error(`${TAG7} next-skip reason=no-prior msgId=${messageId}`);
3680
+ }
3681
+ console.error(
3682
+ `${TAG7} write messageId=${messageId} sessionKey=${input.sessionKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
3683
+ );
3684
+ return { messageId, created: true, senderElementId };
3685
+ } catch (err) {
3686
+ const ms = Date.now() - t0;
3687
+ const reason = sanitizeReason(err);
3688
+ console.error(
3689
+ `${TAG7} FAIL accountId=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
3690
+ );
3691
+ return null;
3692
+ } finally {
3693
+ release();
3694
+ if (sessionWriteLocks.get(input.sessionKey) === chained) {
3695
+ sessionWriteLocks.delete(input.sessionKey);
3696
+ }
3697
+ if (session) await session.close();
3698
+ }
3699
+ }
3700
+ function deriveScope(sessionKey) {
3701
+ const segments = sessionKey.split(":");
3702
+ return segments.length <= 2 ? "admin" : "public";
3703
+ }
3704
+ function splitName(pushName) {
3705
+ if (!pushName) return { givenName: null, familyName: null };
3706
+ const trimmed = pushName.trim();
3707
+ if (!trimmed) return { givenName: null, familyName: null };
3708
+ const firstSpace = trimmed.search(/\s/);
3709
+ if (firstSpace === -1) return { givenName: trimmed, familyName: null };
3710
+ return {
3711
+ givenName: trimmed.slice(0, firstSpace).trim(),
3712
+ familyName: trimmed.slice(firstSpace + 1).trim() || null
3713
+ };
3714
+ }
3715
+ function sanitizeReason(err) {
3716
+ if (!(err instanceof Error)) return String(err).slice(0, 200);
3717
+ const msg = err.message.replace(/bolt:\/\/[^\s)]+/g, "bolt://<redacted>").replace(/\b(neo4j|admin|password)=[^\s)]+/gi, "$1=<redacted>").slice(0, 200);
3718
+ return `${err.name}:${msg}`;
3719
+ }
3720
+
3555
3721
  // app/lib/whatsapp/inbound/media.ts
3556
3722
  import { randomUUID as randomUUID3 } from "crypto";
3557
3723
  import { writeFile, mkdir } from "fs/promises";
@@ -3561,7 +3727,7 @@ import {
3561
3727
  downloadContentFromMessage,
3562
3728
  normalizeMessageContent as normalizeMessageContent2
3563
3729
  } from "@whiskeysockets/baileys";
3564
- var TAG7 = "[whatsapp:media]";
3730
+ var TAG8 = "[whatsapp:media]";
3565
3731
  var MEDIA_DIR = "/tmp/maxy-media";
3566
3732
  function mimeToExt(mimetype) {
3567
3733
  const map = {
@@ -3617,25 +3783,25 @@ async function downloadInboundMedia(msg, sock, opts) {
3617
3783
  }
3618
3784
  );
3619
3785
  if (!buffer || buffer.length === 0) {
3620
- console.error(`${TAG7} primary download returned empty, trying direct fallback`);
3786
+ console.error(`${TAG8} primary download returned empty, trying direct fallback`);
3621
3787
  const downloadable = getDownloadableContent(content);
3622
3788
  if (downloadable) {
3623
3789
  try {
3624
3790
  const stream = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
3625
3791
  buffer = await streamToBuffer(stream);
3626
3792
  } catch (fallbackErr) {
3627
- console.error(`${TAG7} direct download fallback failed: ${String(fallbackErr)}`);
3793
+ console.error(`${TAG8} direct download fallback failed: ${String(fallbackErr)}`);
3628
3794
  }
3629
3795
  }
3630
3796
  }
3631
3797
  if (!buffer || buffer.length === 0) {
3632
- console.error(`${TAG7} download failed: empty buffer for ${mimetype ?? "unknown"}`);
3798
+ console.error(`${TAG8} download failed: empty buffer for ${mimetype ?? "unknown"}`);
3633
3799
  return void 0;
3634
3800
  }
3635
3801
  if (buffer.length > maxBytes) {
3636
3802
  const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
3637
3803
  const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
3638
- console.error(`${TAG7} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
3804
+ console.error(`${TAG8} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
3639
3805
  return void 0;
3640
3806
  }
3641
3807
  await mkdir(MEDIA_DIR, { recursive: true });
@@ -3644,20 +3810,20 @@ async function downloadInboundMedia(msg, sock, opts) {
3644
3810
  const filePath = join4(MEDIA_DIR, filename);
3645
3811
  await writeFile(filePath, buffer);
3646
3812
  const sizeKB = (buffer.length / 1024).toFixed(0);
3647
- console.error(`${TAG7} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
3813
+ console.error(`${TAG8} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
3648
3814
  return {
3649
3815
  path: filePath,
3650
3816
  mimetype: mimetype ?? "application/octet-stream",
3651
3817
  size: buffer.length
3652
3818
  };
3653
3819
  } catch (err) {
3654
- console.error(`${TAG7} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
3820
+ console.error(`${TAG8} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
3655
3821
  return void 0;
3656
3822
  }
3657
3823
  }
3658
3824
 
3659
3825
  // app/lib/whatsapp/inbound/debounce.ts
3660
- var TAG8 = "[whatsapp:debounce]";
3826
+ var TAG9 = "[whatsapp:debounce]";
3661
3827
  var STT_TAG = "[whatsapp:stt-await]";
3662
3828
  function createInboundDebouncer(opts) {
3663
3829
  const { debounceMs, buildKey, onFlush, onError } = opts;
@@ -3688,7 +3854,7 @@ function createInboundDebouncer(opts) {
3688
3854
  pending.delete(key);
3689
3855
  const batchSize = batch.entries.length;
3690
3856
  try {
3691
- console.error(`${TAG8} debounce flush key=${key} batchSize=${batchSize}`);
3857
+ console.error(`${TAG9} debounce flush key=${key} batchSize=${batchSize}`);
3692
3858
  const result = onFlush(batch.entries);
3693
3859
  if (result && typeof result.catch === "function") {
3694
3860
  result.catch(onError);
@@ -3760,7 +3926,7 @@ function createInboundDebouncer(opts) {
3760
3926
  }
3761
3927
 
3762
3928
  // app/lib/whatsapp/opening-hours.ts
3763
- var TAG9 = "[whatsapp:hours]";
3929
+ var TAG10 = "[whatsapp:hours]";
3764
3930
  async function isBusinessOpen(accountId) {
3765
3931
  try {
3766
3932
  const timezone = await resolveTimezone(accountId);
@@ -3778,7 +3944,7 @@ async function isBusinessOpen(accountId) {
3778
3944
  { accountId, dayOfWeek, previousDayOfWeek }
3779
3945
  );
3780
3946
  if (result.records.length === 0) {
3781
- console.error(`${TAG9} [${accountId}] business hours check: no opening hours configured, treating as open`);
3947
+ console.error(`${TAG10} [${accountId}] business hours check: no opening hours configured, treating as open`);
3782
3948
  return { open: true, reason: "no opening hours configured" };
3783
3949
  }
3784
3950
  const specs = result.records.filter((r) => r.get("opens") != null && r.get("closes") != null).map((r) => ({
@@ -3787,7 +3953,7 @@ async function isBusinessOpen(accountId) {
3787
3953
  closes: String(r.get("closes")).trim()
3788
3954
  }));
3789
3955
  if (specs.length === 0) {
3790
- console.error(`${TAG9} [${accountId}] business hours check: no opening hours configured, treating as open`);
3956
+ console.error(`${TAG10} [${accountId}] business hours check: no opening hours configured, treating as open`);
3791
3957
  return { open: true, reason: "no opening hours configured" };
3792
3958
  }
3793
3959
  for (const spec of specs) {
@@ -3797,7 +3963,7 @@ async function isBusinessOpen(accountId) {
3797
3963
  if (spec.opens > spec.closes && currentTime < spec.closes) {
3798
3964
  const hoursStr = `${spec.opens}-${spec.closes} (${spec.day})`;
3799
3965
  console.error(
3800
- `${TAG9} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
3966
+ `${TAG10} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
3801
3967
  );
3802
3968
  return {
3803
3969
  open: true,
@@ -3810,7 +3976,7 @@ async function isBusinessOpen(accountId) {
3810
3976
  } else if (isTimeInRange(currentTime, spec.opens, spec.closes)) {
3811
3977
  const hoursStr = `${spec.opens}-${spec.closes}`;
3812
3978
  console.error(
3813
- `${TAG9} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
3979
+ `${TAG10} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
3814
3980
  );
3815
3981
  return {
3816
3982
  open: true,
@@ -3824,7 +3990,7 @@ async function isBusinessOpen(accountId) {
3824
3990
  const todaySpecs = specs.filter((s) => s.day === dayOfWeek);
3825
3991
  const allHours = todaySpecs.map((s) => `${s.opens}-${s.closes}`).join(", ") || "none today";
3826
3992
  console.error(
3827
- `${TAG9} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
3993
+ `${TAG10} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
3828
3994
  );
3829
3995
  return {
3830
3996
  open: false,
@@ -3838,7 +4004,7 @@ async function isBusinessOpen(accountId) {
3838
4004
  }
3839
4005
  } catch (err) {
3840
4006
  console.error(
3841
- `${TAG9} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
4007
+ `${TAG10} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
3842
4008
  );
3843
4009
  return { open: true, reason: "hours check failed (treating as open)" };
3844
4010
  }
@@ -3884,7 +4050,7 @@ import { execFile } from "child_process";
3884
4050
  import { unlink, stat } from "fs/promises";
3885
4051
  import { promisify } from "util";
3886
4052
  var execFileAsync = promisify(execFile);
3887
- var TAG10 = "[stt]";
4053
+ var TAG11 = "[stt]";
3888
4054
  var WHISPER_BINARY = process.env.WHISPER_BINARY ?? "/opt/whisper.cpp/build/bin/whisper-cli";
3889
4055
  var WHISPER_MODEL = process.env.WHISPER_MODEL ?? "/opt/whisper.cpp/models/ggml-base.bin";
3890
4056
  var WHISPER_TIMEOUT_MS = 20 * 60 * 1e3;
@@ -3895,11 +4061,11 @@ async function transcribe(audioPath, mimetype) {
3895
4061
  const s = await stat(audioPath);
3896
4062
  audioBytes = s.size;
3897
4063
  } catch {
3898
- console.error(`${TAG10} failed: file not readable path=${audioPath}`);
4064
+ console.error(`${TAG11} failed: file not readable path=${audioPath}`);
3899
4065
  return void 0;
3900
4066
  }
3901
4067
  console.error(
3902
- `${TAG10} start provider=whisper-local audio_bytes=${audioBytes} mimetype=${mimetype} path=${audioPath}`
4068
+ `${TAG11} start provider=whisper-local audio_bytes=${audioBytes} mimetype=${mimetype} path=${audioPath}`
3903
4069
  );
3904
4070
  const wavPath = audioPath.replace(/\.[^.]+$/, "") + ".wav";
3905
4071
  try {
@@ -3918,7 +4084,7 @@ async function transcribe(audioPath, mimetype) {
3918
4084
  ], { timeout: 3e4 });
3919
4085
  } catch (err) {
3920
4086
  const reason = err instanceof Error ? err.message : String(err);
3921
- console.error(`${TAG10} failed: ffmpeg conversion error=${reason}`);
4087
+ console.error(`${TAG11} failed: ffmpeg conversion error=${reason}`);
3922
4088
  return void 0;
3923
4089
  }
3924
4090
  try {
@@ -3936,20 +4102,20 @@ async function transcribe(audioPath, mimetype) {
3936
4102
  const text = stdout.trim();
3937
4103
  const durationMs = Date.now() - startMs;
3938
4104
  if (!text) {
3939
- console.error(`${TAG10} failed: whisper returned empty output duration_ms=${durationMs}`);
4105
+ console.error(`${TAG11} failed: whisper returned empty output duration_ms=${durationMs}`);
3940
4106
  return void 0;
3941
4107
  }
3942
4108
  const langMatch = stderr.match(/auto-detected language:\s*(\w+)/);
3943
4109
  const language = langMatch?.[1] ?? "unknown";
3944
4110
  const words = text.split(/\s+/).filter(Boolean).length;
3945
4111
  console.error(
3946
- `${TAG10} done provider=whisper-local duration_ms=${durationMs} words=${words} lang=${language}`
4112
+ `${TAG11} done provider=whisper-local duration_ms=${durationMs} words=${words} lang=${language}`
3947
4113
  );
3948
4114
  return { text, language, durationMs };
3949
4115
  } catch (err) {
3950
4116
  const durationMs = Date.now() - startMs;
3951
4117
  const reason = err instanceof Error ? err.message : String(err);
3952
- console.error(`${TAG10} failed provider=whisper-local duration_ms=${durationMs} error=${reason}`);
4118
+ console.error(`${TAG11} failed provider=whisper-local duration_ms=${durationMs} error=${reason}`);
3953
4119
  return void 0;
3954
4120
  } finally {
3955
4121
  unlink(wavPath).catch(() => {
@@ -3958,7 +4124,7 @@ async function transcribe(audioPath, mimetype) {
3958
4124
  }
3959
4125
 
3960
4126
  // app/lib/whatsapp/manager.ts
3961
- var TAG11 = "[whatsapp:manager]";
4127
+ var TAG12 = "[whatsapp:manager]";
3962
4128
  var MAX_RECONNECT_ATTEMPTS = 10;
3963
4129
  var MESSAGE_STORE_MAX = 500;
3964
4130
  var GROUP_META_TTL = 5 * 60 * 1e3;
@@ -3978,7 +4144,7 @@ function storeMessage(storeKey, entry) {
3978
4144
  if (entries.length > MESSAGE_STORE_MAX) {
3979
4145
  const trimmed = entries.length - MESSAGE_STORE_MAX;
3980
4146
  entries.splice(0, trimmed);
3981
- console.error(`${TAG11} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
4147
+ console.error(`${TAG12} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
3982
4148
  }
3983
4149
  }
3984
4150
  function deriveSessionKey(input) {
@@ -3997,7 +4163,7 @@ function deriveSessionKey(input) {
3997
4163
  }
3998
4164
  async function init(opts) {
3999
4165
  if (initialized) {
4000
- console.error(`${TAG11} already initialized`);
4166
+ console.error(`${TAG12} already initialized`);
4001
4167
  return;
4002
4168
  }
4003
4169
  configDir = opts.configDir;
@@ -4005,20 +4171,20 @@ async function init(opts) {
4005
4171
  loadConfig(opts.accountConfig);
4006
4172
  const accountIds = listCredentialAccountIds(configDir);
4007
4173
  if (accountIds.length === 0) {
4008
- console.error(`${TAG11} init: no stored WhatsApp credentials found`);
4174
+ console.error(`${TAG12} init: no stored WhatsApp credentials found`);
4009
4175
  initialized = true;
4010
4176
  return;
4011
4177
  }
4012
- console.error(`${TAG11} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
4178
+ console.error(`${TAG12} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
4013
4179
  initialized = true;
4014
4180
  for (const accountId of accountIds) {
4015
4181
  const accountCfg = whatsAppConfig.accounts?.[accountId];
4016
4182
  if (accountCfg?.enabled === false) {
4017
- console.error(`${TAG11} skipping disabled account=${accountId}`);
4183
+ console.error(`${TAG12} skipping disabled account=${accountId}`);
4018
4184
  continue;
4019
4185
  }
4020
4186
  startConnection(accountId).catch((err) => {
4021
- console.error(`${TAG11} failed to auto-start account=${accountId}: ${formatError(err)}`);
4187
+ console.error(`${TAG12} failed to auto-start account=${accountId}: ${formatError(err)}`);
4022
4188
  });
4023
4189
  }
4024
4190
  }
@@ -4027,7 +4193,7 @@ async function startConnection(accountId) {
4027
4193
  const authDir = resolveAuthDir(configDir, accountId);
4028
4194
  const hasAuth = await authExists(authDir);
4029
4195
  if (!hasAuth) {
4030
- console.error(`${TAG11} no credentials for account=${accountId}`);
4196
+ console.error(`${TAG12} no credentials for account=${accountId}`);
4031
4197
  return;
4032
4198
  }
4033
4199
  await stopConnection(accountId);
@@ -4063,11 +4229,11 @@ async function stopConnection(accountId) {
4063
4229
  conn.sock.ev.removeAllListeners("creds.update");
4064
4230
  conn.sock.ws?.close?.();
4065
4231
  } catch (err) {
4066
- console.warn(`${TAG11} socket cleanup error during stop account=${accountId}: ${String(err)}`);
4232
+ console.warn(`${TAG12} socket cleanup error during stop account=${accountId}: ${String(err)}`);
4067
4233
  }
4068
4234
  }
4069
4235
  connections.delete(accountId);
4070
- console.error(`${TAG11} stopped account=${accountId}`);
4236
+ console.error(`${TAG12} stopped account=${accountId}`);
4071
4237
  }
4072
4238
  function getStatus() {
4073
4239
  return Array.from(connections.values()).map((conn) => ({
@@ -4108,9 +4274,9 @@ async function registerLoginSocket(accountId, sock, authDir) {
4108
4274
  connections.set(accountId, conn);
4109
4275
  try {
4110
4276
  await sock.sendPresenceUpdate("available");
4111
- console.error(`${TAG11} presence set to available account=${accountId}`);
4277
+ console.error(`${TAG12} presence set to available account=${accountId}`);
4112
4278
  } catch (err) {
4113
- console.error(`${TAG11} presence update failed account=${accountId}: ${String(err)}`);
4279
+ console.error(`${TAG12} presence update failed account=${accountId}: ${String(err)}`);
4114
4280
  }
4115
4281
  await runInitQueries(sock, {
4116
4282
  accountId,
@@ -4121,7 +4287,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
4121
4287
  });
4122
4288
  monitorInbound(conn);
4123
4289
  watchForDisconnect(conn);
4124
- console.error(`${TAG11} registered login socket for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
4290
+ console.error(`${TAG12} registered login socket for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
4125
4291
  }
4126
4292
  function reloadConfig(accountConfig) {
4127
4293
  loadConfig(accountConfig);
@@ -4145,7 +4311,7 @@ async function shutdown() {
4145
4311
  const ids = Array.from(connections.keys());
4146
4312
  await Promise.all(ids.map((id) => stopConnection(id)));
4147
4313
  initialized = false;
4148
- console.error(`${TAG11} shutdown complete`);
4314
+ console.error(`${TAG12} shutdown complete`);
4149
4315
  }
4150
4316
  function loadConfig(accountConfig) {
4151
4317
  try {
@@ -4157,12 +4323,12 @@ function loadConfig(accountConfig) {
4157
4323
  if (parsed.success) {
4158
4324
  whatsAppConfig = parsed.data;
4159
4325
  } else {
4160
- console.error(`${TAG11} config validation failed: ${parsed.error.message}`);
4326
+ console.error(`${TAG12} config validation failed: ${parsed.error.message}`);
4161
4327
  whatsAppConfig = {};
4162
4328
  }
4163
4329
  }
4164
4330
  } catch (err) {
4165
- console.error(`${TAG11} config load error: ${String(err)}`);
4331
+ console.error(`${TAG12} config load error: ${String(err)}`);
4166
4332
  whatsAppConfig = {};
4167
4333
  }
4168
4334
  }
@@ -4173,13 +4339,13 @@ async function connectWithReconnect(conn) {
4173
4339
  let cycleError = null;
4174
4340
  let connectedAt;
4175
4341
  try {
4176
- console.error(`${TAG11} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
4342
+ console.error(`${TAG12} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
4177
4343
  const sock = await createWaSocket({
4178
4344
  authDir: conn.authDir,
4179
4345
  silent: true
4180
4346
  });
4181
4347
  conn.sock = sock;
4182
- console.error(`${TAG11} socket created account=${conn.accountId} \u2014 waiting for connection`);
4348
+ console.error(`${TAG12} socket created account=${conn.accountId} \u2014 waiting for connection`);
4183
4349
  await waitForConnection(sock);
4184
4350
  const selfId = readSelfId(conn.authDir);
4185
4351
  connectedAt = Date.now();
@@ -4189,12 +4355,12 @@ async function connectWithReconnect(conn) {
4189
4355
  conn.lastConnectedAt = connectedAt;
4190
4356
  conn.lastError = void 0;
4191
4357
  conn.lidMapping = sock.signalRepository?.lidMapping ?? null;
4192
- console.error(`${TAG11} connected account=${conn.accountId} phone=${selfId.e164 ?? "unknown"}`);
4358
+ console.error(`${TAG12} connected account=${conn.accountId} phone=${selfId.e164 ?? "unknown"}`);
4193
4359
  try {
4194
4360
  await sock.sendPresenceUpdate("available");
4195
- console.error(`${TAG11} presence set to available account=${conn.accountId}`);
4361
+ console.error(`${TAG12} presence set to available account=${conn.accountId}`);
4196
4362
  } catch (err) {
4197
- console.error(`${TAG11} presence update failed account=${conn.accountId}: ${String(err)}`);
4363
+ console.error(`${TAG12} presence update failed account=${conn.accountId}: ${String(err)}`);
4198
4364
  }
4199
4365
  await runInitQueries(sock, {
4200
4366
  accountId: conn.accountId,
@@ -4221,9 +4387,9 @@ async function connectWithReconnect(conn) {
4221
4387
  }
4222
4388
  const classification = classifyDisconnect(err);
4223
4389
  conn.lastError = classification.message;
4224
- console.error(`${TAG11} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
4390
+ console.error(`${TAG12} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
4225
4391
  if (!classification.shouldRetry) {
4226
- console.error(`${TAG11} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
4392
+ console.error(`${TAG12} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
4227
4393
  return;
4228
4394
  }
4229
4395
  }
@@ -4236,7 +4402,7 @@ async function connectWithReconnect(conn) {
4236
4402
  if (decision.action === "abort") {
4237
4403
  const stuckReason = `GIVING UP account=${conn.accountId} attempts=${decision.finalAttempts}/${maxAttempts} uptimeMsLast=${uptimeMs} stableThresholdMs=${STABLE_UPTIME_MS} lastError=${conn.lastError ?? "(none)"}`;
4238
4404
  console.error(
4239
- `${TAG11} ${stuckReason} \u2014 re-pair via QR or restart required; WhatsApp will not reconnect automatically`
4405
+ `${TAG12} ${stuckReason} \u2014 re-pair via QR or restart required; WhatsApp will not reconnect automatically`
4240
4406
  );
4241
4407
  conn.sessionStuckReason = stuckReason;
4242
4408
  conn.lastError = stuckReason;
@@ -4245,17 +4411,17 @@ async function connectWithReconnect(conn) {
4245
4411
  conn.reconnectAttempts = decision.nextAttempts;
4246
4412
  if (decision.reason === "short-lived") {
4247
4413
  console.error(
4248
- `${TAG11} short-lived session account=${conn.accountId} uptimeMs=${uptimeMs} attempt=${decision.nextAttempts}/${maxAttempts} lastError=${conn.lastError ?? "(clean disconnect)"}`
4414
+ `${TAG12} short-lived session account=${conn.accountId} uptimeMs=${uptimeMs} attempt=${decision.nextAttempts}/${maxAttempts} lastError=${conn.lastError ?? "(clean disconnect)"}`
4249
4415
  );
4250
4416
  } else {
4251
4417
  console.error(
4252
- `${TAG11} session stable account=${conn.accountId} uptimeMs=${uptimeMs} \u2014 reconnect counter reset`
4418
+ `${TAG12} session stable account=${conn.accountId} uptimeMs=${uptimeMs} \u2014 reconnect counter reset`
4253
4419
  );
4254
4420
  }
4255
4421
  if (decision.reason === "short-lived" || cycleError) {
4256
4422
  const delay = computeBackoff(Math.max(1, decision.nextAttempts));
4257
4423
  console.error(
4258
- `${TAG11} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
4424
+ `${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
4259
4425
  );
4260
4426
  await new Promise((resolve25) => {
4261
4427
  const timer2 = setTimeout(resolve25, delay);
@@ -4289,11 +4455,11 @@ function watchForDisconnect(conn) {
4289
4455
  conn.sock.ev.on("connection.update", (update) => {
4290
4456
  if (update.connection === "close") {
4291
4457
  if (connections.get(conn.accountId) !== conn) return;
4292
- console.error(`${TAG11} socket disconnected for account=${conn.accountId}`);
4458
+ console.error(`${TAG12} socket disconnected for account=${conn.accountId}`);
4293
4459
  conn.connected = false;
4294
4460
  conn.sock = null;
4295
4461
  connectWithReconnect(conn).catch((err) => {
4296
- console.error(`${TAG11} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
4462
+ console.error(`${TAG12} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
4297
4463
  });
4298
4464
  }
4299
4465
  });
@@ -4302,7 +4468,7 @@ async function getGroupMeta(conn, jid) {
4302
4468
  const cached = conn.groupMetaCache.get(jid);
4303
4469
  if (cached && cached.expires > Date.now()) return cached;
4304
4470
  if (!conn.sock) return null;
4305
- console.error(`${TAG11} group metadata cache miss for ${jid}, fetching from Baileys account=${conn.accountId}`);
4471
+ console.error(`${TAG12} group metadata cache miss for ${jid}, fetching from Baileys account=${conn.accountId}`);
4306
4472
  try {
4307
4473
  const meta = await conn.sock.groupMetadata(jid);
4308
4474
  const participants = await Promise.all(
@@ -4317,12 +4483,12 @@ async function getGroupMeta(conn, jid) {
4317
4483
  };
4318
4484
  conn.groupMetaCache.set(jid, entry);
4319
4485
  console.error(
4320
- `${TAG11} group metadata cached for ${jid}: "${meta.subject}", ${participants.length} participants, expires in ${GROUP_META_TTL}ms account=${conn.accountId}`
4486
+ `${TAG12} group metadata cached for ${jid}: "${meta.subject}", ${participants.length} participants, expires in ${GROUP_META_TTL}ms account=${conn.accountId}`
4321
4487
  );
4322
4488
  return entry;
4323
4489
  } catch (err) {
4324
4490
  console.error(
4325
- `${TAG11} group metadata fetch failed for ${jid}: ${err instanceof Error ? err.message : String(err)}, caching empty entry for ${GROUP_META_TTL}ms account=${conn.accountId}`
4491
+ `${TAG12} group metadata fetch failed for ${jid}: ${err instanceof Error ? err.message : String(err)}, caching empty entry for ${GROUP_META_TTL}ms account=${conn.accountId}`
4326
4492
  );
4327
4493
  const emptyEntry = { expires: Date.now() + GROUP_META_TTL };
4328
4494
  conn.groupMetaCache.set(jid, emptyEntry);
@@ -4333,7 +4499,7 @@ function monitorInbound(conn) {
4333
4499
  if (!conn.sock || !onInboundMessage) return;
4334
4500
  const sock = conn.sock;
4335
4501
  const debounceMs = whatsAppConfig.accounts?.[conn.accountId]?.debounceMs ?? whatsAppConfig.debounceMs ?? 0;
4336
- console.error(`${TAG11} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
4502
+ console.error(`${TAG12} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
4337
4503
  conn.debouncer = createInboundDebouncer({
4338
4504
  debounceMs,
4339
4505
  buildKey: (payload) => {
@@ -4346,7 +4512,7 @@ function monitorInbound(conn) {
4346
4512
  onInboundMessage(entries[0]);
4347
4513
  return;
4348
4514
  }
4349
- console.error(`${TAG11} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
4515
+ console.error(`${TAG12} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
4350
4516
  const last = entries[entries.length - 1];
4351
4517
  const mediaEntry = entries.find((e) => e.mediaPath);
4352
4518
  const combinedText = entries.map((e) => e.text).filter(Boolean).join("\n");
@@ -4359,7 +4525,7 @@ function monitorInbound(conn) {
4359
4525
  });
4360
4526
  },
4361
4527
  onError: (err) => {
4362
- console.error(`${TAG11} debounce flush error account=${conn.accountId}: ${String(err)}`);
4528
+ console.error(`${TAG12} debounce flush error account=${conn.accountId}: ${String(err)}`);
4363
4529
  }
4364
4530
  });
4365
4531
  sock.ev.on("messages.upsert", async (upsert) => {
@@ -4387,13 +4553,47 @@ function monitorInbound(conn) {
4387
4553
  });
4388
4554
  const entries = messageStore.get(storeKey);
4389
4555
  console.error(
4390
- `${TAG11} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) account=${conn.accountId}`
4556
+ `${TAG12} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) account=${conn.accountId}`
4391
4557
  );
4392
4558
  recordActivity({
4393
4559
  accountId: conn.accountId,
4394
4560
  direction: "inbound",
4395
4561
  jid: remoteJid
4396
4562
  });
4563
+ const fromMe = Boolean(msg.key.fromMe);
4564
+ const sessionKeyAgentType = isGroup ? "public" : fromMe ? "admin" : checkDmAccess({
4565
+ senderPhone,
4566
+ selfPhone: conn.selfPhone ?? "",
4567
+ config: whatsAppConfig,
4568
+ accountConfig: whatsAppConfig.accounts?.[conn.accountId]
4569
+ }).agentType;
4570
+ const sessionKey = deriveSessionKey({
4571
+ agentType: sessionKeyAgentType,
4572
+ accountId: conn.accountId,
4573
+ senderPhone,
4574
+ isGroup,
4575
+ groupJid: isGroup ? remoteJid : void 0,
4576
+ isOwnerMirror: fromMe && !isGroup
4577
+ });
4578
+ if (msg.key.id) {
4579
+ await persistWhatsAppMessage({
4580
+ accountId: conn.accountId,
4581
+ remoteJid,
4582
+ sessionKey,
4583
+ msgKeyId: msg.key.id,
4584
+ fromMe,
4585
+ senderPhone,
4586
+ selfPhone: conn.selfPhone,
4587
+ body: extracted.text,
4588
+ timestamp: ts,
4589
+ pushName: msg.pushName ?? void 0,
4590
+ quoted: extracted.quotedMessage ? {
4591
+ id: extracted.quotedMessage.id,
4592
+ body: extracted.quotedMessage.text,
4593
+ sender: extracted.quotedMessage.sender
4594
+ } : void 0
4595
+ });
4596
+ }
4397
4597
  }
4398
4598
  if (upsert.type === "append") {
4399
4599
  const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
@@ -4406,13 +4606,13 @@ function monitorInbound(conn) {
4406
4606
  );
4407
4607
  }
4408
4608
  console.error(
4409
- `${TAG11} append-type message ${msg.key.id ?? "?"} stored, dispatch skipped account=${conn.accountId}`
4609
+ `${TAG12} append-type message ${msg.key.id ?? "?"} stored, dispatch skipped account=${conn.accountId}`
4410
4610
  );
4411
4611
  continue;
4412
4612
  }
4413
4613
  await handleInboundMessage(conn, msg);
4414
4614
  } catch (err) {
4415
- console.error(`${TAG11} inbound handler error account=${conn.accountId}: ${String(err)}`);
4615
+ console.error(`${TAG12} inbound handler error account=${conn.accountId}: ${String(err)}`);
4416
4616
  }
4417
4617
  }
4418
4618
  });
@@ -4422,31 +4622,31 @@ async function handleInboundMessage(conn, msg) {
4422
4622
  const remoteJid = msg.key.remoteJid;
4423
4623
  if (!remoteJid) return;
4424
4624
  if (remoteJid === "status@broadcast") {
4425
- console.error(`${TAG11} drop: status broadcast account=${conn.accountId}`);
4625
+ console.error(`${TAG12} drop: status broadcast account=${conn.accountId}`);
4426
4626
  return;
4427
4627
  }
4428
4628
  if (!msg.message) {
4429
- console.error(`${TAG11} drop: empty message account=${conn.accountId} from=${remoteJid}`);
4629
+ console.error(`${TAG12} drop: empty message account=${conn.accountId} from=${remoteJid}`);
4430
4630
  return;
4431
4631
  }
4432
4632
  const dedupKey = `${conn.accountId}:${remoteJid}:${msg.key.id}`;
4433
4633
  if (isDuplicateInbound(dedupKey)) {
4434
- console.error(`${TAG11} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
4634
+ console.error(`${TAG12} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
4435
4635
  return;
4436
4636
  }
4437
4637
  if (msg.key.fromMe) {
4438
4638
  if (msg.key.id && isAgentSentMessage(msg.key.id)) {
4439
- console.error(`${TAG11} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
4639
+ console.error(`${TAG12} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
4440
4640
  return;
4441
4641
  }
4442
4642
  const extracted2 = extractMessage(msg);
4443
4643
  if (!extracted2.text) {
4444
- console.error(`${TAG11} owner reply skipped \u2014 no text content account=${conn.accountId}`);
4644
+ console.error(`${TAG12} owner reply skipped \u2014 no text content account=${conn.accountId}`);
4445
4645
  return;
4446
4646
  }
4447
4647
  const isGroup2 = isGroupJid(remoteJid);
4448
4648
  const senderPhone2 = conn.selfPhone ?? "owner";
4449
- console.error(`${TAG11} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
4649
+ console.error(`${TAG12} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
4450
4650
  const reply2 = async (text) => {
4451
4651
  const currentSock = conn.sock;
4452
4652
  if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
@@ -4474,7 +4674,7 @@ async function handleInboundMessage(conn, msg) {
4474
4674
  }
4475
4675
  const extracted = extractMessage(msg);
4476
4676
  if (!extracted.text && !extracted.mediaType) {
4477
- console.error(`${TAG11} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
4677
+ console.error(`${TAG12} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
4478
4678
  return;
4479
4679
  }
4480
4680
  let mediaResult;
@@ -4484,7 +4684,7 @@ async function handleInboundMessage(conn, msg) {
4484
4684
  maxBytes: maxMb * 1024 * 1024
4485
4685
  });
4486
4686
  if (!mediaResult) {
4487
- console.error(`${TAG11} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
4687
+ console.error(`${TAG12} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
4488
4688
  }
4489
4689
  }
4490
4690
  const isGroup = isGroupJid(remoteJid);
@@ -4529,7 +4729,7 @@ async function handleInboundMessage(conn, msg) {
4529
4729
  });
4530
4730
  }
4531
4731
  console.error(
4532
- `${TAG11} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (mediaResult ? ` mediaPath=${mediaResult.path}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
4732
+ `${TAG12} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (mediaResult ? ` mediaPath=${mediaResult.path}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
4533
4733
  );
4534
4734
  if (!accessResult.allowed) return;
4535
4735
  let groupSubject;
@@ -4572,15 +4772,15 @@ async function handleInboundMessage(conn, msg) {
4572
4772
  if (accessResult.agentType === "public") {
4573
4773
  const hoursResult = await isBusinessOpen(conn.accountId);
4574
4774
  if (!hoursResult.open) {
4575
- console.error(`${TAG11} [${conn.accountId}] dispatch skipped: business closed`);
4775
+ console.error(`${TAG12} [${conn.accountId}] dispatch skipped: business closed`);
4576
4776
  const afterHoursMessage = whatsAppConfig.accounts?.[conn.accountId]?.afterHoursMessage ?? whatsAppConfig.afterHoursMessage;
4577
4777
  if (afterHoursMessage) {
4578
4778
  try {
4579
4779
  await reply(afterHoursMessage);
4580
- console.error(`${TAG11} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
4780
+ console.error(`${TAG12} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
4581
4781
  } catch (err) {
4582
4782
  console.error(
4583
- `${TAG11} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
4783
+ `${TAG12} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
4584
4784
  );
4585
4785
  }
4586
4786
  }
@@ -5166,7 +5366,7 @@ async function storeGeneratedFile(accountId, filePath) {
5166
5366
  import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
5167
5367
  import { tmpdir } from "os";
5168
5368
  import { join as join5 } from "path";
5169
- var TAG12 = "[voice]";
5369
+ var TAG13 = "[voice]";
5170
5370
  var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
5171
5371
  "audio/ogg",
5172
5372
  "audio/webm",
@@ -5198,7 +5398,7 @@ async function transcribeVoiceNote(file, source) {
5198
5398
  const bytes = file.size;
5199
5399
  const mimeType = file.type;
5200
5400
  console.error(
5201
- `${TAG12} recording send source=${source} duration_ms=unknown bytes=${bytes} format=${mimeType}`
5401
+ `${TAG13} recording send source=${source} duration_ms=unknown bytes=${bytes} format=${mimeType}`
5202
5402
  );
5203
5403
  let tempDir;
5204
5404
  let tempPath;
@@ -5210,7 +5410,7 @@ async function transcribeVoiceNote(file, source) {
5210
5410
  await writeFile3(tempPath, buffer);
5211
5411
  } catch (err) {
5212
5412
  const reason = err instanceof Error ? err.message : String(err);
5213
- console.error(`${TAG12} failed source=${source} error=temp-file-write: ${reason}`);
5413
+ console.error(`${TAG13} failed source=${source} error=temp-file-write: ${reason}`);
5214
5414
  return { ok: false, error: "Could not process voice note" };
5215
5415
  }
5216
5416
  try {
@@ -5218,7 +5418,7 @@ async function transcribeVoiceNote(file, source) {
5218
5418
  if (!sttResult) {
5219
5419
  const elapsed2 = Date.now() - startMs;
5220
5420
  console.error(
5221
- `${TAG12} failed source=${source} error=transcription-failed duration_ms=${elapsed2}`
5421
+ `${TAG13} failed source=${source} error=transcription-failed duration_ms=${elapsed2}`
5222
5422
  );
5223
5423
  return { ok: false, error: "Could not transcribe voice note. Please try again or type your message." };
5224
5424
  }
@@ -5226,7 +5426,7 @@ async function transcribeVoiceNote(file, source) {
5226
5426
  const elapsed = Date.now() - startMs;
5227
5427
  const words = rawText.split(/\s+/).filter(Boolean).length;
5228
5428
  console.error(
5229
- `${TAG12} transcribed source=${source} duration_ms=${elapsed} stt_ms=${sttResult.durationMs} words=${words}`
5429
+ `${TAG13} transcribed source=${source} duration_ms=${elapsed} stt_ms=${sttResult.durationMs} words=${words}`
5230
5430
  );
5231
5431
  return {
5232
5432
  ok: true,
@@ -5236,7 +5436,7 @@ async function transcribeVoiceNote(file, source) {
5236
5436
  const elapsed = Date.now() - startMs;
5237
5437
  const reason = err instanceof Error ? err.message : String(err);
5238
5438
  console.error(
5239
- `${TAG12} failed source=${source} error=${reason} duration_ms=${elapsed}`
5439
+ `${TAG13} failed source=${source} error=${reason} duration_ms=${elapsed}`
5240
5440
  );
5241
5441
  return { ok: false, error: "Voice note transcription failed. Please try again or type your message." };
5242
5442
  } finally {
@@ -5271,7 +5471,7 @@ var VERDICT_DEFINITIONS = {
5271
5471
  };
5272
5472
 
5273
5473
  // app/lib/inbound-gateway.ts
5274
- var TAG13 = "[inbound-gateway]";
5474
+ var TAG14 = "[inbound-gateway]";
5275
5475
  var GATEWAY_TIMEOUT_MS = 1e4;
5276
5476
  var MIN_WORDS_FOR_PROCESSING = 5;
5277
5477
  function defaultResult(rawText, latencyMs) {
@@ -5394,11 +5594,11 @@ async function processInbound(rawText, channel) {
5394
5594
  };
5395
5595
  result.fallthrough = false;
5396
5596
  console.warn(
5397
- `${TAG13} short-message-injection channel=${channel} words=${words.length} latency_ms=${result.latencyMs}`
5597
+ `${TAG14} short-message-injection channel=${channel} words=${words.length} latency_ms=${result.latencyMs}`
5398
5598
  );
5399
5599
  } else {
5400
5600
  console.log(
5401
- `${TAG13} passthrough channel=${channel} reason=short-message words=${words.length} latency_ms=${result.latencyMs}`
5601
+ `${TAG14} passthrough channel=${channel} reason=short-message words=${words.length} latency_ms=${result.latencyMs}`
5402
5602
  );
5403
5603
  }
5404
5604
  return result;
@@ -5415,13 +5615,13 @@ async function processInbound(rawText, channel) {
5415
5615
  const latencyMs = Date.now() - startMs;
5416
5616
  if (llmResult.kind === "fallback") {
5417
5617
  console.warn(
5418
- `${TAG13} fallthrough channel=${channel} reason=${llmResult.cause} detail=${llmResult.reason} latency_ms=${latencyMs}`
5618
+ `${TAG14} fallthrough channel=${channel} reason=${llmResult.cause} detail=${llmResult.reason} latency_ms=${latencyMs}`
5419
5619
  );
5420
5620
  return defaultResult(rawText.trim(), latencyMs);
5421
5621
  }
5422
5622
  if (llmResult.kind !== "ok-tool") {
5423
5623
  console.warn(
5424
- `${TAG13} fallthrough channel=${channel} reason=no-tool-response latency_ms=${latencyMs}`
5624
+ `${TAG14} fallthrough channel=${channel} reason=no-tool-response latency_ms=${latencyMs}`
5425
5625
  );
5426
5626
  return defaultResult(rawText.trim(), latencyMs);
5427
5627
  }
@@ -5431,7 +5631,7 @@ async function processInbound(rawText, channel) {
5431
5631
  const verdict = input.verdict;
5432
5632
  if (!processedText || !verdict || !["clean", "suspicious", "discard"].includes(verdict)) {
5433
5633
  console.warn(
5434
- `${TAG13} fallthrough channel=${channel} reason=mandatory-fields-missing latency_ms=${latencyMs} hasProcessedText=${!!processedText} verdict=${String(verdict)}`
5634
+ `${TAG14} fallthrough channel=${channel} reason=mandatory-fields-missing latency_ms=${latencyMs} hasProcessedText=${!!processedText} verdict=${String(verdict)}`
5435
5635
  );
5436
5636
  return defaultResult(rawText.trim(), latencyMs);
5437
5637
  }
@@ -5459,18 +5659,18 @@ async function processInbound(rawText, channel) {
5459
5659
  fallthrough: false
5460
5660
  };
5461
5661
  console.log(
5462
- `${TAG13} channel=${channel} verdict=${verdict} promptInjection=${promptInjectionRisk} intent=${intent} language=${language} complexity=${complexity} requiresHistory=${requiresHistory} rewrite=${!isAdmin && processedText !== rawText.trim()} searchQuery=${searchQuery ? "yes" : "null"} latency_ms=${latencyMs}`
5662
+ `${TAG14} channel=${channel} verdict=${verdict} promptInjection=${promptInjectionRisk} intent=${intent} language=${language} complexity=${complexity} requiresHistory=${requiresHistory} rewrite=${!isAdmin && processedText !== rawText.trim()} searchQuery=${searchQuery ? "yes" : "null"} latency_ms=${latencyMs}`
5463
5663
  );
5464
5664
  if (verdict !== "clean") {
5465
5665
  console.warn(
5466
- `${TAG13} ${verdict.toUpperCase()} channel=${channel} reason=${reason} promptInjection=${promptInjectionRisk}`
5666
+ `${TAG14} ${verdict.toUpperCase()} channel=${channel} reason=${reason} promptInjection=${promptInjectionRisk}`
5467
5667
  );
5468
5668
  }
5469
5669
  return result;
5470
5670
  } catch (err) {
5471
5671
  const reason = err instanceof Error ? err.message : String(err);
5472
5672
  console.warn(
5473
- `${TAG13} fallthrough channel=${channel} reason=parse-error: ${reason} latency_ms=${latencyMs}`
5673
+ `${TAG14} fallthrough channel=${channel} reason=parse-error: ${reason} latency_ms=${latencyMs}`
5474
5674
  );
5475
5675
  return defaultResult(rawText.trim(), latencyMs);
5476
5676
  }
@@ -6563,7 +6763,7 @@ function checkTelegramAccess(params) {
6563
6763
  }
6564
6764
 
6565
6765
  // server/routes/telegram.ts
6566
- var TAG14 = "[telegram-webhook]";
6766
+ var TAG15 = "[telegram-webhook]";
6567
6767
  var TELEGRAM_API = "https://api.telegram.org";
6568
6768
  function getWebhookSecret(botType) {
6569
6769
  const filePath = botType === "admin" ? TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE : TELEGRAM_WEBHOOK_SECRET_FILE;
@@ -6587,12 +6787,12 @@ async function handleInbound(params) {
6587
6787
  const gatewayChannel = agentType === "admin" ? "telegram-admin" : "telegram-dm";
6588
6788
  registerSession(sessionKey, agentType, accountId);
6589
6789
  console.error(
6590
- `${TAG14} session registered: sessionKey=${sessionKey} agentType=${agentType} botType=${botType} senderId=${senderId} accountId=${accountId.slice(0, 8)}\u2026`
6790
+ `${TAG15} session registered: sessionKey=${sessionKey} agentType=${agentType} botType=${botType} senderId=${senderId} accountId=${accountId.slice(0, 8)}\u2026`
6591
6791
  );
6592
6792
  const gatewayResult = await processInbound(text, gatewayChannel);
6593
6793
  if (gatewayResult.screening.verdict === "discard") {
6594
6794
  console.error(
6595
- `${TAG14} discarded: senderId=${senderId} chatId=${chatId} reason=${gatewayResult.screening.reason}`
6795
+ `${TAG15} discarded: senderId=${senderId} chatId=${chatId} reason=${gatewayResult.screening.reason}`
6596
6796
  );
6597
6797
  return;
6598
6798
  }
@@ -6615,7 +6815,7 @@ async function handleInbound(params) {
6615
6815
  }
6616
6816
  } catch (err) {
6617
6817
  console.error(
6618
- `${TAG14} agent-error: chatId=${chatId} senderId=${senderId} error=${err instanceof Error ? err.message : String(err)}`
6818
+ `${TAG15} agent-error: chatId=${chatId} senderId=${senderId} error=${err instanceof Error ? err.message : String(err)}`
6619
6819
  );
6620
6820
  responseText = "I'm having trouble right now. Please try again in a moment.";
6621
6821
  }
@@ -6633,12 +6833,12 @@ async function handleInbound(params) {
6633
6833
  const data = await res.json();
6634
6834
  if (!data.ok) {
6635
6835
  console.error(
6636
- `${TAG14} send-error: chatId=${chatId} error=${data.description ?? "unknown"}`
6836
+ `${TAG15} send-error: chatId=${chatId} error=${data.description ?? "unknown"}`
6637
6837
  );
6638
6838
  }
6639
6839
  } catch (err) {
6640
6840
  console.error(
6641
- `${TAG14} send-error: chatId=${chatId} error=${err instanceof Error ? err.message : String(err)}`
6841
+ `${TAG15} send-error: chatId=${chatId} error=${err instanceof Error ? err.message : String(err)}`
6642
6842
  );
6643
6843
  }
6644
6844
  }
@@ -6646,28 +6846,28 @@ var app6 = new Hono();
6646
6846
  app6.post("/webhook", async (c) => {
6647
6847
  const botType = c.req.query("bot");
6648
6848
  if (!botType || botType !== "public" && botType !== "admin") {
6649
- console.error(`${TAG14} invalid-bot-type: received=${botType ?? "missing"}`);
6849
+ console.error(`${TAG15} invalid-bot-type: received=${botType ?? "missing"}`);
6650
6850
  return c.json({ error: "Missing or invalid bot type" }, 400);
6651
6851
  }
6652
6852
  const storedSecret = getWebhookSecret(botType);
6653
6853
  if (!storedSecret) {
6654
- console.error(`${TAG14} secret=missing botType=${botType}`);
6854
+ console.error(`${TAG15} secret=missing botType=${botType}`);
6655
6855
  return c.json({ error: "Webhook not configured" }, 401);
6656
6856
  }
6657
6857
  const headerSecret = c.req.header("x-telegram-bot-api-secret-token");
6658
6858
  if (!headerSecret || !verifyWebhookSecret(headerSecret, storedSecret)) {
6659
- console.error(`${TAG14} secret=invalid botType=${botType}`);
6859
+ console.error(`${TAG15} secret=invalid botType=${botType}`);
6660
6860
  return c.json({ error: "Unauthorized" }, 401);
6661
6861
  }
6662
6862
  const account = resolveAccount();
6663
6863
  if (!account) {
6664
- console.error(`${TAG14} config=no-account`);
6864
+ console.error(`${TAG15} config=no-account`);
6665
6865
  return c.json({ error: "No account configured" }, 500);
6666
6866
  }
6667
6867
  const tgConfig = account.config.telegram ?? {};
6668
6868
  const botToken = botType === "admin" ? tgConfig.adminBotToken : tgConfig.publicBotToken;
6669
6869
  if (!botToken) {
6670
- console.error(`${TAG14} config=no-token botType=${botType}`);
6870
+ console.error(`${TAG15} config=no-token botType=${botType}`);
6671
6871
  return c.json({ error: `No ${botType} bot token configured` }, 500);
6672
6872
  }
6673
6873
  let update;
@@ -6695,7 +6895,7 @@ app6.post("/webhook", async (c) => {
6695
6895
  }
6696
6896
  const accessResult = checkTelegramAccess({ senderId, botType, config: tgConfig });
6697
6897
  console.error(
6698
- `${TAG14} access: botType=${botType} senderId=${senderId} chatId=${chatId} allowed=${accessResult.allowed} reason=${accessResult.reason} agentType=${accessResult.agentType}`
6898
+ `${TAG15} access: botType=${botType} senderId=${senderId} chatId=${chatId} allowed=${accessResult.allowed} reason=${accessResult.reason} agentType=${accessResult.agentType}`
6699
6899
  );
6700
6900
  if (!accessResult.allowed) {
6701
6901
  return c.json({ ok: true });
@@ -6706,7 +6906,7 @@ app6.post("/webhook", async (c) => {
6706
6906
  headers: { "Content-Type": "application/json" },
6707
6907
  body: JSON.stringify({ callback_query_id: callbackId })
6708
6908
  }).catch((err) => {
6709
- console.error(`${TAG14} callback-ack-error: ${err instanceof Error ? err.message : String(err)}`);
6909
+ console.error(`${TAG15} callback-ack-error: ${err instanceof Error ? err.message : String(err)}`);
6710
6910
  });
6711
6911
  }
6712
6912
  handleInbound({
@@ -6719,7 +6919,7 @@ app6.post("/webhook", async (c) => {
6719
6919
  agentType: accessResult.agentType
6720
6920
  }).catch((err) => {
6721
6921
  console.error(
6722
- `${TAG14} unhandled-error: chatId=${chatId} senderId=${senderId} error=${err instanceof Error ? err.message : String(err)}`
6922
+ `${TAG15} unhandled-error: chatId=${chatId} senderId=${senderId} error=${err instanceof Error ? err.message : String(err)}`
6723
6923
  );
6724
6924
  });
6725
6925
  return c.json({ ok: true });
@@ -6733,14 +6933,14 @@ import { realpathSync as realpathSync2, readdirSync as readdirSync2, readFileSyn
6733
6933
 
6734
6934
  // app/lib/whatsapp/login.ts
6735
6935
  import { randomUUID as randomUUID6 } from "crypto";
6736
- var TAG15 = "[whatsapp:login]";
6936
+ var TAG16 = "[whatsapp:login]";
6737
6937
  var ACTIVE_LOGIN_TTL_MS = 3 * 6e4;
6738
6938
  var activeLogins = /* @__PURE__ */ new Map();
6739
6939
  function closeSocket(sock) {
6740
6940
  try {
6741
6941
  sock.ws?.close?.();
6742
6942
  } catch (err) {
6743
- console.warn(`${TAG15} socket close error during cleanup: ${String(err)}`);
6943
+ console.warn(`${TAG16} socket close error during cleanup: ${String(err)}`);
6744
6944
  }
6745
6945
  }
6746
6946
  function resetActiveLogin(accountId) {
@@ -6763,7 +6963,7 @@ async function loginConnectionLoop(accountId, login) {
6763
6963
  const current = activeLogins.get(accountId);
6764
6964
  if (current?.id === login.id) {
6765
6965
  current.connected = true;
6766
- console.error(`${TAG15} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
6966
+ console.error(`${TAG16} loginConnectionLoop: connected account=${accountId} attempt=${attempt}`);
6767
6967
  }
6768
6968
  return;
6769
6969
  } catch (err) {
@@ -6773,7 +6973,7 @@ async function loginConnectionLoop(accountId, login) {
6773
6973
  if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
6774
6974
  if (attempt >= LOGIN_MAX_RECONNECTS) {
6775
6975
  console.error(
6776
- `${TAG15} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
6976
+ `${TAG16} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
6777
6977
  );
6778
6978
  current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
6779
6979
  } else {
@@ -6785,7 +6985,7 @@ async function loginConnectionLoop(accountId, login) {
6785
6985
  attempt++;
6786
6986
  const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
6787
6987
  console.error(
6788
- `${TAG15} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
6988
+ `${TAG16} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
6789
6989
  );
6790
6990
  closeSocket(current.sock);
6791
6991
  await new Promise((r) => setTimeout(r, delay));
@@ -6796,7 +6996,7 @@ async function loginConnectionLoop(accountId, login) {
6796
6996
  current.sock = newSock;
6797
6997
  } catch (sockErr) {
6798
6998
  console.error(
6799
- `${TAG15} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
6999
+ `${TAG16} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
6800
7000
  );
6801
7001
  current.error = `Reconnection failed: ${String(sockErr)}`;
6802
7002
  return;
@@ -6810,7 +7010,7 @@ async function startLogin(opts) {
6810
7010
  const hasAuth = await authExists(authDir);
6811
7011
  const selfId = readSelfId(authDir);
6812
7012
  console.error(
6813
- `${TAG15} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasQr=${!!existing0.qr}}` : " activeLogin=none")
7013
+ `${TAG16} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasQr=${!!existing0.qr}}` : " activeLogin=none")
6814
7014
  );
6815
7015
  if (hasAuth && !force) {
6816
7016
  const who = selfId.e164 ?? selfId.jid ?? "unknown";
@@ -6822,7 +7022,7 @@ async function startLogin(opts) {
6822
7022
  await clearAuth(authDir);
6823
7023
  const existing = activeLogins.get(accountId);
6824
7024
  if (existing && isLoginFresh(existing) && existing.qrDataUrl && !force) {
6825
- console.error(`${TAG15} startLogin account=${accountId} guard: returning existing QR (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
7025
+ console.error(`${TAG16} startLogin account=${accountId} guard: returning existing QR (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
6826
7026
  return {
6827
7027
  qrDataUrl: existing.qrDataUrl,
6828
7028
  qrRaw: existing.qr,
@@ -6830,7 +7030,7 @@ async function startLogin(opts) {
6830
7030
  };
6831
7031
  }
6832
7032
  if (existing) {
6833
- console.error(`${TAG15} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
7033
+ console.error(`${TAG16} startLogin account=${accountId} ${force ? "force override" : "stale/no-QR"}, resetting active login`);
6834
7034
  }
6835
7035
  resetActiveLogin(accountId);
6836
7036
  let resolveQr = null;
@@ -6852,14 +7052,14 @@ async function startLogin(opts) {
6852
7052
  onQr: (qr2) => {
6853
7053
  loginQrCount++;
6854
7054
  if (pendingQr) {
6855
- console.error(`${TAG15} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
7055
+ console.error(`${TAG16} QR rotation #${loginQrCount} received for account=${accountId} \u2014 not forwarded (initial QR already captured)`);
6856
7056
  return;
6857
7057
  }
6858
7058
  pendingQr = qr2;
6859
7059
  const current = activeLogins.get(accountId);
6860
7060
  if (current && !current.qr) current.qr = qr2;
6861
7061
  clearTimeout(qrTimer);
6862
- console.error(`${TAG15} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
7062
+ console.error(`${TAG16} QR #${loginQrCount} received for account=${accountId} \u2014 forwarding to caller`);
6863
7063
  resolveQr?.(qr2);
6864
7064
  }
6865
7065
  });
@@ -6879,7 +7079,7 @@ async function startLogin(opts) {
6879
7079
  activeLogins.set(accountId, login);
6880
7080
  if (pendingQr && !login.qr) login.qr = pendingQr;
6881
7081
  loginConnectionLoop(accountId, login).catch((err) => {
6882
- console.error(`${TAG15} loginConnectionLoop unexpected error: ${String(err)}`);
7082
+ console.error(`${TAG16} loginConnectionLoop unexpected error: ${String(err)}`);
6883
7083
  const current = activeLogins.get(accountId);
6884
7084
  if (current?.id === login.id) {
6885
7085
  current.error = `Unexpected login error: ${String(err)}`;
@@ -6904,7 +7104,7 @@ async function waitForLogin(opts) {
6904
7104
  const { accountId, timeoutMs = 6e4 } = opts;
6905
7105
  const login = activeLogins.get(accountId);
6906
7106
  console.error(
6907
- `${TAG15} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasQr=${!!login.qr}}` : " login=none")
7107
+ `${TAG16} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasQr=${!!login.qr}}` : " login=none")
6908
7108
  );
6909
7109
  if (!login) {
6910
7110
  return { connected: false, message: "No active WhatsApp login in progress." };
@@ -6917,7 +7117,7 @@ async function waitForLogin(opts) {
6917
7117
  while (Date.now() < deadline) {
6918
7118
  if (login.connected) {
6919
7119
  const selfId = readSelfId(login.authDir);
6920
- console.error(`${TAG15} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
7120
+ console.error(`${TAG16} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
6921
7121
  const sock = login.sock;
6922
7122
  const authDir = login.authDir;
6923
7123
  activeLogins.delete(accountId);
@@ -6937,7 +7137,7 @@ async function waitForLogin(opts) {
6937
7137
  await new Promise((r) => setTimeout(r, 1e3));
6938
7138
  }
6939
7139
  const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
6940
- console.error(`${TAG15} waitForLogin timeout account=${accountId} elapsed=${elapsed}s \u2014 cleaning up active login`);
7140
+ console.error(`${TAG16} waitForLogin timeout account=${accountId} elapsed=${elapsed}s \u2014 cleaning up active login`);
6941
7141
  resetActiveLogin(accountId);
6942
7142
  return { connected: false, message: "Login timed out. Try generating a new QR." };
6943
7143
  }
@@ -7051,17 +7251,17 @@ function serializeWhatsAppSchema() {
7051
7251
  }
7052
7252
 
7053
7253
  // server/routes/whatsapp.ts
7054
- var TAG16 = "[whatsapp:api]";
7254
+ var TAG17 = "[whatsapp:api]";
7055
7255
  var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT || "";
7056
7256
  var app7 = new Hono();
7057
7257
  app7.get("/status", (c) => {
7058
7258
  try {
7059
7259
  const status = getStatus();
7060
7260
  const summary = status.map((a) => `${a.accountId}:${a.connected ? "up" : "down"}`).join(", ");
7061
- console.error(`${TAG16} status accounts=${status.length} [${summary}]`);
7261
+ console.error(`${TAG17} status accounts=${status.length} [${summary}]`);
7062
7262
  return c.json({ accounts: status });
7063
7263
  } catch (err) {
7064
- console.error(`${TAG16} status error: ${String(err)}`);
7264
+ console.error(`${TAG17} status error: ${String(err)}`);
7065
7265
  return c.json({ error: String(err) }, 500);
7066
7266
  }
7067
7267
  });
@@ -7072,10 +7272,10 @@ app7.post("/login/start", async (c) => {
7072
7272
  const force = body.force ?? false;
7073
7273
  const authDir = join6(MAXY_DIR, "credentials", "whatsapp", accountId);
7074
7274
  const result = await startLogin({ accountId, authDir, force });
7075
- console.error(`${TAG16} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
7275
+ console.error(`${TAG17} login/start result account=${accountId} hasQr=${!!result.qrRaw}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
7076
7276
  return c.json(result);
7077
7277
  } catch (err) {
7078
- console.error(`${TAG16} login/start error: ${String(err)}`);
7278
+ console.error(`${TAG17} login/start error: ${String(err)}`);
7079
7279
  return c.json({ error: String(err) }, 500);
7080
7280
  }
7081
7281
  });
@@ -7090,7 +7290,7 @@ app7.post("/login/wait", async (c) => {
7090
7290
  try {
7091
7291
  await registerLoginSocket(accountId, result.sock, result.authDir);
7092
7292
  } catch (regErr) {
7093
- console.error(`${TAG16} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
7293
+ console.error(`${TAG17} registerLoginSocket failed account=${accountId}: ${String(regErr)}`);
7094
7294
  }
7095
7295
  try {
7096
7296
  const account = resolveAccount();
@@ -7098,16 +7298,16 @@ app7.post("/login/wait", async (c) => {
7098
7298
  const persistResult = persistAfterPairing(account.accountDir, accountId, result.selfPhone ?? null);
7099
7299
  configPersisted = persistResult.ok;
7100
7300
  if (!persistResult.ok) {
7101
- console.error(`${TAG16} config persist failed account=${accountId}: ${persistResult.error}`);
7301
+ console.error(`${TAG17} config persist failed account=${accountId}: ${persistResult.error}`);
7102
7302
  }
7103
7303
  } else {
7104
- console.error(`${TAG16} config persist skipped \u2014 no account resolved`);
7304
+ console.error(`${TAG17} config persist skipped \u2014 no account resolved`);
7105
7305
  }
7106
7306
  } catch (persistErr) {
7107
- console.error(`${TAG16} config persist error account=${accountId}: ${String(persistErr)}`);
7307
+ console.error(`${TAG17} config persist error account=${accountId}: ${String(persistErr)}`);
7108
7308
  }
7109
7309
  }
7110
- console.error(`${TAG16} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
7310
+ console.error(`${TAG17} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${configPersisted}`);
7111
7311
  return c.json({
7112
7312
  connected: result.connected,
7113
7313
  message: result.message,
@@ -7115,7 +7315,7 @@ app7.post("/login/wait", async (c) => {
7115
7315
  configPersisted
7116
7316
  });
7117
7317
  } catch (err) {
7118
- console.error(`${TAG16} login/wait error: ${String(err)}`);
7318
+ console.error(`${TAG17} login/wait error: ${String(err)}`);
7119
7319
  return c.json({ error: String(err) }, 500);
7120
7320
  }
7121
7321
  });
@@ -7126,7 +7326,7 @@ app7.post("/disconnect", async (c) => {
7126
7326
  await stopConnection(accountId);
7127
7327
  return c.json({ disconnected: true, accountId });
7128
7328
  } catch (err) {
7129
- console.error(`${TAG16} disconnect error: ${String(err)}`);
7329
+ console.error(`${TAG17} disconnect error: ${String(err)}`);
7130
7330
  return c.json({ error: String(err) }, 500);
7131
7331
  }
7132
7332
  });
@@ -7137,7 +7337,7 @@ app7.post("/reconnect", async (c) => {
7137
7337
  await startConnection(accountId);
7138
7338
  return c.json({ reconnecting: true, accountId });
7139
7339
  } catch (err) {
7140
- console.error(`${TAG16} reconnect error: ${String(err)}`);
7340
+ console.error(`${TAG17} reconnect error: ${String(err)}`);
7141
7341
  return c.json({ error: String(err) }, 500);
7142
7342
  }
7143
7343
  });
@@ -7156,7 +7356,7 @@ app7.post("/send", async (c) => {
7156
7356
  const result = await sendTextMessage(sock, to, text, { accountId });
7157
7357
  return c.json(result);
7158
7358
  } catch (err) {
7159
- console.error(`${TAG16} send error: ${String(err)}`);
7359
+ console.error(`${TAG17} send error: ${String(err)}`);
7160
7360
  return c.json({ error: String(err) }, 500);
7161
7361
  }
7162
7362
  });
@@ -7177,7 +7377,7 @@ app7.post("/config", async (c) => {
7177
7377
  return c.json({ ok: false, error: 'Missing required field "phone" (E.164 format, e.g. +441234567890).' }, 400);
7178
7378
  }
7179
7379
  const result = addAdminPhone(account.accountDir, phone);
7180
- console.error(`${TAG16} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
7380
+ console.error(`${TAG17} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
7181
7381
  return c.json(result, result.ok ? 200 : 400);
7182
7382
  }
7183
7383
  case "remove-admin-phone": {
@@ -7185,12 +7385,12 @@ app7.post("/config", async (c) => {
7185
7385
  return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
7186
7386
  }
7187
7387
  const result = removeAdminPhone(account.accountDir, phone);
7188
- console.error(`${TAG16} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
7388
+ console.error(`${TAG17} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
7189
7389
  return c.json(result, result.ok ? 200 : 400);
7190
7390
  }
7191
7391
  case "list-admin-phones": {
7192
7392
  const phones = readAdminPhones(account.accountDir);
7193
- console.error(`${TAG16} config action=list-admin-phones count=${phones.length}`);
7393
+ console.error(`${TAG17} config action=list-admin-phones count=${phones.length}`);
7194
7394
  return c.json({ ok: true, phones });
7195
7395
  }
7196
7396
  case "set-public-agent": {
@@ -7198,14 +7398,14 @@ app7.post("/config", async (c) => {
7198
7398
  return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
7199
7399
  }
7200
7400
  const result = setPublicAgent(account.accountDir, slug);
7201
- console.error(`${TAG16} config action=set-public-agent slug=${slug} ok=${result.ok}`);
7401
+ console.error(`${TAG17} config action=set-public-agent slug=${slug} ok=${result.ok}`);
7202
7402
  return c.json(result, result.ok ? 200 : 400);
7203
7403
  }
7204
7404
  case "get-public-agent": {
7205
7405
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
7206
7406
  const targetGroup = typeof groupJid === "string" && groupJid.trim() ? groupJid.trim() : void 0;
7207
7407
  const resolved = resolvePublicAgent(account.accountDir, { accountId: targetAccount, groupJid: targetGroup });
7208
- console.error(`${TAG16} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
7408
+ console.error(`${TAG17} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
7209
7409
  return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
7210
7410
  }
7211
7411
  case "set-group-public-agent": {
@@ -7217,7 +7417,7 @@ app7.post("/config", async (c) => {
7217
7417
  }
7218
7418
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
7219
7419
  const result = setGroupPublicAgent(account.accountDir, targetAccount, groupJid, slug);
7220
- console.error(`${TAG16} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
7420
+ console.error(`${TAG17} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
7221
7421
  return c.json(result, result.ok ? 200 : 400);
7222
7422
  }
7223
7423
  case "unset-group-public-agent": {
@@ -7226,7 +7426,7 @@ app7.post("/config", async (c) => {
7226
7426
  }
7227
7427
  const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
7228
7428
  const result = unsetGroupPublicAgent(account.accountDir, targetAccount, groupJid);
7229
- console.error(`${TAG16} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
7429
+ console.error(`${TAG17} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
7230
7430
  return c.json(result, result.ok ? 200 : 400);
7231
7431
  }
7232
7432
  case "list-public-agents": {
@@ -7243,26 +7443,26 @@ app7.post("/config", async (c) => {
7243
7443
  const config = JSON.parse(readFileSync9(configPath2, "utf-8"));
7244
7444
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
7245
7445
  } catch {
7246
- console.error(`${TAG16} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
7446
+ console.error(`${TAG17} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
7247
7447
  }
7248
7448
  }
7249
7449
  } catch (err) {
7250
- console.error(`${TAG16} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
7450
+ console.error(`${TAG17} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
7251
7451
  }
7252
7452
  }
7253
- console.error(`${TAG16} config action=list-public-agents count=${agents.length}`);
7453
+ console.error(`${TAG17} config action=list-public-agents count=${agents.length}`);
7254
7454
  return c.json({ ok: true, agents });
7255
7455
  }
7256
7456
  case "schema": {
7257
7457
  const text = serializeWhatsAppSchema();
7258
- console.error(`${TAG16} config action=schema`);
7458
+ console.error(`${TAG17} config action=schema`);
7259
7459
  return c.json({ ok: true, text });
7260
7460
  }
7261
7461
  case "list-groups": {
7262
7462
  const groupAccountId = accountId ?? "default";
7263
7463
  const sock = getSocket(groupAccountId);
7264
7464
  if (!sock) {
7265
- console.error(`${TAG16} config action=list-groups error="not connected" accountId=${groupAccountId}`);
7465
+ console.error(`${TAG17} config action=list-groups error="not connected" accountId=${groupAccountId}`);
7266
7466
  return c.json({ ok: false, error: `WhatsApp account "${groupAccountId}" is not connected. Connect first, then retry.` });
7267
7467
  }
7268
7468
  try {
@@ -7272,10 +7472,10 @@ app7.post("/config", async (c) => {
7272
7472
  name: g.subject ?? g.id,
7273
7473
  participantCount: Array.isArray(g.participants) ? g.participants.length : 0
7274
7474
  }));
7275
- console.error(`${TAG16} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
7475
+ console.error(`${TAG17} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
7276
7476
  return c.json({ ok: true, groups });
7277
7477
  } catch (err) {
7278
- console.error(`${TAG16} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
7478
+ console.error(`${TAG17} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
7279
7479
  return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
7280
7480
  }
7281
7481
  }
@@ -7285,12 +7485,12 @@ app7.post("/config", async (c) => {
7285
7485
  }
7286
7486
  const result = updateConfig(account.accountDir, fields);
7287
7487
  const fieldNames = Object.keys(fields);
7288
- console.error(`${TAG16} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
7488
+ console.error(`${TAG17} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
7289
7489
  return c.json(result, result.ok ? 200 : 400);
7290
7490
  }
7291
7491
  case "get-config": {
7292
7492
  const waConfig = getConfig(account.accountDir);
7293
- console.error(`${TAG16} config action=get-config`);
7493
+ console.error(`${TAG17} config action=get-config`);
7294
7494
  return c.json({ ok: true, config: waConfig });
7295
7495
  }
7296
7496
  default:
@@ -7300,7 +7500,7 @@ app7.post("/config", async (c) => {
7300
7500
  );
7301
7501
  }
7302
7502
  } catch (err) {
7303
- console.error(`${TAG16} config error: ${String(err)}`);
7503
+ console.error(`${TAG17} config error: ${String(err)}`);
7304
7504
  return c.json({ ok: false, error: String(err) }, 500);
7305
7505
  }
7306
7506
  });
@@ -7322,16 +7522,16 @@ app7.post("/send-document", async (c) => {
7322
7522
  const accountResolved = realpathSync2(accountDir);
7323
7523
  if (!resolvedPath.startsWith(accountResolved + "/")) {
7324
7524
  const sanitised = filePath.replace(accountDir, "<account>/");
7325
- console.error(`${TAG16} send-document REJECTED path=${sanitised} reason=outside_account_directory`);
7525
+ console.error(`${TAG17} send-document REJECTED path=${sanitised} reason=outside_account_directory`);
7326
7526
  return c.json({ error: "Access denied: file is outside the account directory" }, 403);
7327
7527
  }
7328
7528
  } catch (err) {
7329
7529
  const code = err.code;
7330
7530
  if (code === "ENOENT") {
7331
- console.error(`${TAG16} send-document ENOENT path=${filePath}`);
7531
+ console.error(`${TAG17} send-document ENOENT path=${filePath}`);
7332
7532
  return c.json({ error: `File not found: ${filePath}` }, 404);
7333
7533
  }
7334
- console.error(`${TAG16} send-document path error: ${String(err)}`);
7534
+ console.error(`${TAG17} send-document path error: ${String(err)}`);
7335
7535
  return c.json({ error: String(err) }, 500);
7336
7536
  }
7337
7537
  const fileStat = await stat3(resolvedPath);
@@ -7353,11 +7553,11 @@ app7.post("/send-document", async (c) => {
7353
7553
  caption
7354
7554
  }, { accountId });
7355
7555
  console.error(
7356
- `${TAG16} send-document to=${to} size=${fileStat.size} mime=${mimetype} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
7556
+ `${TAG17} send-document to=${to} size=${fileStat.size} mime=${mimetype} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
7357
7557
  );
7358
7558
  return c.json(result);
7359
7559
  } catch (err) {
7360
- console.error(`${TAG16} send-document error: ${String(err)}`);
7560
+ console.error(`${TAG17} send-document error: ${String(err)}`);
7361
7561
  return c.json({ error: String(err) }, 500);
7362
7562
  }
7363
7563
  });
@@ -7367,11 +7567,11 @@ app7.get("/activity", (c) => {
7367
7567
  const result = getChannelActivity(accountId);
7368
7568
  const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
7369
7569
  console.error(
7370
- `${TAG16} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
7570
+ `${TAG17} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
7371
7571
  );
7372
7572
  return c.json(result);
7373
7573
  } catch (err) {
7374
- console.error(`${TAG16} activity error: ${String(err)}`);
7574
+ console.error(`${TAG17} activity error: ${String(err)}`);
7375
7575
  return c.json({ error: String(err) }, 500);
7376
7576
  }
7377
7577
  });
@@ -7390,10 +7590,10 @@ app7.get("/conversations", (c) => {
7390
7590
  };
7391
7591
  });
7392
7592
  conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
7393
- console.error(`${TAG16} conversations account=${accountId} count=${conversations.length}`);
7593
+ console.error(`${TAG17} conversations account=${accountId} count=${conversations.length}`);
7394
7594
  return c.json({ conversations });
7395
7595
  } catch (err) {
7396
- console.error(`${TAG16} conversations error: ${String(err)}`);
7596
+ console.error(`${TAG17} conversations error: ${String(err)}`);
7397
7597
  return c.json({ error: String(err) }, 500);
7398
7598
  }
7399
7599
  });
@@ -7408,10 +7608,10 @@ app7.get("/messages", (c) => {
7408
7608
  const limit = limitParam ? parseInt(limitParam, 10) : void 0;
7409
7609
  const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
7410
7610
  const messages = getMessages(accountId, jid, effectiveLimit);
7411
- console.error(`${TAG16} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
7611
+ console.error(`${TAG17} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
7412
7612
  return c.json({ messages });
7413
7613
  } catch (err) {
7414
- console.error(`${TAG16} messages error: ${String(err)}`);
7614
+ console.error(`${TAG17} messages error: ${String(err)}`);
7415
7615
  return c.json({ error: String(err) }, 500);
7416
7616
  }
7417
7617
  });
@@ -7423,12 +7623,12 @@ app7.get("/group-info", async (c) => {
7423
7623
  return c.json({ error: "Missing required parameter: jid" }, 400);
7424
7624
  }
7425
7625
  if (!isGroupJid(jid)) {
7426
- console.error(`${TAG16} group-info error="not a group JID" jid=${jid} account=${accountId}`);
7626
+ console.error(`${TAG17} group-info error="not a group JID" jid=${jid} account=${accountId}`);
7427
7627
  return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
7428
7628
  }
7429
7629
  const sock = getSocket(accountId);
7430
7630
  if (!sock) {
7431
- console.error(`${TAG16} group-info error="not connected" account=${accountId}`);
7631
+ console.error(`${TAG17} group-info error="not connected" account=${accountId}`);
7432
7632
  return c.json({ error: `WhatsApp account "${accountId}" is not connected. Connect first, then retry.` }, 400);
7433
7633
  }
7434
7634
  const meta = await sock.groupMetadata(jid);
@@ -7441,10 +7641,10 @@ app7.get("/group-info", async (c) => {
7441
7641
  participantCount: meta.participants.length,
7442
7642
  participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
7443
7643
  };
7444
- console.error(`${TAG16} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
7644
+ console.error(`${TAG17} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
7445
7645
  return c.json(result);
7446
7646
  } catch (err) {
7447
- console.error(`${TAG16} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
7647
+ console.error(`${TAG17} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
7448
7648
  return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
7449
7649
  }
7450
7650
  });
@@ -8325,7 +8525,7 @@ var app11 = new Hono();
8325
8525
  app11.post("/cancel", requireAdminSession, async (c) => {
8326
8526
  const session_key = c.var.sessionKey;
8327
8527
  try {
8328
- const { interruptClient: interruptClient2 } = await import("./client-pool-4YDRTKAT.js");
8528
+ const { interruptClient: interruptClient2 } = await import("./client-pool-S4UZCYDJ.js");
8329
8529
  await interruptClient2(session_key);
8330
8530
  return c.json({ ok: true });
8331
8531
  } catch (err) {
@@ -9478,13 +9678,13 @@ async function cdpNavigateNewTab(url, opts = {}) {
9478
9678
  // server/routes/admin/device-browser.ts
9479
9679
  var app19 = new Hono();
9480
9680
  app19.post("/navigate", async (c) => {
9481
- const TAG17 = "[device-url:click]";
9681
+ const TAG18 = "[device-url:click]";
9482
9682
  let body;
9483
9683
  try {
9484
9684
  body = await c.req.json();
9485
9685
  } catch (err) {
9486
9686
  const detail = err instanceof Error ? err.message : String(err);
9487
- console.error(`${TAG17} reject reason=body-not-json detail=${detail} browser=fallback navigateResult=error`);
9687
+ console.error(`${TAG18} reject reason=body-not-json detail=${detail} browser=fallback navigateResult=error`);
9488
9688
  return c.json(
9489
9689
  { ok: false, navigateResult: "error", browser: "fallback", detail: "Request body was not valid JSON" },
9490
9690
  400
@@ -9494,7 +9694,7 @@ app19.post("/navigate", async (c) => {
9494
9694
  const intent = typeof body.intent === "string" ? body.intent : "";
9495
9695
  const hostname2 = typeof body.hostname === "string" ? body.hostname : "";
9496
9696
  if (!url) {
9497
- console.error(`${TAG17} reject reason=missing-url intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`);
9697
+ console.error(`${TAG18} reject reason=missing-url intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`);
9498
9698
  return c.json(
9499
9699
  { ok: false, navigateResult: "error", browser: "fallback", detail: "url field is required" },
9500
9700
  400
@@ -9504,7 +9704,7 @@ app19.post("/navigate", async (c) => {
9504
9704
  try {
9505
9705
  parsed = new URL(url);
9506
9706
  } catch {
9507
- console.error(`${TAG17} reject reason=url-malformed intent=${JSON.stringify(intent)} url=${url} browser=fallback navigateResult=error`);
9707
+ console.error(`${TAG18} reject reason=url-malformed intent=${JSON.stringify(intent)} url=${url} browser=fallback navigateResult=error`);
9508
9708
  return c.json(
9509
9709
  { ok: false, navigateResult: "error", browser: "fallback", detail: "url is not a valid URL" },
9510
9710
  400
@@ -9512,7 +9712,7 @@ app19.post("/navigate", async (c) => {
9512
9712
  }
9513
9713
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
9514
9714
  console.error(
9515
- `${TAG17} reject reason=scheme-not-allowed scheme=${parsed.protocol} intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`
9715
+ `${TAG18} reject reason=scheme-not-allowed scheme=${parsed.protocol} intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`
9516
9716
  );
9517
9717
  return c.json(
9518
9718
  {
@@ -9528,7 +9728,7 @@ app19.post("/navigate", async (c) => {
9528
9728
  const cdpOk = await ensureCdp(transport);
9529
9729
  if (!cdpOk) {
9530
9730
  console.error(
9531
- `${TAG17} intent=${JSON.stringify(intent)} browser=fallback navigateResult=cdp-unreachable hostname=${JSON.stringify(hostname2)}`
9731
+ `${TAG18} intent=${JSON.stringify(intent)} browser=fallback navigateResult=cdp-unreachable hostname=${JSON.stringify(hostname2)}`
9532
9732
  );
9533
9733
  return c.json(
9534
9734
  {
@@ -9544,7 +9744,7 @@ app19.post("/navigate", async (c) => {
9544
9744
  const browser = outcome.result === "ok" ? "vnc" : "fallback";
9545
9745
  const detailStr = outcome.detail ? ` detail=${JSON.stringify(outcome.detail.length > 230 ? outcome.detail.slice(0, 227) + "..." : outcome.detail)}` : "";
9546
9746
  console.error(
9547
- `${TAG17} intent=${JSON.stringify(intent)} browser=${browser} navigateResult=${outcome.result} hostname=${JSON.stringify(hostname2)} targetId=${outcome.targetId ?? "none"}${detailStr}`
9747
+ `${TAG18} intent=${JSON.stringify(intent)} browser=${browser} navigateResult=${outcome.result} hostname=${JSON.stringify(hostname2)} targetId=${outcome.targetId ?? "none"}${detailStr}`
9548
9748
  );
9549
9749
  if (outcome.result !== "ok") {
9550
9750
  return c.json(
@@ -9575,18 +9775,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
9575
9775
  ]);
9576
9776
  var app20 = new Hono();
9577
9777
  app20.post("/", async (c) => {
9578
- const TAG17 = "[admin:events]";
9778
+ const TAG18 = "[admin:events]";
9579
9779
  let body;
9580
9780
  try {
9581
9781
  body = await c.req.json();
9582
9782
  } catch (err) {
9583
9783
  const detail = err instanceof Error ? err.message : String(err);
9584
- console.error(`${TAG17} reject reason=body-not-json detail=${detail}`);
9784
+ console.error(`${TAG18} reject reason=body-not-json detail=${detail}`);
9585
9785
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
9586
9786
  }
9587
9787
  const event = typeof body.event === "string" ? body.event : "";
9588
9788
  if (!ALLOWED_EVENTS.has(event)) {
9589
- console.error(`${TAG17} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
9789
+ console.error(`${TAG18} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
9590
9790
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
9591
9791
  }
9592
9792
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};