@automagik/omni 2.260317.3 → 2.260320.2

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.
@@ -27890,6 +27890,19 @@ async function executeLogAction(config2, context2, _deps) {
27890
27890
  };
27891
27891
  }
27892
27892
  }
27893
+ function extractMessages(context2) {
27894
+ if (context2.debounce?.messages && context2.debounce.messages.length > 0) {
27895
+ const messages = context2.debounce.messages.map((m2) => m2.text).filter((t) => !!t);
27896
+ if (messages.length === 0) {
27897
+ return { error: "no text content found in debounced messages" };
27898
+ }
27899
+ return messages;
27900
+ }
27901
+ const messageContent = context2.payload.content ?? context2.payload.text ?? "";
27902
+ if (!messageContent)
27903
+ return { error: "message content not found in payload" };
27904
+ return [messageContent];
27905
+ }
27893
27906
  function extractAgentCallContext(config2, context2) {
27894
27907
  const instanceId = config2.providerId ? substituteTemplate(config2.providerId, context2) : context2.payload.instanceId;
27895
27908
  if (!instanceId) {
@@ -27903,9 +27916,9 @@ function extractAgentCallContext(config2, context2) {
27903
27916
  return { error: "chatId not found in payload" };
27904
27917
  if (!senderId)
27905
27918
  return { error: "senderId not found in payload" };
27906
- const messageContent = context2.payload.content ?? context2.payload.text ?? "";
27907
- if (!messageContent)
27908
- return { error: "message content not found in payload" };
27919
+ const messagesResult = extractMessages(context2);
27920
+ if ("error" in messagesResult)
27921
+ return messagesResult;
27909
27922
  const agentId = substituteTemplate(config2.agentId, context2);
27910
27923
  if (!agentId)
27911
27924
  return { error: "agentId is required" };
@@ -27916,7 +27929,7 @@ function extractAgentCallContext(config2, context2) {
27916
27929
  chatId,
27917
27930
  senderId,
27918
27931
  senderName,
27919
- messages: [messageContent]
27932
+ messages: messagesResult
27920
27933
  }
27921
27934
  };
27922
27935
  }
@@ -29510,7 +29523,7 @@ class GenieClient {
29510
29523
  this.targetAgentTemplate = config2.targetAgent;
29511
29524
  this.agentRole = config2.agentRole;
29512
29525
  this.autoSpawn = config2.autoSpawn ?? true;
29513
- this.autoSpawnDir = config2.autoSpawnDir ?? join(homedir(), "workspace");
29526
+ this.autoSpawnDir = config2.autoSpawnDir ?? "";
29514
29527
  this.hasTemplates = /\{\w+\}/.test(this.teamNameTemplate) || /\{\w+\}/.test(this.agentNameTemplate) || /\{\w+\}/.test(this.targetAgentTemplate);
29515
29528
  }
29516
29529
  isTeamKnown(teamName) {
@@ -222904,7 +222917,7 @@ var init_sentry_scrub = __esm(() => {
222904
222917
  var require_package8 = __commonJS((exports, module) => {
222905
222918
  module.exports = {
222906
222919
  name: "@omni/api",
222907
- version: "2.260317.3",
222920
+ version: "2.260320.2",
222908
222921
  type: "module",
222909
222922
  exports: {
222910
222923
  ".": {
@@ -331865,7 +331878,7 @@ var init_instances3 = __esm(() => {
331865
331878
  slackAppToken: exports_external.string().optional().nullable().describe("Slack app token (persisted for reconnection)"),
331866
331879
  slackSigningSecret: exports_external.string().optional().nullable().describe("Slack signing secret (persisted for reconnection)"),
331867
331880
  readReceipts: exports_external.enum(["on", "off", "exclude-self"]).default("on").describe("Read receipt mode: on (default), off, or exclude-self (skip receipts for the instance own number)"),
331868
- groupHistorySize: exports_external.number().int().min(0).max(200).default(50).describe("Number of context messages to include for group chats when dispatching to agent (0 = disabled, max 200)"),
331881
+ groupHistorySize: exports_external.number().int().min(0).max(200).default(50).describe("Number of context messages to include when dispatching to agent. Groups use the full value; DMs are capped at 20. (0 = disabled, max 200)"),
331869
331882
  reactionAck: exports_external.enum(["on", "off"]).default("off").describe("Reaction ack mode: on to send a reaction while agent processes"),
331870
331883
  reactionAckEmoji: exports_external.record(exports_external.string()).optional().nullable().describe('Per-channel emoji map for reaction ack (e.g. {"whatsapp":"\\u2705"})'),
331871
331884
  ackTimeoutMs: exports_external.number().int().min(0).max(120000).default(30000).describe("Ack timeout in milliseconds (max 120000)")
@@ -333756,6 +333769,19 @@ async function resolveMessageFromRef(services, ref) {
333756
333769
  }
333757
333770
  return found;
333758
333771
  }
333772
+ async function verifyMessageInstanceOwnership(services, message2, instanceId) {
333773
+ if (!message2.chatId)
333774
+ return;
333775
+ const chat2 = await services.chats.getById(message2.chatId);
333776
+ if (chat2 && chat2.instanceId !== instanceId) {
333777
+ throw new OmniError({
333778
+ code: ERROR_CODES.FORBIDDEN,
333779
+ message: "Message does not belong to this instance",
333780
+ context: { instanceId, messageInstanceId: chat2.instanceId },
333781
+ recoverable: false
333782
+ });
333783
+ }
333784
+ }
333759
333785
  var log77, mediaDownloadLog, messagesRoutes, UUID_REGEX, MessageSourceSchema, MessageTypeSchema, MessageStatusSchema, DeliveryStatusSchema, listQuerySchema12, createMessageSchema, updateMessageSchema, recordEditSchema, addReactionSchema, removeReactionSchema, updateDeliveryStatusSchema, MentionSchema, sendTextSchema, sendMediaSchema, sendReactionSchema, sendStickerSchema, sendContactSchema, sendLocationSchema, messageRefSchema, _mediaStorageForDownload = null, sendTtsSchema, forwardMessageSchema, sendPresenceSchema, markMessageReadSchema, markBatchReadSchema, sendPollSchema, sendEmbedSchema, editMessageChannelSchema, deleteMessageChannelSchema, starMessageSchema;
333760
333786
  var init_messages5 = __esm(() => {
333761
333787
  init_dist6();
@@ -335035,10 +335061,28 @@ var init_messages5 = __esm(() => {
335035
335061
  recoverable: false
335036
335062
  });
335037
335063
  }
335038
- await plugin6.editMessage(instanceId, channelId, messageId, text3);
335064
+ let resolvedMessageId = messageId;
335065
+ if (isUUID(messageId)) {
335066
+ const message2 = await services.messages.getById(messageId);
335067
+ await verifyMessageInstanceOwnership(services, message2, instanceId);
335068
+ resolvedMessageId = message2.externalId;
335069
+ log77.debug("Resolved internal UUID to external ID", { messageId, externalId: resolvedMessageId });
335070
+ }
335071
+ try {
335072
+ await plugin6.editMessage(instanceId, channelId, resolvedMessageId, text3);
335073
+ } catch (error2) {
335074
+ if (error2 instanceof OmniError)
335075
+ throw error2;
335076
+ throw new OmniError({
335077
+ code: ERROR_CODES.CHANNEL_SEND_FAILED,
335078
+ message: `Failed to edit message: ${error2 instanceof Error ? error2.message : String(error2)}`,
335079
+ context: { instanceId, channelType: instance4.channel, messageId: resolvedMessageId },
335080
+ recoverable: false
335081
+ });
335082
+ }
335039
335083
  return c.json({
335040
335084
  success: true,
335041
- data: { messageId, edited: true }
335085
+ data: { messageId, externalId: resolvedMessageId, edited: true }
335042
335086
  });
335043
335087
  });
335044
335088
  messagesRoutes.post("/delete-channel", zValidator("json", deleteMessageChannelSchema), async (c) => {
@@ -337611,6 +337655,93 @@ function buildWhatsAppMessageContext(rawPayload, chatId, instance4, text3) {
337611
337655
  return { isDirectMessage, mentionsBot, isReplyToBot, text: text3 };
337612
337656
  }
337613
337657
 
337658
+ // ../api/src/plugins/message-debouncer.ts
337659
+ class MessageDebouncer {
337660
+ buffers = new Map;
337661
+ timers = new Map;
337662
+ inFlight = new Set;
337663
+ onFlush;
337664
+ constructor(onFlush) {
337665
+ this.onFlush = onFlush;
337666
+ }
337667
+ getChatKey(instanceId, chatId) {
337668
+ return `${instanceId}:${chatId}`;
337669
+ }
337670
+ buffer(instanceId, chatId, message2, config4) {
337671
+ const chatKey = this.getChatKey(instanceId, chatId);
337672
+ const buffer3 = this.buffers.get(chatKey) ?? [];
337673
+ buffer3.push(message2);
337674
+ this.buffers.set(chatKey, buffer3);
337675
+ if (this.inFlight.has(chatKey))
337676
+ return;
337677
+ this.restartTimer(chatKey, config4);
337678
+ }
337679
+ onUserTyping(instanceId, chatId, config4) {
337680
+ const chatKey = this.getChatKey(instanceId, chatId);
337681
+ if (config4.restartOnTyping && this.buffers.has(chatKey)) {
337682
+ log83.debug("Restarting debounce timer on user typing", { chatKey });
337683
+ this.restartTimer(chatKey, config4);
337684
+ }
337685
+ }
337686
+ restartTimer(chatKey, config4) {
337687
+ const existing = this.timers.get(chatKey);
337688
+ if (config4.mode === "fixed" && existing)
337689
+ return;
337690
+ if (existing)
337691
+ clearTimeout(existing);
337692
+ let delay2;
337693
+ switch (config4.mode) {
337694
+ case "disabled":
337695
+ delay2 = 0;
337696
+ break;
337697
+ case "fixed":
337698
+ delay2 = config4.minMs;
337699
+ break;
337700
+ case "randomized":
337701
+ delay2 = config4.minMs + Math.random() * (config4.maxMs - config4.minMs);
337702
+ break;
337703
+ default:
337704
+ delay2 = 0;
337705
+ }
337706
+ const timer2 = setTimeout(() => this.flush(chatKey), delay2);
337707
+ this.timers.set(chatKey, timer2);
337708
+ }
337709
+ async flush(chatKey) {
337710
+ const messages4 = this.buffers.get(chatKey);
337711
+ const timer2 = this.timers.get(chatKey);
337712
+ this.buffers.delete(chatKey);
337713
+ this.timers.delete(chatKey);
337714
+ if (timer2)
337715
+ clearTimeout(timer2);
337716
+ if (!messages4?.length)
337717
+ return;
337718
+ this.inFlight.add(chatKey);
337719
+ try {
337720
+ await this.onFlush(chatKey, messages4);
337721
+ } catch (error2) {
337722
+ log83.error("Error flushing debounced messages", { chatKey, error: String(error2) });
337723
+ } finally {
337724
+ this.inFlight.delete(chatKey);
337725
+ const pending = this.buffers.get(chatKey);
337726
+ if (pending?.length) {
337727
+ setTimeout(() => this.flush(chatKey), 0);
337728
+ }
337729
+ }
337730
+ }
337731
+ clear() {
337732
+ for (const timer2 of this.timers.values())
337733
+ clearTimeout(timer2);
337734
+ this.buffers.clear();
337735
+ this.timers.clear();
337736
+ this.inFlight.clear();
337737
+ }
337738
+ }
337739
+ var log83;
337740
+ var init_message_debouncer = __esm(() => {
337741
+ init_src();
337742
+ log83 = createLogger("message-debouncer");
337743
+ });
337744
+
337614
337745
  // ../api/src/plugins/session-storage.ts
337615
337746
  function scopeSessionKey(providerId, sessionKey) {
337616
337747
  return `provider:${providerId}:session:${sessionKey}`;
@@ -337699,7 +337830,7 @@ class RateLimiter {
337699
337830
  let timestamps = this.counters.get(key) ?? [];
337700
337831
  timestamps = timestamps.filter((ts) => now - ts < this.windowMs);
337701
337832
  if (timestamps.length >= maxPerMinute) {
337702
- log83.debug("Rate limit exceeded", { key, count: timestamps.length, limit: maxPerMinute });
337833
+ log84.debug("Rate limit exceeded", { key, count: timestamps.length, limit: maxPerMinute });
337703
337834
  return false;
337704
337835
  }
337705
337836
  timestamps.push(now);
@@ -337731,7 +337862,7 @@ class ReactionDedup {
337731
337862
  }
337732
337863
  const msgCount = this.messageCounters.get(messageId) ?? 0;
337733
337864
  if (msgCount >= this.maxPerMessage) {
337734
- log83.debug("Reaction per-message limit reached", { messageId, count: msgCount });
337865
+ log84.debug("Reaction per-message limit reached", { messageId, count: msgCount });
337735
337866
  return true;
337736
337867
  }
337737
337868
  this.seen.set(key, Date.now());
@@ -337754,73 +337885,6 @@ class ReactionDedup {
337754
337885
  return false;
337755
337886
  }
337756
337887
  }
337757
-
337758
- class MessageDebouncer {
337759
- buffers = new Map;
337760
- timers = new Map;
337761
- onFlush;
337762
- constructor(onFlush) {
337763
- this.onFlush = onFlush;
337764
- }
337765
- getChatKey(instanceId, chatId) {
337766
- return `${instanceId}:${chatId}`;
337767
- }
337768
- buffer(instanceId, chatId, message2, config4) {
337769
- const chatKey = this.getChatKey(instanceId, chatId);
337770
- const buffer3 = this.buffers.get(chatKey) ?? [];
337771
- buffer3.push(message2);
337772
- this.buffers.set(chatKey, buffer3);
337773
- this.restartTimer(chatKey, config4);
337774
- }
337775
- onUserTyping(instanceId, chatId, config4) {
337776
- const chatKey = this.getChatKey(instanceId, chatId);
337777
- if (config4.restartOnTyping && this.buffers.has(chatKey)) {
337778
- log83.debug("Restarting debounce timer on user typing", { chatKey });
337779
- this.restartTimer(chatKey, config4);
337780
- }
337781
- }
337782
- restartTimer(chatKey, config4) {
337783
- const existing = this.timers.get(chatKey);
337784
- if (config4.mode === "fixed" && existing)
337785
- return;
337786
- if (existing)
337787
- clearTimeout(existing);
337788
- let delay2;
337789
- switch (config4.mode) {
337790
- case "disabled":
337791
- delay2 = 0;
337792
- break;
337793
- case "fixed":
337794
- delay2 = config4.minMs;
337795
- break;
337796
- case "randomized":
337797
- delay2 = config4.minMs + Math.random() * (config4.maxMs - config4.minMs);
337798
- break;
337799
- default:
337800
- delay2 = 0;
337801
- }
337802
- const timer2 = setTimeout(() => this.flush(chatKey), delay2);
337803
- this.timers.set(chatKey, timer2);
337804
- }
337805
- async flush(chatKey) {
337806
- const messages4 = this.buffers.get(chatKey);
337807
- this.buffers.delete(chatKey);
337808
- this.timers.delete(chatKey);
337809
- if (messages4?.length) {
337810
- try {
337811
- await this.onFlush(chatKey, messages4);
337812
- } catch (error2) {
337813
- log83.error("Error flushing debounced messages", { chatKey, error: String(error2) });
337814
- }
337815
- }
337816
- }
337817
- clear() {
337818
- for (const timer2 of this.timers.values())
337819
- clearTimeout(timer2);
337820
- this.buffers.clear();
337821
- this.timers.clear();
337822
- }
337823
- }
337824
337888
  function getDebounceConfig(instance4) {
337825
337889
  return {
337826
337890
  mode: instance4.messageDebounceMode ?? "disabled",
@@ -337906,7 +337970,7 @@ async function sendTypingPresence(channel4, instanceId, chatId, state) {
337906
337970
  await plugin6.sendTyping(instanceId, chatId, duration);
337907
337971
  }
337908
337972
  } catch (error2) {
337909
- log83.debug("Failed to send typing presence", { error: String(error2) });
337973
+ log84.debug("Failed to send typing presence", { error: String(error2) });
337910
337974
  }
337911
337975
  }
337912
337976
  async function sendTextMessage5(channel4, instanceId, chatId, text3, messageFormatMode = "convert", replyTo, correlationId, senderAgentId) {
@@ -337922,7 +337986,7 @@ async function sendTextMessage5(channel4, instanceId, chatId, text3, messageForm
337922
337986
  }
337923
337987
  async function sendErrorFeedback(channel4, instanceId, chatId, error2) {
337924
337988
  const errorMsg = error2 instanceof Error ? error2.message : String(error2);
337925
- log83.error("agent_dispatch_error", { channel: channel4, instanceId, chatId, error: errorMsg });
337989
+ log84.error("agent_dispatch_error", { channel: channel4, instanceId, chatId, error: errorMsg });
337926
337990
  const text3 = "\u26A0\uFE0F Sorry, I ran into an issue processing your message. Please try again.";
337927
337991
  await sendTextMessage5(channel4, instanceId, chatId, text3);
337928
337992
  }
@@ -337972,7 +338036,7 @@ function resolveMediaPath2(mediaUrl) {
337972
338036
  const fullPath = resolve2(MEDIA_BASE_PATH3, relativePath);
337973
338037
  const basePath = resolve2(MEDIA_BASE_PATH3);
337974
338038
  if (!fullPath.startsWith(`${basePath}/`) && fullPath !== basePath) {
337975
- log83.warn("Path traversal attempt blocked", { mediaUrl, resolved: fullPath, basePath });
338039
+ log84.warn("Path traversal attempt blocked", { mediaUrl, resolved: fullPath, basePath });
337976
338040
  return null;
337977
338041
  }
337978
338042
  return fullPath;
@@ -338029,7 +338093,7 @@ async function waitForMediaProcessing(services, instanceId, chatId, externalId,
338029
338093
  return MEDIA_WAIT_NULL;
338030
338094
  const chat2 = await services.chats.findByExternalIdSmart(instanceId, chatId);
338031
338095
  if (!chat2) {
338032
- log83.warn("Chat not found for media wait", { instanceId, chatId });
338096
+ log84.warn("Chat not found for media wait", { instanceId, chatId });
338033
338097
  return MEDIA_WAIT_NULL;
338034
338098
  }
338035
338099
  const deadline = Date.now() + 60000;
@@ -338037,14 +338101,14 @@ async function waitForMediaProcessing(services, instanceId, chatId, externalId,
338037
338101
  const msg = await services.messages.getByExternalId(chat2.id, externalId);
338038
338102
  const result = checkProcessedColumn(msg, column2);
338039
338103
  if (result === "error") {
338040
- log83.warn("Media processing failed", { instanceId, chatId, externalId, error: msg?.[column2] });
338104
+ log84.warn("Media processing failed", { instanceId, chatId, externalId, error: msg?.[column2] });
338041
338105
  return MEDIA_WAIT_NULL;
338042
338106
  }
338043
338107
  if (result !== "pending")
338044
338108
  return result;
338045
338109
  await sleep4(pollMs);
338046
338110
  }
338047
- log83.warn("Media processing wait timed out", { instanceId, chatId, externalId, contentType });
338111
+ log84.warn("Media processing wait timed out", { instanceId, chatId, externalId, contentType });
338048
338112
  return MEDIA_WAIT_NULL;
338049
338113
  }
338050
338114
  function formatProcessedMedia(contentType, fullPath, processedText, includePath, sendMediaPathTypes) {
@@ -338082,12 +338146,11 @@ async function resolveQuotedMessage(services, instanceId, chatId, replyToId) {
338082
338146
  const content = getMessageContentText(quoted);
338083
338147
  if (!content)
338084
338148
  return null;
338085
- const maxLen = 500;
338086
- const truncated = content.length > maxLen ? `${content.slice(0, maxLen)}...` : content;
338149
+ const truncated = content.length > QUOTED_MESSAGE_MAX_CHARS ? `${content.slice(0, QUOTED_MESSAGE_MAX_CHARS)}...` : content;
338087
338150
  const timeStr = time3 ? ` at ${time3}` : "";
338088
338151
  return `[Quoting ${sender}${timeStr}: ${truncated}]`;
338089
338152
  } catch (error2) {
338090
- log83.debug("Failed to resolve quoted message", { replyToId, error: String(error2) });
338153
+ log84.debug("Failed to resolve quoted message", { replyToId, error: String(error2) });
338091
338154
  return null;
338092
338155
  }
338093
338156
  }
@@ -338160,11 +338223,11 @@ async function resolveContactName2(services, instanceId, jid, cacheMap) {
338160
338223
  try {
338161
338224
  const chat2 = await services.chats.findByExternalIdSmart(instanceId, jid);
338162
338225
  if (chat2?.name) {
338163
- log83.debug("Contact name from DB fallback", { jid, name: chat2.name });
338226
+ log84.debug("Contact name from DB fallback", { jid, name: chat2.name });
338164
338227
  return chat2.name;
338165
338228
  }
338166
338229
  } catch (error2) {
338167
- log83.warn("Failed to query DB for contact", { jid, error: String(error2) });
338230
+ log84.warn("Failed to query DB for contact", { jid, error: String(error2) });
338168
338231
  }
338169
338232
  return null;
338170
338233
  }
@@ -338196,14 +338259,14 @@ async function applyJidMentionReplacement(services, instanceId, jid, jidToName,
338196
338259
  async function replaceMentionsWithContactNames(services, instanceId, text3, mentionedJids, mentionedContacts) {
338197
338260
  if (!mentionedJids?.length)
338198
338261
  return text3;
338199
- log83.debug("Starting mention replacement", { mentionCount: mentionedJids.length });
338262
+ log84.debug("Starting mention replacement", { mentionCount: mentionedJids.length });
338200
338263
  const jidToName = buildJidNameMap(mentionedContacts);
338201
338264
  const stats = { resolved: 0, replaced: 0, unresolved: 0, skipped: 0 };
338202
338265
  let replacedText = text3;
338203
338266
  for (const jid of mentionedJids) {
338204
338267
  replacedText = await applyJidMentionReplacement(services, instanceId, jid, jidToName, replacedText, stats);
338205
338268
  }
338206
- log83.debug("Mention replacement complete", {
338269
+ log84.debug("Mention replacement complete", {
338207
338270
  original: text3,
338208
338271
  replaced: replacedText,
338209
338272
  mentionCount: mentionedJids.length,
@@ -338272,7 +338335,7 @@ async function fetchSenderMetadata(services, channel4, instanceId, senderId) {
338272
338335
  platformUsername: identity?.platformUsername ?? undefined
338273
338336
  };
338274
338337
  } catch (error2) {
338275
- log83.debug("Failed to fetch sender identity metadata", { error: String(error2) });
338338
+ log84.debug("Failed to fetch sender identity metadata", { error: String(error2) });
338276
338339
  return {};
338277
338340
  }
338278
338341
  }
@@ -338286,7 +338349,7 @@ async function fetchChatMetadata(services, instanceId, chatId, chatType) {
338286
338349
  participantCount: chat2?.participantCount ?? undefined
338287
338350
  };
338288
338351
  } catch (error2) {
338289
- log83.debug("Failed to fetch chat metadata", { error: String(error2) });
338352
+ log84.debug("Failed to fetch chat metadata", { error: String(error2) });
338290
338353
  return {};
338291
338354
  }
338292
338355
  }
@@ -338308,7 +338371,7 @@ async function routeStreamDelta(sender, delta) {
338308
338371
  }
338309
338372
  async function resolveStreamingCapabilities(services, instance4, channel4, chatId, traceId, db2) {
338310
338373
  if (!instance4.agentStreamMode) {
338311
- log83.debug("Stream guard: agentStreamMode is falsy", {
338374
+ log84.debug("Stream guard: agentStreamMode is falsy", {
338312
338375
  instanceId: instance4.id,
338313
338376
  agentStreamMode: instance4.agentStreamMode,
338314
338377
  chatId
@@ -338317,7 +338380,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
338317
338380
  }
338318
338381
  const provider = await getAgentProvider(services, instance4, db2);
338319
338382
  if (!provider?.triggerStream) {
338320
- log83.debug("Stream guard: provider has no triggerStream", {
338383
+ log84.debug("Stream guard: provider has no triggerStream", {
338321
338384
  instanceId: instance4.id,
338322
338385
  hasProvider: !!provider,
338323
338386
  chatId
@@ -338326,7 +338389,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
338326
338389
  }
338327
338390
  const plugin6 = await getPlugin(channel4);
338328
338391
  if (!plugin6?.capabilities?.canStreamResponse || !plugin6.createStreamSender) {
338329
- log83.debug("Stream guard: channel does not support streaming", {
338392
+ log84.debug("Stream guard: channel does not support streaming", {
338330
338393
  channel: channel4,
338331
338394
  canStream: plugin6?.capabilities?.canStreamResponse,
338332
338395
  chatId
@@ -338335,7 +338398,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
338335
338398
  }
338336
338399
  const streamKey = `${instance4.id}:${chatId}`;
338337
338400
  if (activeStreams.has(streamKey)) {
338338
- log83.info("Stream guard: parallel stream blocked, falling back to accumulate", {
338401
+ log84.info("Stream guard: parallel stream blocked, falling back to accumulate", {
338339
338402
  instanceId: instance4.id,
338340
338403
  chatId,
338341
338404
  traceId
@@ -338358,7 +338421,7 @@ async function consumeStream(generator, sender, instanceId, chatId, traceId) {
338358
338421
  hadContent = true;
338359
338422
  await routeStreamDelta(sender, delta);
338360
338423
  }
338361
- log83.info("Streaming response complete", {
338424
+ log84.info("Streaming response complete", {
338362
338425
  instanceId,
338363
338426
  chatId,
338364
338427
  durationMs: Date.now() - startTime3,
@@ -338486,7 +338549,7 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
338486
338549
  }
338487
338550
  return streamResult;
338488
338551
  } catch (err) {
338489
- log83.error("Streaming dispatch failed, falling back", {
338552
+ log84.error("Streaming dispatch failed, falling back", {
338490
338553
  instanceId: instance4.id,
338491
338554
  chatId,
338492
338555
  error: String(err),
@@ -338536,20 +338599,26 @@ async function buildContextMessages(services, instance4, chatId, currentMessageI
338536
338599
  if (!chat2) {
338537
338600
  return [];
338538
338601
  }
338602
+ const effectiveLimit = chat2.chatType === "group" ? historyLimit : Math.min(historyLimit, DM_HISTORY_LIMIT);
338539
338603
  const messagesResult = await services.messages.list({
338540
338604
  chatId: chat2.id,
338541
- limit: historyLimit
338605
+ limit: effectiveLimit
338542
338606
  });
338543
338607
  const recentMessages = messagesResult.items;
338544
338608
  if (!recentMessages || recentMessages.length === 0) {
338545
338609
  return [];
338546
338610
  }
338547
338611
  const lastBotMessageIndex = recentMessages.findIndex((msg) => msg.isFromMe === true);
338548
- if (lastBotMessageIndex === -1 || lastBotMessageIndex === 0) {
338549
- return [];
338550
- }
338551
338612
  const currentMessageIdSet = new Set(currentMessageIds.filter(Boolean));
338552
- const contextMsgs = recentMessages.slice(0, lastBotMessageIndex).filter((msg) => !currentMessageIdSet.has(msg.externalId));
338613
+ let contextMsgs;
338614
+ if (chat2.chatType !== "group") {
338615
+ contextMsgs = recentMessages.filter((msg) => !currentMessageIdSet.has(msg.externalId));
338616
+ } else {
338617
+ if (lastBotMessageIndex === -1 || lastBotMessageIndex === 0) {
338618
+ return [];
338619
+ }
338620
+ contextMsgs = recentMessages.slice(0, lastBotMessageIndex).filter((msg) => !currentMessageIdSet.has(msg.externalId));
338621
+ }
338553
338622
  if (contextMsgs.length === 0) {
338554
338623
  return [];
338555
338624
  }
@@ -338564,7 +338633,7 @@ async function buildContextMessages(services, instance4, chatId, currentMessageI
338564
338633
  return `[${name}${time3 ? ` - ${time3}` : ""}] ${text3}`;
338565
338634
  });
338566
338635
  } catch (error2) {
338567
- log83.warn("Failed to build context messages", { error: error2, chatId, instanceId: instance4.id });
338636
+ log84.warn("Failed to build context messages", { error: error2, chatId, instanceId: instance4.id });
338568
338637
  return [];
338569
338638
  }
338570
338639
  }
@@ -338599,7 +338668,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
338599
338668
  return false;
338600
338669
  const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
338601
338670
  if (!messageTexts.length && !mediaFiles.length) {
338602
- log83.debug("No text or media content for provider trigger, skipping");
338671
+ log84.debug("No text or media content for provider trigger, skipping");
338603
338672
  return false;
338604
338673
  }
338605
338674
  if (!messageTexts.length && mediaFiles.length) {
@@ -338635,7 +338704,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
338635
338704
  recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
338636
338705
  await forwardToChainedInstance(instance4, parts, correlationId, messages4);
338637
338706
  }
338638
- log83.info("Agent response via IAgentProvider", {
338707
+ log84.info("Agent response via IAgentProvider", {
338639
338708
  instanceId: instance4.id,
338640
338709
  chatId,
338641
338710
  parts: result?.parts.length ?? 0,
@@ -338649,14 +338718,14 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
338649
338718
  async function dispatchViaLegacy(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId) {
338650
338719
  const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
338651
338720
  if (perThreadExtraContext?.length) {
338652
- log83.warn("per_thread context available but legacy dispatch path has limited support \u2014 prepending as text", {
338721
+ log84.warn("per_thread context available but legacy dispatch path has limited support \u2014 prepending as text", {
338653
338722
  instanceId: instance4.id,
338654
338723
  contextCount: perThreadExtraContext.length
338655
338724
  });
338656
338725
  messageTexts.unshift(...perThreadExtraContext);
338657
338726
  }
338658
338727
  if (!messageTexts.length && !mediaFiles.length) {
338659
- log83.debug("No text or media content in messages, skipping agent call");
338728
+ log84.debug("No text or media content in messages, skipping agent call");
338660
338729
  return;
338661
338730
  }
338662
338731
  if (!messageTexts.length && mediaFiles.length) {
@@ -338690,7 +338759,7 @@ async function dispatchViaLegacy(services, instance4, messages4, triggerType, ch
338690
338759
  recordJourneyCheckpoint(correlationId, "T8", JOURNEY_STAGES.T8);
338691
338760
  await sendResponseParts(channel4, instance4.id, chatId, parts, getSplitDelayConfig(instance4), _fmtMode, replyTo, correlationId, senderAgentId);
338692
338761
  recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
338693
- log83.info("Agent response via legacy runner", {
338762
+ log84.info("Agent response via legacy runner", {
338694
338763
  instanceId: instance4.id,
338695
338764
  chatId,
338696
338765
  parts: result.parts.length,
@@ -338710,14 +338779,14 @@ async function performSessionReset(instance4, sessionId, chatId, services, db2,
338710
338779
  sessionActuallyReset = true;
338711
338780
  }
338712
338781
  } catch (err) {
338713
- log83.warn("Failed to reset provider session", { error: String(err), instanceId: instance4.id, sessionId });
338782
+ log84.warn("Failed to reset provider session", { error: String(err), instanceId: instance4.id, sessionId });
338714
338783
  }
338715
338784
  if (sessionActuallyReset) {
338716
338785
  sessionActivityStore.recordReset(instance4.id, sessionId, Date.now());
338717
338786
  eventBus.publish("session.reset", { instanceId: instance4.id, sessionId, timestamp: Date.now() }, { instanceId: instance4.id, channelType: channel4 }).catch((err) => {
338718
- log83.warn("Failed to publish session.reset event", { error: String(err), instanceId: instance4.id, sessionId });
338787
+ log84.warn("Failed to publish session.reset event", { error: String(err), instanceId: instance4.id, sessionId });
338719
338788
  });
338720
- log83.info("Session reset triggered", {
338789
+ log84.info("Session reset triggered", {
338721
338790
  instanceId: instance4.id,
338722
338791
  sessionId,
338723
338792
  strategy: resetStrategy,
@@ -338760,7 +338829,7 @@ async function markPerThreadSessionInitialized(db2, instanceId, sessionId) {
338760
338829
  target: [agentSessions.instanceId, agentSessions.sessionKey],
338761
338830
  set: { lastUsedAt: now, updatedAt: now }
338762
338831
  });
338763
- log83.info("per_thread session initialized", { instanceId, sessionId });
338832
+ log84.info("per_thread session initialized", { instanceId, sessionId });
338764
338833
  }
338765
338834
  function mimeToContentType(mimeType) {
338766
338835
  if (mimeType.startsWith("audio/"))
@@ -338799,7 +338868,7 @@ async function processMediaFile(msg, mimeType, mediaService) {
338799
338868
  const result = await mediaService.process(localPath, mimeType, { caption: msg.content.caption });
338800
338869
  return result.success && result.content ? result.content : null;
338801
338870
  } catch (err) {
338802
- log83.debug("Media processing failed for history message", { error: String(err), messageId: msg.externalId });
338871
+ log84.debug("Media processing failed for history message", { error: String(err), messageId: msg.externalId });
338803
338872
  return null;
338804
338873
  } finally {
338805
338874
  if (ownedTempFile) {
@@ -338836,7 +338905,7 @@ async function processHistoryMessage2(msg, mediaService, reactFn, unreactFn) {
338836
338905
  async function fetchAndProcessThreadHistory(services, instance4, channel4, chatId, threadId2) {
338837
338906
  const plugin6 = await getPlugin(channel4);
338838
338907
  if (!plugin6?.fetchHistory) {
338839
- log83.debug("Channel plugin does not support fetchHistory", { instanceId: instance4.id, channel: channel4 });
338908
+ log84.debug("Channel plugin does not support fetchHistory", { instanceId: instance4.id, channel: channel4 });
338840
338909
  return [];
338841
338910
  }
338842
338911
  let historyResult;
@@ -338847,7 +338916,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
338847
338916
  limit: 200
338848
338917
  });
338849
338918
  } catch (err) {
338850
- log83.warn("fetchHistory failed, proceeding without thread context", {
338919
+ log84.warn("fetchHistory failed, proceeding without thread context", {
338851
338920
  error: String(err),
338852
338921
  instanceId: instance4.id,
338853
338922
  channel: channel4
@@ -338877,7 +338946,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
338877
338946
  const results = await Promise.all(batch.map((msg) => processHistoryMessage2(msg, mediaService, reactFn, unreactFn)));
338878
338947
  contextMessages.push(...results);
338879
338948
  }
338880
- log83.info("Thread history fetched", {
338949
+ log84.info("Thread history fetched", {
338881
338950
  instanceId: instance4.id,
338882
338951
  channel: channel4,
338883
338952
  chatId,
@@ -338888,7 +338957,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
338888
338957
  return contextMessages;
338889
338958
  }
338890
338959
  async function handlePerThreadLazyInit(services, instance4, channel4, chatId, threadId2, sessionId, db2) {
338891
- log83.info("per_thread lazy init", {
338960
+ log84.info("per_thread lazy init", {
338892
338961
  instanceId: instance4.id,
338893
338962
  channel: channel4,
338894
338963
  chatId,
@@ -338899,7 +338968,7 @@ async function handlePerThreadLazyInit(services, instance4, channel4, chatId, th
338899
338968
  try {
338900
338969
  await markPerThreadSessionInitialized(db2, instance4.id, sessionId);
338901
338970
  } catch (err) {
338902
- log83.warn("Failed to mark per_thread session initialized", {
338971
+ log84.warn("Failed to mark per_thread session initialized", {
338903
338972
  error: String(err),
338904
338973
  instanceId: instance4.id,
338905
338974
  sessionId
@@ -338941,7 +339010,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
338941
339010
  const ackHandle = startAck(plugin6, ackProvider, instance4.id, chatId, messageId, channel4, ackConfig);
338942
339011
  const personId = await resolvePersonId(services, channel4, instance4.id, senderId, firstMessage.metadata.personId);
338943
339012
  if (!personId) {
338944
- log83.warn("Could not resolve person ID, skipping agent", {
339013
+ log84.warn("Could not resolve person ID, skipping agent", {
338945
339014
  instanceId: instance4.id,
338946
339015
  chatId,
338947
339016
  senderId
@@ -338954,7 +339023,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
338954
339023
  const pushName = rawPayload.pushName ?? rawPayload.displayName;
338955
339024
  const senderName = await services.agentRunner.getSenderName(personId, pushName);
338956
339025
  const senderAgentId = await resolveDispatchSenderAgentId(db2, instance4);
338957
- log83.info("Dispatching to agent", {
339026
+ log84.info("Dispatching to agent", {
338958
339027
  instanceId: instance4.id,
338959
339028
  chatId,
338960
339029
  messageCount: messages4.length,
@@ -338967,7 +339036,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
338967
339036
  const agentAckMessage = inst.agentAckMessage ?? null;
338968
339037
  if (agentAckMessage) {
338969
339038
  sendTextMessage5(channel4, instance4.id, chatId, agentAckMessage).catch((err) => {
338970
- log83.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
339039
+ log84.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
338971
339040
  });
338972
339041
  }
338973
339042
  const perThreadExtraContext = await resolvePerThreadExtraContext(db2, services, instance4, channel4, chatId, senderId, firstMessage);
@@ -338980,7 +339049,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
338980
339049
  handled = await dispatchViaProvider(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, rawEvent, db2, perThreadExtraContext, senderAgentId);
338981
339050
  }
338982
339051
  } catch (providerError) {
338983
- log83.error("Provider dispatch failed, falling back to legacy", {
339052
+ log84.error("Provider dispatch failed, falling back to legacy", {
338984
339053
  instanceId: instance4.id,
338985
339054
  chatId,
338986
339055
  error: String(providerError),
@@ -338991,12 +339060,12 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
338991
339060
  ackHandle.remove();
338992
339061
  return;
338993
339062
  }
338994
- log83.debug("No IAgentProvider resolved or provider failed, using legacy agentRunner path", {
339063
+ log84.debug("No IAgentProvider resolved or provider failed, using legacy agentRunner path", {
338995
339064
  instanceId: instance4.id
338996
339065
  });
338997
339066
  await dispatchViaLegacy(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId);
338998
339067
  } catch (error2) {
338999
- log83.error("Failed to process agent response", {
339068
+ log84.error("Failed to process agent response", {
339000
339069
  instanceId: instance4.id,
339001
339070
  chatId,
339002
339071
  error: String(error2),
@@ -339040,7 +339109,7 @@ function createOpenClawProviderInstance(provider, instance4) {
339040
339109
  }
339041
339110
  function createAgnoProvider(provider, instance4) {
339042
339111
  if (!provider.apiKey) {
339043
- log83.warn("Provider has no API key, falling back to legacy path", { providerId: provider.id });
339112
+ log84.warn("Provider has no API key, falling back to legacy path", { providerId: provider.id });
339044
339113
  return null;
339045
339114
  }
339046
339115
  const client = createProviderClient({
@@ -339062,7 +339131,7 @@ function createClaudeCodeProviderInstance(provider, instance4, db2) {
339062
339131
  const schemaConfig = provider.schemaConfig ?? {};
339063
339132
  const projectPath = schemaConfig.projectPath;
339064
339133
  if (!projectPath) {
339065
- log83.error("Claude Code provider missing projectPath", { providerId: provider.id });
339134
+ log84.error("Claude Code provider missing projectPath", { providerId: provider.id });
339066
339135
  throw new Error("Claude Code provider requires schemaConfig.projectPath");
339067
339136
  }
339068
339137
  return new ClaudeCodeAgentProvider(provider.id, provider.name, {
@@ -339093,7 +339162,7 @@ function createWebhookProvider(provider) {
339093
339162
  }
339094
339163
  function createAgUiProviderInstance(provider, instance4) {
339095
339164
  if (!provider.apiKey) {
339096
- log83.warn("AG-UI provider has no API key, falling back to legacy path", { providerId: provider.id });
339165
+ log84.warn("AG-UI provider has no API key, falling back to legacy path", { providerId: provider.id });
339097
339166
  return null;
339098
339167
  }
339099
339168
  const schemaConfig = provider.schemaConfig ?? {};
@@ -339112,7 +339181,7 @@ function createAgUiProviderInstance(provider, instance4) {
339112
339181
  }
339113
339182
  function createA2AProviderInstance(provider, instance4) {
339114
339183
  if (!provider.apiKey) {
339115
- log83.warn("A2A provider has no API key, falling back to legacy path", { providerId: provider.id });
339184
+ log84.warn("A2A provider has no API key, falling back to legacy path", { providerId: provider.id });
339116
339185
  return null;
339117
339186
  }
339118
339187
  const schemaConfig = provider.schemaConfig ?? {};
@@ -339134,12 +339203,13 @@ function createGenieProviderInstance(provider, instance4) {
339134
339203
  const agentName = typeof schemaConfig.agentName === "string" ? schemaConfig.agentName : "";
339135
339204
  const targetAgent = typeof schemaConfig.targetAgent === "string" ? schemaConfig.targetAgent : "";
339136
339205
  if (!agentName || !targetAgent) {
339137
- log83.error("Genie provider missing agentName or targetAgent in schemaConfig", { providerId: provider.id });
339206
+ log84.error("Genie provider missing agentName or targetAgent in schemaConfig", { providerId: provider.id });
339138
339207
  return null;
339139
339208
  }
339140
339209
  const teamName = typeof schemaConfig.teamName === "string" ? schemaConfig.teamName : "genie";
339141
339210
  const agentRole = typeof schemaConfig.agentRole === "string" ? schemaConfig.agentRole : "team-lead";
339142
- const client = createGenieClient({ teamName, agentName, targetAgent, agentRole });
339211
+ const autoSpawnDir = typeof schemaConfig.autoSpawnDir === "string" ? schemaConfig.autoSpawnDir : undefined;
339212
+ const client = createGenieClient({ teamName, agentName, targetAgent, agentRole, autoSpawnDir });
339143
339213
  return new GenieAgentProvider(provider.id, provider.name, client, {
339144
339214
  prefixSenderName: instance4.agentPrefixSenderName ?? true
339145
339215
  });
@@ -339173,7 +339243,7 @@ function resolveProvider(provider, instance4, db2) {
339173
339243
  agentProvider = createGenieProviderInstance(provider, instance4);
339174
339244
  break;
339175
339245
  default:
339176
- log83.debug("Provider schema not supported for IAgentProvider dispatch", {
339246
+ log84.debug("Provider schema not supported for IAgentProvider dispatch", {
339177
339247
  schema: provider.schema,
339178
339248
  providerId: provider.id
339179
339249
  });
@@ -339193,7 +339263,7 @@ async function getAgentProvider(services, instance4, db2) {
339193
339263
  return null;
339194
339264
  return resolveProvider(provider, instance4, db2);
339195
339265
  } catch (error2) {
339196
- log83.warn("Failed to resolve agent provider, falling back to legacy", {
339266
+ log84.warn("Failed to resolve agent provider, falling back to legacy", {
339197
339267
  instanceId: instance4.id,
339198
339268
  providerId: instance4.agentProviderId,
339199
339269
  error: String(error2)
@@ -339227,7 +339297,7 @@ async function applyInstanceFkAndReturn(db2, instance4) {
339227
339297
  }
339228
339298
  async function resolveEffectiveInstance(services, db2, instance4, chatId, personId) {
339229
339299
  if (!chatId) {
339230
- log83.debug("No internal chatId \u2014 using instance default agent", { instanceId: instance4.id, personId });
339300
+ log84.debug("No internal chatId \u2014 using instance default agent", { instanceId: instance4.id, personId });
339231
339301
  return applyInstanceFkAndReturn(db2, instance4);
339232
339302
  }
339233
339303
  const route = await services.routeResolver.resolve(instance4.id, chatId, personId);
@@ -339251,7 +339321,7 @@ async function resolveEffectiveInstance(services, db2, instance4, chatId, person
339251
339321
  if (effectiveAgentFkId) {
339252
339322
  await applyAgentFkOverrides(db2, effectiveAgentFkId, effectiveInstance);
339253
339323
  }
339254
- log83.debug("Route resolved and merged", {
339324
+ log84.debug("Route resolved and merged", {
339255
339325
  instanceId: instance4.id,
339256
339326
  chatId,
339257
339327
  personId,
@@ -339271,7 +339341,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339271
339341
  const chat2 = await services.chats.findByExternalIdSmart(baseInstance.id, externalChatId);
339272
339342
  const internalChatId = chat2?.id;
339273
339343
  const { instance: instance4, routeId: _routeId } = await resolveEffectiveInstance(services, db2, baseInstance, internalChatId, metadata.personId);
339274
- log83.info("Dispatching reaction trigger", {
339344
+ log84.info("Dispatching reaction trigger", {
339275
339345
  instanceId: instance4.id,
339276
339346
  chatId: externalChatId,
339277
339347
  routeChatId: internalChatId ?? "none",
@@ -339311,7 +339381,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339311
339381
  const _fmtMode = instance4.messageFormatMode ?? "convert";
339312
339382
  await sendResponseParts(channel4, instance4.id, externalChatId, result2.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
339313
339383
  }
339314
- log83.info("Reaction trigger response via provider", {
339384
+ log84.info("Reaction trigger response via provider", {
339315
339385
  instanceId: instance4.id,
339316
339386
  chatId: externalChatId,
339317
339387
  routeChatId: internalChatId,
@@ -339323,7 +339393,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339323
339393
  });
339324
339394
  return;
339325
339395
  }
339326
- log83.debug("No IAgentProvider resolved, using legacy agentRunner path", {
339396
+ log84.debug("No IAgentProvider resolved, using legacy agentRunner path", {
339327
339397
  instanceId: instance4.id
339328
339398
  });
339329
339399
  const personId = await resolvePersonId(services, channel4, instance4.id, payload.from, metadata.personId);
@@ -339349,7 +339419,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339349
339419
  const _fmtMode = instance4.messageFormatMode ?? "convert";
339350
339420
  await sendResponseParts(channel4, instance4.id, externalChatId, result.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
339351
339421
  }
339352
- log83.info("Reaction trigger response via legacy runner", {
339422
+ log84.info("Reaction trigger response via legacy runner", {
339353
339423
  instanceId: instance4.id,
339354
339424
  chatId: externalChatId,
339355
339425
  routeChatId: internalChatId,
@@ -339358,7 +339428,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339358
339428
  traceId: metadata.traceId
339359
339429
  });
339360
339430
  } catch (error2) {
339361
- log83.error("Failed to process reaction trigger", {
339431
+ log84.error("Failed to process reaction trigger", {
339362
339432
  instanceId: instance4.id,
339363
339433
  chatId: externalChatId,
339364
339434
  routeChatId: internalChatId,
@@ -339400,7 +339470,7 @@ async function resolveLidMentionBot(chatsService, instanceId, ownerIdentifier, m
339400
339470
  for (const lidJid of lidMentions) {
339401
339471
  if (ownerIsLid && extractPhoneFromJid(lidJid) === ownerPhone) {
339402
339472
  messageContext.mentionsBot = true;
339403
- log83.debug("LID mention matches owner LID directly", { lidJid, ownerIdentifier });
339473
+ log84.debug("LID mention matches owner LID directly", { lidJid, ownerIdentifier });
339404
339474
  break;
339405
339475
  }
339406
339476
  try {
@@ -339409,14 +339479,14 @@ async function resolveLidMentionBot(chatsService, instanceId, ownerIdentifier, m
339409
339479
  const resolvedPhone = extractPhoneFromJid(mapping);
339410
339480
  if (resolvedPhone === ownerPhone) {
339411
339481
  messageContext.mentionsBot = true;
339412
- log83.debug("LID resolved to instance owner via DB", { lidJid, resolvedPhone, ownerPhone });
339482
+ log84.debug("LID resolved to instance owner via DB", { lidJid, resolvedPhone, ownerPhone });
339413
339483
  break;
339414
339484
  }
339415
339485
  if (ownerIsLid) {
339416
339486
  const ownerMapping = await chatsService.findLidMapping(instanceId, ownerIdentifier);
339417
339487
  if (ownerMapping && extractPhoneFromJid(ownerMapping) === resolvedPhone) {
339418
339488
  messageContext.mentionsBot = true;
339419
- log83.debug("LID resolved to owner via reverse mapping", { lidJid, resolvedPhone, ownerIdentifier });
339489
+ log84.debug("LID resolved to owner via reverse mapping", { lidJid, resolvedPhone, ownerIdentifier });
339420
339490
  break;
339421
339491
  }
339422
339492
  }
@@ -339450,15 +339520,15 @@ function needsLidMentionCheck(messageContext, instance4) {
339450
339520
  }
339451
339521
  async function shouldProcessMessage3(agentRunner, accessService, chatsService, messagesService, routeResolver, rateLimiter, payload, metadata) {
339452
339522
  if (!metadata.instanceId) {
339453
- log83.debug("No instanceId in metadata", { from: payload.from, chatId: payload.chatId });
339523
+ log84.debug("No instanceId in metadata", { from: payload.from, chatId: payload.chatId });
339454
339524
  return null;
339455
339525
  }
339456
339526
  if (payload.from === metadata.platformIdentityId) {
339457
- log83.debug("Message from self, skipping", { instanceId: metadata.instanceId, from: payload.from });
339527
+ log84.debug("Message from self, skipping", { instanceId: metadata.instanceId, from: payload.from });
339458
339528
  return null;
339459
339529
  }
339460
339530
  if (isTrashEmojiOnly(payload.content?.text)) {
339461
- log83.debug("Skipping trash emoji message (session-cleaner handles this)", {
339531
+ log84.debug("Skipping trash emoji message (session-cleaner handles this)", {
339462
339532
  instanceId: metadata.instanceId,
339463
339533
  chatId: payload.chatId
339464
339534
  });
@@ -339466,16 +339536,16 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
339466
339536
  }
339467
339537
  const chatId = payload.chatId ?? "";
339468
339538
  if (isBroadcastOrNewsletter(chatId)) {
339469
- log83.debug("Skipping newsletter/broadcast message", { instanceId: metadata.instanceId, chatId });
339539
+ log84.debug("Skipping newsletter/broadcast message", { instanceId: metadata.instanceId, chatId });
339470
339540
  return null;
339471
339541
  }
339472
339542
  const instance4 = await agentRunner.getInstanceWithProvider(metadata.instanceId);
339473
339543
  if (!instance4?.agentId) {
339474
- log83.debug("Instance has no agentId", { instanceId: metadata.instanceId });
339544
+ log84.debug("Instance has no agentId", { instanceId: metadata.instanceId });
339475
339545
  return null;
339476
339546
  }
339477
339547
  if (!instanceTriggersOnEvent(instance4, "message.received")) {
339478
- log83.debug("Instance does not trigger on message.received", { instanceId: instance4.id });
339548
+ log84.debug("Instance does not trigger on message.received", { instanceId: instance4.id });
339479
339549
  return null;
339480
339550
  }
339481
339551
  const messageContext = buildMessageContext(payload, instance4);
@@ -339485,7 +339555,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
339485
339555
  await resolveLidMentionBot(chatsService, metadata.instanceId, instance4.ownerIdentifier, mentionedJids, messageContext);
339486
339556
  }
339487
339557
  await resolveSlackThreadReply(chatsService, messagesService, instance4, payload, messageContext);
339488
- log83.debug("Message context built", {
339558
+ log84.debug("Message context built", {
339489
339559
  instanceId: instance4.id,
339490
339560
  chatId: payload.chatId,
339491
339561
  isDirectMessage: messageContext.isDirectMessage,
@@ -339495,7 +339565,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
339495
339565
  });
339496
339566
  const effectiveReplyFilter = await resolveEffectiveReplyFilter(chatsService, routeResolver, instance4.id, payload.chatId, instance4.agentReplyFilter);
339497
339567
  if (!shouldAgentReply(effectiveReplyFilter, messageContext)) {
339498
- log83.debug("Message did not pass reply filter", {
339568
+ log84.debug("Message did not pass reply filter", {
339499
339569
  instanceId: instance4.id,
339500
339570
  chatId: payload.chatId,
339501
339571
  messageContext,
@@ -339506,7 +339576,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
339506
339576
  const channel4 = metadata.channelType ?? "whatsapp";
339507
339577
  const rateLimit = instance4.triggerRateLimit;
339508
339578
  if (!rateLimiter.isAllowed(payload.from, channel4, instance4.id, rateLimit ?? DEFAULT_RATE_LIMIT)) {
339509
- log83.info("Rate limited", { instanceId: instance4.id, from: payload.from, channel: channel4 });
339579
+ log84.info("Rate limited", { instanceId: instance4.id, from: payload.from, channel: channel4 });
339510
339580
  return null;
339511
339581
  }
339512
339582
  const accessDenied = await checkAccessWithFallback(accessService, instance4, payload, channel4);
@@ -339524,7 +339594,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
339524
339594
  const primaryId = payload.from ?? "";
339525
339595
  let accessResult = await accessService.checkAccess(instance4, primaryId, channel4);
339526
339596
  if (!accessResult.allowed && participantAlt && participantAlt !== primaryId) {
339527
- log83.warn("Access fallback to participantAlt", {
339597
+ log84.warn("Access fallback to participantAlt", {
339528
339598
  instanceId: instance4.id,
339529
339599
  primaryId,
339530
339600
  participantAlt,
@@ -339533,7 +339603,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
339533
339603
  accessResult = await accessService.checkAccess(instance4, participantAlt, channel4);
339534
339604
  }
339535
339605
  if (!accessResult.allowed && resolvedSenderPhone && resolvedSenderPhone !== primaryId && resolvedSenderPhone !== participantAlt) {
339536
- log83.debug("Access fallback to resolvedSenderPhone (LID\u2192phone)", {
339606
+ log84.debug("Access fallback to resolvedSenderPhone (LID\u2192phone)", {
339537
339607
  instanceId: instance4.id,
339538
339608
  primaryId,
339539
339609
  resolvedSenderPhone,
@@ -339543,7 +339613,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
339543
339613
  }
339544
339614
  if (accessResult.allowed)
339545
339615
  return false;
339546
- log83.info("Access denied", {
339616
+ log84.info("Access denied", {
339547
339617
  instanceId: instance4.id,
339548
339618
  chatId: payload.chatId,
339549
339619
  from: payload.from,
@@ -339552,7 +339622,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
339552
339622
  });
339553
339623
  if (accessResult.mode === "allowlist" && !accessResult.rule && primaryId) {
339554
339624
  accessService.requestPairing(instance4.id, primaryId).catch((err) => {
339555
- log83.warn("Failed to create pairing request", { instanceId: instance4.id, from: primaryId, error: String(err) });
339625
+ log84.warn("Failed to create pairing request", { instanceId: instance4.id, from: primaryId, error: String(err) });
339556
339626
  });
339557
339627
  }
339558
339628
  if (accessResult.rule?.action !== "silent_block" && accessResult.rule?.blockMessage) {
@@ -339569,20 +339639,20 @@ async function shouldProcessReaction(agentRunner, accessService, rateLimiter, re
339569
339639
  if (!instanceTriggersOnEvent(instance4, eventType))
339570
339640
  return null;
339571
339641
  if (!isReactionTrigger(instance4, payload.emoji)) {
339572
- log83.debug("Reaction emoji not in trigger list", { instanceId: instance4.id, emoji: payload.emoji });
339642
+ log84.debug("Reaction emoji not in trigger list", { instanceId: instance4.id, emoji: payload.emoji });
339573
339643
  return null;
339574
339644
  }
339575
339645
  const channel4 = metadata.channelType ?? "whatsapp";
339576
339646
  const rateLimit = instance4.triggerRateLimit;
339577
339647
  if (!rateLimiter.isAllowed(payload.from, channel4, instance4.id, rateLimit ?? DEFAULT_RATE_LIMIT)) {
339578
- log83.info("Rate limited reaction trigger", { instanceId: instance4.id, from: payload.from });
339648
+ log84.info("Rate limited reaction trigger", { instanceId: instance4.id, from: payload.from });
339579
339649
  return null;
339580
339650
  }
339581
339651
  const accessDenied = await checkAccessWithFallback(accessService, instance4, payload, channel4);
339582
339652
  if (accessDenied)
339583
339653
  return null;
339584
339654
  if (reactionDedup.isDuplicate(payload.messageId, payload.emoji, payload.from)) {
339585
- log83.debug("Duplicate reaction, skipping", {
339655
+ log84.debug("Duplicate reaction, skipping", {
339586
339656
  instanceId: instance4.id,
339587
339657
  messageId: payload.messageId,
339588
339658
  emoji: payload.emoji
@@ -339615,7 +339685,7 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
339615
339685
  try {
339616
339686
  const apiKey = await settings.getSecret("gemini.api_key", "GEMINI_API_KEY");
339617
339687
  if (!apiKey) {
339618
- log83.warn("Gate: no Gemini API key, fail-open", { traceId });
339688
+ log84.warn("Gate: no Gemini API key, fail-open", { traceId });
339619
339689
  return true;
339620
339690
  }
339621
339691
  const controller = new AbortController;
@@ -339633,13 +339703,13 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
339633
339703
  });
339634
339704
  clearTimeout(timeout);
339635
339705
  if (!res.ok) {
339636
- log83.warn("Gate: API error, fail-open", { traceId, status: res.status, durationMs: Date.now() - startMs });
339706
+ log84.warn("Gate: API error, fail-open", { traceId, status: res.status, durationMs: Date.now() - startMs });
339637
339707
  return true;
339638
339708
  }
339639
339709
  const data = await res.json();
339640
339710
  const answer = data.candidates?.[0]?.content?.parts?.[0]?.text?.trim().toLowerCase() ?? "";
339641
339711
  const shouldRespond = !answer.startsWith("skip");
339642
- log83.info("Gate decision", {
339712
+ log84.info("Gate decision", {
339643
339713
  traceId,
339644
339714
  decision: shouldRespond ? "respond" : "skip",
339645
339715
  rawAnswer: answer,
@@ -339653,14 +339723,14 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
339653
339723
  clearTimeout(timeout);
339654
339724
  const errName = fetchError.name;
339655
339725
  if (errName === "AbortError") {
339656
- log83.warn("Gate: timeout, fail-open", { traceId, durationMs: Date.now() - startMs });
339726
+ log84.warn("Gate: timeout, fail-open", { traceId, durationMs: Date.now() - startMs });
339657
339727
  } else {
339658
- log83.warn("Gate: fetch error, fail-open", { traceId, error: String(fetchError) });
339728
+ log84.warn("Gate: fetch error, fail-open", { traceId, error: String(fetchError) });
339659
339729
  }
339660
339730
  return true;
339661
339731
  }
339662
339732
  } catch (error2) {
339663
- log83.warn("Gate: unexpected error, fail-open", { traceId, error: String(error2) });
339733
+ log84.warn("Gate: unexpected error, fail-open", { traceId, error: String(error2) });
339664
339734
  return true;
339665
339735
  }
339666
339736
  }
@@ -339670,7 +339740,7 @@ async function shouldSkipViaGate(triggerType, firstMsg, instance4, messages4, se
339670
339740
  const chatType = determineChatType(firstMsg.payload.chatId, firstMsg.metadata.channelType ?? "whatsapp", firstMsg.payload.rawPayload ?? {});
339671
339741
  const shouldRespond = await shouldRespondViaGate(instance4, messages4, chatType, services.settings);
339672
339742
  if (!shouldRespond) {
339673
- log83.info("Gate skipped response", {
339743
+ log84.info("Gate skipped response", {
339674
339744
  instanceId: instance4.id,
339675
339745
  chatId: firstMsg.payload.chatId,
339676
339746
  triggerType,
@@ -339693,7 +339763,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339693
339763
  const instanceId = firstMsg.metadata.instanceId;
339694
339764
  const baseInstance = await agentRunner.getInstanceWithProvider(instanceId);
339695
339765
  if (!baseInstance) {
339696
- log83.warn("Instance not found for debounced messages", { instanceId });
339766
+ log84.warn("Instance not found for debounced messages", { instanceId });
339697
339767
  return;
339698
339768
  }
339699
339769
  const externalChatId = firstMsg.payload.chatId;
@@ -339741,7 +339811,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339741
339811
  timestamp: event.timestamp
339742
339812
  }, effectiveDebounceConfig);
339743
339813
  } catch (error2) {
339744
- log83.error("Error processing message for dispatch", {
339814
+ log84.error("Error processing message for dispatch", {
339745
339815
  instanceId: metadata.instanceId,
339746
339816
  error: String(error2)
339747
339817
  });
@@ -339770,7 +339840,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339770
339840
  traceId
339771
339841
  }, event, db2);
339772
339842
  } catch (error2) {
339773
- log83.error("Error processing reaction for dispatch", {
339843
+ log84.error("Error processing reaction for dispatch", {
339774
339844
  instanceId: metadata.instanceId,
339775
339845
  error: String(error2)
339776
339846
  });
@@ -339799,7 +339869,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339799
339869
  traceId
339800
339870
  }, event, db2);
339801
339871
  } catch (error2) {
339802
- log83.error("Error processing reaction removal for dispatch", {
339872
+ log84.error("Error processing reaction removal for dispatch", {
339803
339873
  instanceId: metadata.instanceId,
339804
339874
  error: String(error2)
339805
339875
  });
@@ -339826,7 +339896,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339826
339896
  debouncer.onUserTyping(metadata.instanceId, payload.chatId, debounceConfig);
339827
339897
  }
339828
339898
  } catch (error2) {
339829
- log83.debug("Error handling typing event", { error: String(error2) });
339899
+ log84.debug("Error handling typing event", { error: String(error2) });
339830
339900
  }
339831
339901
  }, {
339832
339902
  durable: "agent-dispatcher-typing",
@@ -339835,22 +339905,22 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339835
339905
  startFrom: "last",
339836
339906
  concurrency: 10
339837
339907
  });
339838
- log83.info("Agent dispatcher initialized (message + reaction + reaction-removed triggers)");
339908
+ log84.info("Agent dispatcher initialized (message + reaction + reaction-removed triggers)");
339839
339909
  } catch (error2) {
339840
- log83.error("Failed to set up agent dispatcher", { error: String(error2) });
339910
+ log84.error("Failed to set up agent dispatcher", { error: String(error2) });
339841
339911
  clearInterval(cleanupInterval2);
339842
339912
  debouncer.clear();
339843
339913
  throw error2;
339844
339914
  }
339845
339915
  return async () => {
339846
- log83.info("Shutting down agent dispatcher");
339916
+ log84.info("Shutting down agent dispatcher");
339847
339917
  clearInterval(cleanupInterval2);
339848
339918
  debouncer.clear();
339849
339919
  const disposePromises = [];
339850
339920
  for (const [key, provider] of providerCache.entries()) {
339851
339921
  if (provider.dispose) {
339852
339922
  disposePromises.push(provider.dispose().catch((err) => {
339853
- log83.warn("Error disposing provider", { key, error: String(err) });
339923
+ log84.warn("Error disposing provider", { key, error: String(err) });
339854
339924
  }));
339855
339925
  }
339856
339926
  }
@@ -339860,7 +339930,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339860
339930
  try {
339861
339931
  client.stop();
339862
339932
  } catch (err) {
339863
- log83.warn("Error stopping OpenClaw client", { providerId: id, error: String(err) });
339933
+ log84.warn("Error stopping OpenClaw client", { providerId: id, error: String(err) });
339864
339934
  }
339865
339935
  }));
339866
339936
  }
@@ -339868,7 +339938,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339868
339938
  let timeoutId;
339869
339939
  const timeoutGuard = new Promise((resolve3) => {
339870
339940
  timeoutId = setTimeout(() => {
339871
- log83.warn("Dispatcher shutdown timed out after 5s, proceeding");
339941
+ log84.warn("Dispatcher shutdown timed out after 5s, proceeding");
339872
339942
  resolve3([]);
339873
339943
  }, 5000);
339874
339944
  });
@@ -339881,10 +339951,10 @@ async function setupAgentDispatcher(eventBus, services, db2) {
339881
339951
  }
339882
339952
  providerCache.clear();
339883
339953
  openclawClientPool.clear();
339884
- log83.info("Agent dispatcher shutdown complete");
339954
+ log84.info("Agent dispatcher shutdown complete");
339885
339955
  };
339886
339956
  }
339887
- var log83, DEFAULT_RATE_LIMIT = 5, DEFAULT_RATE_WINDOW_MS = 60000, CHANNEL_MESSAGE_LIMITS, DEFAULT_MESSAGE_LIMIT = 4000, MEDIA_BASE_PATH3, MEDIA_ICONS, MEDIA_WAIT_NULL, DEFAULT_SEND_MEDIA_PATH_TYPES, BOT_PREFIX = "\uD83E\uDD16 ", activeStreams, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", providerCache, openclawClientPool, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
339957
+ var log84, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, DEFAULT_RATE_LIMIT = 5, DEFAULT_RATE_WINDOW_MS = 60000, CHANNEL_MESSAGE_LIMITS, DEFAULT_MESSAGE_LIMIT = 4000, MEDIA_BASE_PATH3, MEDIA_ICONS, MEDIA_WAIT_NULL, DEFAULT_SEND_MEDIA_PATH_TYPES, BOT_PREFIX = "\uD83E\uDD16 ", activeStreams, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", providerCache, openclawClientPool, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
339888
339958
  var init_agent_dispatcher = __esm(() => {
339889
339959
  init_src2();
339890
339960
  init_src();
@@ -339895,9 +339965,10 @@ var init_agent_dispatcher = __esm(() => {
339895
339965
  init_sentry_scrub();
339896
339966
  init_agent_runner();
339897
339967
  init_loader2();
339968
+ init_message_debouncer();
339898
339969
  init_session_storage();
339899
339970
  init_src6();
339900
- log83 = createLogger("agent-dispatcher");
339971
+ log84 = createLogger("agent-dispatcher");
339901
339972
  CHANNEL_MESSAGE_LIMITS = {
339902
339973
  discord: 2000,
339903
339974
  "whatsapp-baileys": 65536,
@@ -339967,7 +340038,7 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
339967
340038
  await eventBus.subscribe("sync.started", async (event) => {
339968
340039
  const payload = event.payload;
339969
340040
  const { jobId, instanceId, type, config: config4 } = payload;
339970
- log84.info("Processing sync job", { jobId, instanceId, type });
340041
+ log85.info("Processing sync job", { jobId, instanceId, type });
339971
340042
  try {
339972
340043
  await services.syncJobs.start(jobId);
339973
340044
  const instance4 = await services.instances.getById(instanceId);
@@ -339994,12 +340065,12 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
339994
340065
  case "history-push":
339995
340066
  break;
339996
340067
  default:
339997
- log84.warn("Unknown sync type", { jobId, type });
340068
+ log85.warn("Unknown sync type", { jobId, type });
339998
340069
  await services.syncJobs.fail(jobId, `Unknown sync type: ${type}`);
339999
340070
  }
340000
340071
  } catch (error2) {
340001
340072
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
340002
- log84.error("Sync job failed", { jobId, error: errorMessage });
340073
+ log85.error("Sync job failed", { jobId, error: errorMessage });
340003
340074
  await services.syncJobs.fail(jobId, errorMessage);
340004
340075
  }
340005
340076
  }, {
@@ -340007,15 +340078,15 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
340007
340078
  queue: "sync-workers",
340008
340079
  startFrom: "new"
340009
340080
  });
340010
- log84.info("Sync worker initialized - listening for sync.started events");
340081
+ log85.info("Sync worker initialized - listening for sync.started events");
340011
340082
  } catch (error2) {
340012
- log84.error("Failed to set up sync worker", { error: String(error2) });
340083
+ log85.error("Failed to set up sync worker", { error: String(error2) });
340013
340084
  throw error2;
340014
340085
  }
340015
340086
  }
340016
340087
  async function buildWhatsAppAnchors(instanceId, _services) {
340017
340088
  if (!db2) {
340018
- log84.warn("Database not available for building anchors");
340089
+ log85.warn("Database not available for building anchors");
340019
340090
  return [];
340020
340091
  }
340021
340092
  const result = await db2.execute(sql`
@@ -340051,20 +340122,20 @@ async function buildWhatsAppAnchors(instanceId, _services) {
340051
340122
  });
340052
340123
  }
340053
340124
  }
340054
- log84.info("Built WhatsApp anchors", { instanceId, anchorCount: anchors.length });
340125
+ log85.info("Built WhatsApp anchors", { instanceId, anchorCount: anchors.length });
340055
340126
  return anchors;
340056
340127
  }
340057
340128
  function buildAnchorsForExplicitChatJids(jobId, chatJids, dbAnchors) {
340058
- log84.info("Using explicit chatJids for sync", { jobId, chatJids });
340129
+ log85.info("Using explicit chatJids for sync", { jobId, chatJids });
340059
340130
  const anchors = [];
340060
340131
  for (const jid of chatJids) {
340061
340132
  const dbAnchor = dbAnchors.find((a3) => a3.chatJid === jid);
340062
340133
  if (dbAnchor) {
340063
- log84.debug("Found DB anchor for chatJid", { jobId, chatJid: jid, anchorId: dbAnchor.messageKey.id });
340134
+ log85.debug("Found DB anchor for chatJid", { jobId, chatJid: jid, anchorId: dbAnchor.messageKey.id });
340064
340135
  anchors.push(dbAnchor);
340065
340136
  continue;
340066
340137
  }
340067
- log84.debug("No DB anchor for chatJid, will fetch recent", { jobId, chatJid: jid });
340138
+ log85.debug("No DB anchor for chatJid, will fetch recent", { jobId, chatJid: jid });
340068
340139
  anchors.push({
340069
340140
  chatJid: jid,
340070
340141
  messageKey: { remoteJid: jid, id: "", fromMe: false },
@@ -340090,7 +340161,7 @@ async function discoverAnchorsFromPlugin(jobId, instanceId, plugin6, dbAnchors,
340090
340161
  discovered.push({ chatJid: jid, messageKey: { remoteJid: jid, id: "", fromMe: false }, timestamp: Date.now() });
340091
340162
  }
340092
340163
  if (discovered.length > 0) {
340093
- log84.info("Discovered chats from DB + Baileys not in anchors", {
340164
+ log85.info("Discovered chats from DB + Baileys not in anchors", {
340094
340165
  jobId,
340095
340166
  discoveredCount: discovered.length,
340096
340167
  fromDb: dbExternalIds.length,
@@ -340111,7 +340182,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340111
340182
  throw new Error(`No plugin found for channel type: ${channelType}`);
340112
340183
  }
340113
340184
  if (!("fetchHistory" in plugin6) || typeof plugin6.fetchHistory !== "function") {
340114
- log84.warn("Plugin does not support fetchHistory", { channelType });
340185
+ log85.warn("Plugin does not support fetchHistory", { channelType });
340115
340186
  await services.syncJobs.complete(jobId);
340116
340187
  return;
340117
340188
  }
@@ -340120,7 +340191,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340120
340191
  let fetched = 0;
340121
340192
  let stored = 0;
340122
340193
  let duplicates = 0;
340123
- log84.info("Starting message sync", {
340194
+ log85.info("Starting message sync", {
340124
340195
  jobId,
340125
340196
  instanceId,
340126
340197
  channelType,
@@ -340130,13 +340201,13 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340130
340201
  if (channelType === "whatsapp-baileys" && config4.chatJids?.length) {
340131
340202
  const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
340132
340203
  anchors = await resolveWhatsAppAnchors(jobId, instanceId, config4, plugin6, dbAnchors, services);
340133
- log84.info("WhatsApp per-chat active sync", { jobId, anchorCount: anchors.length, chatJids: config4.chatJids });
340204
+ log85.info("WhatsApp per-chat active sync", { jobId, anchorCount: anchors.length, chatJids: config4.chatJids });
340134
340205
  } else if (channelType === "whatsapp-baileys") {
340135
340206
  const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
340136
340207
  const discoveredAnchors = await discoverAnchorsFromPlugin(jobId, instanceId, plugin6, dbAnchors, services);
340137
340208
  anchors = [...dbAnchors, ...discoveredAnchors];
340138
340209
  if (anchors.length > 0) {
340139
- log84.info("WhatsApp default sync with DB+cache discovery", {
340210
+ log85.info("WhatsApp default sync with DB+cache discovery", {
340140
340211
  jobId,
340141
340212
  instanceId,
340142
340213
  dbAnchorCount: dbAnchors.length,
@@ -340144,7 +340215,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340144
340215
  totalAnchors: anchors.length
340145
340216
  });
340146
340217
  } else {
340147
- log84.info("WhatsApp passive sync (no prior data)", { jobId, instanceId });
340218
+ log85.info("WhatsApp passive sync (no prior data)", { jobId, instanceId });
340148
340219
  }
340149
340220
  }
340150
340221
  const fetchOptions = {
@@ -340186,7 +340257,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340186
340257
  });
340187
340258
  stored++;
340188
340259
  } catch (error2) {
340189
- log84.warn("Failed to store synced message", {
340260
+ log85.warn("Failed to store synced message", {
340190
340261
  externalId: msg.externalId,
340191
340262
  error: String(error2)
340192
340263
  });
@@ -340203,7 +340274,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
340203
340274
  duplicates
340204
340275
  });
340205
340276
  await services.syncJobs.complete(jobId);
340206
- log84.info("Message sync completed", {
340277
+ log85.info("Message sync completed", {
340207
340278
  jobId,
340208
340279
  fetched,
340209
340280
  stored,
@@ -340250,14 +340321,14 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
340250
340321
  throw new Error(`No plugin found for channel type: ${channelType}`);
340251
340322
  }
340252
340323
  if (!("fetchContacts" in plugin6) || typeof plugin6.fetchContacts !== "function") {
340253
- log84.warn("Plugin does not support fetchContacts", { channelType });
340324
+ log85.warn("Plugin does not support fetchContacts", { channelType });
340254
340325
  await services.syncJobs.complete(jobId);
340255
340326
  return;
340256
340327
  }
340257
340328
  let fetched = 0;
340258
340329
  let stored = 0;
340259
340330
  let linked = 0;
340260
- log84.info("Starting contacts sync", {
340331
+ log85.info("Starting contacts sync", {
340261
340332
  jobId,
340262
340333
  instanceId,
340263
340334
  channelType
@@ -340296,7 +340367,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
340296
340367
  await updateDmChatName(services, instanceId, c.platformUserId, c.name);
340297
340368
  }
340298
340369
  } catch (error2) {
340299
- log84.warn("Failed to store synced contact", {
340370
+ log85.warn("Failed to store synced contact", {
340300
340371
  platformUserId: c.platformUserId,
340301
340372
  error: String(error2)
340302
340373
  });
@@ -340313,7 +340384,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
340313
340384
  duplicates: 0
340314
340385
  });
340315
340386
  await services.syncJobs.complete(jobId);
340316
- log84.info("Contacts sync completed", {
340387
+ log85.info("Contacts sync completed", {
340317
340388
  jobId,
340318
340389
  fetched,
340319
340390
  stored,
@@ -340327,7 +340398,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
340327
340398
  }
340328
340399
  const fetchMethod = channelType === "discord" ? "fetchGuilds" : "fetchGroups";
340329
340400
  if (!(fetchMethod in plugin6) || typeof plugin6[fetchMethod] !== "function") {
340330
- log84.warn(`Plugin does not support ${fetchMethod}`, { channelType });
340401
+ log85.warn(`Plugin does not support ${fetchMethod}`, { channelType });
340331
340402
  await services.syncJobs.complete(jobId);
340332
340403
  return;
340333
340404
  }
@@ -340338,7 +340409,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
340338
340409
  let fetched = 0;
340339
340410
  let stored = 0;
340340
340411
  let updated = 0;
340341
- log84.info("Starting groups sync", {
340412
+ log85.info("Starting groups sync", {
340342
340413
  jobId,
340343
340414
  instanceId,
340344
340415
  channelType
@@ -340388,7 +340459,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
340388
340459
  stored++;
340389
340460
  }
340390
340461
  } catch (error2) {
340391
- log84.warn("Failed to store synced group", {
340462
+ log85.warn("Failed to store synced group", {
340392
340463
  externalId: g2.externalId,
340393
340464
  error: String(error2)
340394
340465
  });
@@ -340429,7 +340500,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
340429
340500
  stored++;
340430
340501
  }
340431
340502
  } catch (error2) {
340432
- log84.warn("Failed to store synced guild", {
340503
+ log85.warn("Failed to store synced guild", {
340433
340504
  externalId: g2.externalId,
340434
340505
  error: String(error2)
340435
340506
  });
@@ -340444,7 +340515,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
340444
340515
  duplicates: updated
340445
340516
  });
340446
340517
  await services.syncJobs.complete(jobId);
340447
- log84.info("Groups sync completed", {
340518
+ log85.info("Groups sync completed", {
340448
340519
  jobId,
340449
340520
  fetched,
340450
340521
  stored,
@@ -340554,12 +340625,12 @@ async function setupHistoryPushTracker(eventBus, services) {
340554
340625
  throw error2;
340555
340626
  }
340556
340627
  }
340557
- var log84, RATE_LIMITS2, db2 = null, historyPushLog;
340628
+ var log85, RATE_LIMITS2, db2 = null, historyPushLog;
340558
340629
  var init_sync_worker = __esm(() => {
340559
340630
  init_src();
340560
340631
  init_src4();
340561
340632
  init_drizzle_orm();
340562
- log84 = createLogger("sync-worker");
340633
+ log85 = createLogger("sync-worker");
340563
340634
  RATE_LIMITS2 = {
340564
340635
  "whatsapp-baileys": 30,
340565
340636
  discord: 50,
@@ -340623,15 +340694,15 @@ async function handleTrashEmojiMessage(services, db3, event) {
340623
340694
  return;
340624
340695
  if (!isTrashEmojiOnly2(content.text))
340625
340696
  return;
340626
- log85.info("Trash emoji detected, clearing session", { instanceId, chatId, from });
340697
+ log86.info("Trash emoji detected, clearing session", { instanceId, chatId, from });
340627
340698
  try {
340628
340699
  const { sessionId, sessionStrategy } = await clearAgentSession(services, db3, instanceId, from, chatId);
340629
- log85.info("Session cleared successfully", { instanceId, sessionId, sessionStrategy });
340700
+ log86.info("Session cleared successfully", { instanceId, sessionId, sessionStrategy });
340630
340701
  try {
340631
340702
  await sendMessage(services, instanceId, chatId, "\u2705 Conversa limpa! Sua sess\xE3o com o assistente foi resetada.");
340632
- log85.info("Sent session cleared confirmation", { instanceId, chatId });
340703
+ log86.info("Sent session cleared confirmation", { instanceId, chatId });
340633
340704
  } catch (sendError) {
340634
- log85.error("Failed to send confirmation message", { instanceId, chatId, error: String(sendError) });
340705
+ log86.error("Failed to send confirmation message", { instanceId, chatId, error: String(sendError) });
340635
340706
  }
340636
340707
  } catch (error2) {
340637
340708
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
@@ -340642,14 +340713,14 @@ async function handleTrashEmojiMessage(services, db3, event) {
340642
340713
  "Session clearing not supported for"
340643
340714
  ];
340644
340715
  if (skippableErrors.some((e) => errorMessage.includes(e))) {
340645
- log85.debug("Session clearing skipped", { instanceId, reason: errorMessage });
340716
+ log86.debug("Session clearing skipped", { instanceId, reason: errorMessage });
340646
340717
  return;
340647
340718
  }
340648
- log85.error("Failed to clear session", { instanceId, chatId, error: errorMessage });
340719
+ log86.error("Failed to clear session", { instanceId, chatId, error: errorMessage });
340649
340720
  try {
340650
340721
  await sendMessage(services, instanceId, chatId, "\u274C Erro ao limpar sess\xE3o. Tente novamente.");
340651
340722
  } catch (sendError) {
340652
- log85.error("Failed to send error message", { instanceId, chatId, error: String(sendError) });
340723
+ log86.error("Failed to send error message", { instanceId, chatId, error: String(sendError) });
340653
340724
  }
340654
340725
  }
340655
340726
  }
@@ -340663,13 +340734,13 @@ async function setupSessionCleaner(eventBus, services, db3) {
340663
340734
  startFrom: "last",
340664
340735
  concurrency: 5
340665
340736
  });
340666
- log85.info("Session cleaner initialized");
340737
+ log86.info("Session cleaner initialized");
340667
340738
  } catch (error2) {
340668
- log85.error("Failed to set up session cleaner", { error: String(error2) });
340739
+ log86.error("Failed to set up session cleaner", { error: String(error2) });
340669
340740
  throw error2;
340670
340741
  }
340671
340742
  }
340672
- var log85;
340743
+ var log86;
340673
340744
  var init_session_cleaner = __esm(() => {
340674
340745
  init_src();
340675
340746
  init_src4();
@@ -340677,7 +340748,7 @@ var init_session_cleaner = __esm(() => {
340677
340748
  init_agent_runner();
340678
340749
  init_agent_dispatcher();
340679
340750
  init_loader2();
340680
- log85 = createLogger("session-cleaner");
340751
+ log86 = createLogger("session-cleaner");
340681
340752
  });
340682
340753
 
340683
340754
  // ../api/src/plugins/instance-monitor.ts
@@ -341215,14 +341286,14 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
341215
341286
  return "ok";
341216
341287
  const parsed = parseMetadata(msg.text);
341217
341288
  if (!parsed.instance || !parsed.chat || !parsed.channel) {
341218
- log86.debug("Skipping message \u2014 missing routing metadata", { team, inboxName, from: msg.from });
341289
+ log87.debug("Skipping message \u2014 missing routing metadata", { team, inboxName, from: msg.from });
341219
341290
  return "ok";
341220
341291
  }
341221
341292
  if (!parsed.cleanText)
341222
341293
  return "ok";
341223
341294
  const plugin6 = channelRegistry2.get(parsed.channel);
341224
341295
  if (!plugin6) {
341225
- log86.warn("Channel plugin not found", { channel: parsed.channel, team, inboxName });
341296
+ log87.warn("Channel plugin not found", { channel: parsed.channel, team, inboxName });
341226
341297
  return "ok";
341227
341298
  }
341228
341299
  const outgoing = {
@@ -341234,7 +341305,7 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
341234
341305
  try {
341235
341306
  const result = await plugin6.sendMessage(parsed.instance, outgoing);
341236
341307
  if (result.success) {
341237
- log86.info("Forwarded reply", {
341308
+ log87.info("Forwarded reply", {
341238
341309
  team,
341239
341310
  inboxName,
341240
341311
  channel: parsed.channel,
@@ -341244,11 +341315,11 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
341244
341315
  messageId: result.messageId
341245
341316
  });
341246
341317
  } else {
341247
- log86.error("sendMessage failed", { team, inboxName, channel: parsed.channel, error: result.error });
341318
+ log87.error("sendMessage failed", { team, inboxName, channel: parsed.channel, error: result.error });
341248
341319
  }
341249
341320
  return "ok";
341250
341321
  } catch (err) {
341251
- log86.error("sendMessage threw", { team, inboxName, error: String(err) });
341322
+ log87.error("sendMessage threw", { team, inboxName, error: String(err) });
341252
341323
  return "retry";
341253
341324
  }
341254
341325
  }
@@ -341272,7 +341343,7 @@ async function processInbox(inboxName, team, state, channelRegistry2, patterns)
341272
341343
  const entry = state.cursors[cursorKey] ?? { lastIndex: 0 };
341273
341344
  let { lastIndex } = entry;
341274
341345
  if (lastIndex > inbox.length) {
341275
- log86.warn("Inbox shrank (truncated/rotated), resetting cursor", {
341346
+ log87.warn("Inbox shrank (truncated/rotated), resetting cursor", {
341276
341347
  team,
341277
341348
  inboxName,
341278
341349
  oldCursor: lastIndex,
@@ -341325,20 +341396,20 @@ async function setupInboxBridge(services, channelRegistry2) {
341325
341396
  let patterns = [];
341326
341397
  try {
341327
341398
  patterns = await discoverAgentPatterns(services);
341328
- log86.info("Inbox bridge started", {
341399
+ log87.info("Inbox bridge started", {
341329
341400
  patterns: patterns.map((p2) => ({ raw: p2.raw, isTemplate: p2.isTemplate, prefix: p2.prefix }))
341330
341401
  });
341331
341402
  } catch (err) {
341332
- log86.warn("Initial agent discovery failed", { error: String(err) });
341403
+ log87.warn("Initial agent discovery failed", { error: String(err) });
341333
341404
  }
341334
341405
  const discoveryTimer = setInterval(async () => {
341335
341406
  try {
341336
341407
  patterns = await discoverAgentPatterns(services);
341337
- log86.debug("Agent patterns refreshed", {
341408
+ log87.debug("Agent patterns refreshed", {
341338
341409
  patterns: patterns.map((p2) => ({ raw: p2.raw, isTemplate: p2.isTemplate, prefix: p2.prefix }))
341339
341410
  });
341340
341411
  } catch (err) {
341341
- log86.warn("Agent discovery refresh failed", { error: String(err) });
341412
+ log87.warn("Agent discovery refresh failed", { error: String(err) });
341342
341413
  }
341343
341414
  }, DISCOVERY_INTERVAL_MS);
341344
341415
  discoveryTimer.unref();
@@ -341350,7 +341421,7 @@ async function setupInboxBridge(services, channelRegistry2) {
341350
341421
  try {
341351
341422
  await pollInboxes(patterns, channelRegistry2);
341352
341423
  } catch (err) {
341353
- log86.error("Poll cycle error", { error: String(err) });
341424
+ log87.error("Poll cycle error", { error: String(err) });
341354
341425
  } finally {
341355
341426
  polling = false;
341356
341427
  }
@@ -341359,13 +341430,13 @@ async function setupInboxBridge(services, channelRegistry2) {
341359
341430
  return async () => {
341360
341431
  clearInterval(discoveryTimer);
341361
341432
  clearInterval(pollTimer);
341362
- log86.info("Inbox bridge stopped");
341433
+ log87.info("Inbox bridge stopped");
341363
341434
  };
341364
341435
  }
341365
- var log86, CLAUDE_TEAMS_DIR, BRIDGE_STATE_PATH, POLL_INTERVAL_MS2 = 2000, DISCOVERY_INTERVAL_MS = 60000, CURSOR_TTL_MS;
341436
+ var log87, CLAUDE_TEAMS_DIR, BRIDGE_STATE_PATH, POLL_INTERVAL_MS2 = 2000, DISCOVERY_INTERVAL_MS = 60000, CURSOR_TTL_MS;
341366
341437
  var init_inbox_bridge = __esm(() => {
341367
341438
  init_src();
341368
- log86 = createLogger("inbox-bridge");
341439
+ log87 = createLogger("inbox-bridge");
341369
341440
  CLAUDE_TEAMS_DIR = join25(homedir3(), ".claude", "teams");
341370
341441
  BRIDGE_STATE_PATH = join25(homedir3(), ".claude", "bridge", "state.json");
341371
341442
  CURSOR_TTL_MS = 24 * 60 * 60 * 1000;
@@ -341398,7 +341469,7 @@ function setupScheduler(services, channelRegistry2) {
341398
341469
  recordScheduledJob("dead-letter-auto-retry", "success", durationSec);
341399
341470
  const pendingCount = await services.deadLetters.getPendingCount();
341400
341471
  deadLettersPending.set(pendingCount);
341401
- log87.info("Dead letter auto-retry completed", result);
341472
+ log88.info("Dead letter auto-retry completed", result);
341402
341473
  } catch (err) {
341403
341474
  const durationSec = (Date.now() - startTime3) / 1000;
341404
341475
  recordScheduledJob("dead-letter-auto-retry", "failure", durationSec);
@@ -341420,7 +341491,7 @@ function setupScheduler(services, channelRegistry2) {
341420
341491
  recordScheduledJob("payload-cleanup", "success", durationSec);
341421
341492
  const stats = await services.payloadStore.getStats();
341422
341493
  payloadStorageSize.set(stats.totalSizeCompressed);
341423
- log87.info("Payload cleanup completed", { deleted });
341494
+ log88.info("Payload cleanup completed", { deleted });
341424
341495
  } catch (err) {
341425
341496
  const durationSec = (Date.now() - startTime3) / 1000;
341426
341497
  recordScheduledJob("payload-cleanup", "failure", durationSec);
@@ -341440,7 +341511,7 @@ function setupScheduler(services, channelRegistry2) {
341440
341511
  const deleted = await services.deadLetters.cleanupExpired();
341441
341512
  const durationSec = (Date.now() - startTime3) / 1000;
341442
341513
  recordScheduledJob("dead-letter-cleanup", "success", durationSec);
341443
- log87.info("Dead letter cleanup completed", { deleted });
341514
+ log88.info("Dead letter cleanup completed", { deleted });
341444
341515
  } catch (err) {
341445
341516
  const durationSec = (Date.now() - startTime3) / 1000;
341446
341517
  recordScheduledJob("dead-letter-cleanup", "failure", durationSec);
@@ -341469,7 +341540,7 @@ function setupScheduler(services, channelRegistry2) {
341469
341540
  });
341470
341541
  jobsCreated++;
341471
341542
  } catch (err) {
341472
- log87.warn("Failed to create contacts sync job for instance", {
341543
+ log88.warn("Failed to create contacts sync job for instance", {
341473
341544
  instanceId: instance4.id,
341474
341545
  error: String(err)
341475
341546
  });
@@ -341477,7 +341548,7 @@ function setupScheduler(services, channelRegistry2) {
341477
341548
  }
341478
341549
  const durationSec = (Date.now() - startTime3) / 1000;
341479
341550
  recordScheduledJob("contacts-sync-daily", "success", durationSec);
341480
- log87.info("Daily contacts sync jobs created", { jobsCreated, instanceCount: instances2.length });
341551
+ log88.info("Daily contacts sync jobs created", { jobsCreated, instanceCount: instances2.length });
341481
341552
  } catch (err) {
341482
341553
  const durationSec = (Date.now() - startTime3) / 1000;
341483
341554
  recordScheduledJob("contacts-sync-daily", "failure", durationSec);
@@ -341506,7 +341577,7 @@ function setupScheduler(services, channelRegistry2) {
341506
341577
  });
341507
341578
  jobsCreated++;
341508
341579
  } catch (err) {
341509
- log87.warn("Failed to create groups sync job for instance", {
341580
+ log88.warn("Failed to create groups sync job for instance", {
341510
341581
  instanceId: instance4.id,
341511
341582
  error: String(err)
341512
341583
  });
@@ -341514,7 +341585,7 @@ function setupScheduler(services, channelRegistry2) {
341514
341585
  }
341515
341586
  const durationSec = (Date.now() - startTime3) / 1000;
341516
341587
  recordScheduledJob("groups-sync-daily", "success", durationSec);
341517
- log87.info("Daily groups sync jobs created", { jobsCreated, instanceCount: instances2.length });
341588
+ log88.info("Daily groups sync jobs created", { jobsCreated, instanceCount: instances2.length });
341518
341589
  } catch (err) {
341519
341590
  const durationSec = (Date.now() - startTime3) / 1000;
341520
341591
  recordScheduledJob("groups-sync-daily", "failure", durationSec);
@@ -341543,7 +341614,7 @@ function setupScheduler(services, channelRegistry2) {
341543
341614
  }
341544
341615
  const durationSec = (Date.now() - startTime3) / 1000;
341545
341616
  recordScheduledJob("unread-count-refresh", "success", durationSec);
341546
- log87.debug("Refreshed unread counts", { instanceCount: waInstances.length });
341617
+ log88.debug("Refreshed unread counts", { instanceCount: waInstances.length });
341547
341618
  } catch (err) {
341548
341619
  const durationSec = (Date.now() - startTime3) / 1000;
341549
341620
  recordScheduledJob("unread-count-refresh", "failure", durationSec);
@@ -341554,7 +341625,7 @@ function setupScheduler(services, channelRegistry2) {
341554
341625
  });
341555
341626
  updateSchedulerMetrics();
341556
341627
  scheduler.start();
341557
- log87.info("Scheduler started", {
341628
+ log88.info("Scheduler started", {
341558
341629
  jobs: scheduler.listJobs().map((j) => ({
341559
341630
  name: j.name,
341560
341631
  cron: j.cron,
@@ -341574,14 +341645,14 @@ function updateSchedulerMetrics() {
341574
341645
  function stopScheduler() {
341575
341646
  const scheduler = getScheduler();
341576
341647
  scheduler.stop();
341577
- log87.info("Scheduler stopped");
341648
+ log88.info("Scheduler stopped");
341578
341649
  }
341579
- var log87;
341650
+ var log88;
341580
341651
  var init_scheduler2 = __esm(() => {
341581
341652
  init_src();
341582
341653
  init_esm5();
341583
341654
  init_sentry_scrub();
341584
- log87 = createLogger("scheduler:setup");
341655
+ log88 = createLogger("scheduler:setup");
341585
341656
  });
341586
341657
 
341587
341658
  // ../api/src/utils/startup-banner.ts
@@ -341655,12 +341726,12 @@ function printStartupBanner(options) {
341655
341726
  process.stdout.write(`${line3}
341656
341727
  `);
341657
341728
  }
341658
- log88.info("Server ready", { host, port, version: version4 });
341729
+ log89.info("Server ready", { host, port, version: version4 });
341659
341730
  }
341660
- var log88, COLORS3, BOX, ANSI_ESCAPE_PATTERN;
341731
+ var log89, COLORS3, BOX, ANSI_ESCAPE_PATTERN;
341661
341732
  var init_startup_banner = __esm(() => {
341662
341733
  init_src();
341663
- log88 = createLogger("api:startup");
341734
+ log89 = createLogger("api:startup");
341664
341735
  COLORS3 = {
341665
341736
  reset: "\x1B[0m",
341666
341737
  dim: "\x1B[2m",
@@ -341820,84 +341891,84 @@ function setupShutdownHandlers(server, earlyShutdown) {
341820
341891
  }
341821
341892
  async function setupEventBusServices(eventBus, services, db3) {
341822
341893
  if (!eventBus) {
341823
- log89.warn("Skipping event bus services (no event bus)");
341894
+ log90.warn("Skipping event bus services (no event bus)");
341824
341895
  return;
341825
341896
  }
341826
341897
  try {
341827
341898
  await setupMessagePersistence(eventBus, services);
341828
341899
  } catch (error2) {
341829
- log89.error("Failed to set up message persistence", { error: String(error2) });
341900
+ log90.error("Failed to set up message persistence", { error: String(error2) });
341830
341901
  }
341831
341902
  try {
341832
341903
  await setupMediaProcessor(eventBus, db3, services);
341833
341904
  } catch (error2) {
341834
- log89.error("Failed to set up media processor", { error: String(error2) });
341905
+ log90.error("Failed to set up media processor", { error: String(error2) });
341835
341906
  }
341836
341907
  try {
341837
341908
  globalDispatcherCleanup = await setupAgentResponder(eventBus, services, db3);
341838
341909
  } catch (error2) {
341839
- log89.error("Failed to set up agent dispatcher", { error: String(error2) });
341910
+ log90.error("Failed to set up agent dispatcher", { error: String(error2) });
341840
341911
  }
341841
341912
  if (globalChannelRegistry) {
341842
341913
  try {
341843
341914
  globalInboxBridgeCleanup = await setupInboxBridge(services, globalChannelRegistry);
341844
341915
  } catch (error2) {
341845
- log89.error("Failed to set up inbox bridge", { error: String(error2) });
341916
+ log90.error("Failed to set up inbox bridge", { error: String(error2) });
341846
341917
  }
341847
341918
  }
341848
341919
  try {
341849
341920
  await services.automations.startEngine({});
341850
341921
  } catch (error2) {
341851
- log89.error("Failed to start automation engine", { error: String(error2) });
341922
+ log90.error("Failed to start automation engine", { error: String(error2) });
341852
341923
  }
341853
341924
  try {
341854
341925
  await setupSessionCleaner(eventBus, services, db3);
341855
341926
  } catch (error2) {
341856
- log89.error("Failed to set up session cleaner", { error: String(error2) });
341927
+ log90.error("Failed to set up session cleaner", { error: String(error2) });
341857
341928
  }
341858
341929
  if (globalChannelRegistry) {
341859
341930
  try {
341860
341931
  await setupSyncWorker(eventBus, services, globalChannelRegistry, db3);
341861
341932
  } catch (error2) {
341862
- log89.error("Failed to set up sync worker", { error: String(error2) });
341933
+ log90.error("Failed to set up sync worker", { error: String(error2) });
341863
341934
  }
341864
341935
  }
341865
341936
  try {
341866
341937
  await setupHistoryPushTracker(eventBus, services);
341867
341938
  } catch (error2) {
341868
- log89.error("Failed to set up history-push tracker", { error: String(error2) });
341939
+ log90.error("Failed to set up history-push tracker", { error: String(error2) });
341869
341940
  }
341870
341941
  }
341871
341942
  async function waitForDatabaseReady(db3, maxAttempts = 30) {
341872
- log89.info("Waiting for database readiness");
341943
+ log90.info("Waiting for database readiness");
341873
341944
  for (let attempt = 1;attempt <= maxAttempts; attempt++) {
341874
341945
  try {
341875
341946
  await db3.execute(sql`SELECT 1`);
341876
- log89.info("Database ready", { attempt });
341947
+ log90.info("Database ready", { attempt });
341877
341948
  return;
341878
341949
  } catch {
341879
341950
  if (attempt === maxAttempts) {
341880
341951
  throw new Error(`Database not ready after ${maxAttempts} attempts`);
341881
341952
  }
341882
- log89.warn("Database not ready, retrying...", { attempt });
341953
+ log90.warn("Database not ready, retrying...", { attempt });
341883
341954
  await new Promise((resolve3) => setTimeout(resolve3, 1000));
341884
341955
  }
341885
341956
  }
341886
341957
  }
341887
341958
  async function main() {
341888
- log89.info("Starting Omni API v2");
341959
+ log90.info("Starting Omni API v2");
341889
341960
  enableDefaultMetrics();
341890
341961
  const pgserveConfig = resolvePgserveConfig();
341891
341962
  const databaseUrl = await startEmbeddedPgserve(pgserveConfig);
341892
- log89.info("Connecting to database");
341963
+ log90.info("Connecting to database");
341893
341964
  const db3 = createDb({ url: databaseUrl });
341894
341965
  const earlyShutdown = async () => {
341895
- log89.info("Shutdown during startup \u2014 cleaning up");
341966
+ log90.info("Shutdown during startup \u2014 cleaning up");
341896
341967
  try {
341897
341968
  await closeDb();
341898
341969
  await stopEmbeddedPgserve();
341899
341970
  } catch (err) {
341900
- log89.error("Cleanup failed during early shutdown", { error: String(err) });
341971
+ log90.error("Cleanup failed during early shutdown", { error: String(err) });
341901
341972
  } finally {
341902
341973
  process.exit(1);
341903
341974
  }
@@ -341911,7 +341982,7 @@ async function main() {
341911
341982
  await stopEmbeddedPgserve();
341912
341983
  throw error2;
341913
341984
  }
341914
- log89.info("Running database migrations");
341985
+ log90.info("Running database migrations");
341915
341986
  const migrationStart = Date.now();
341916
341987
  const MIGRATION_TIMEOUT_MS = 60000;
341917
341988
  try {
@@ -341924,7 +341995,7 @@ async function main() {
341924
341995
  await stopEmbeddedPgserve();
341925
341996
  throw error2;
341926
341997
  }
341927
- log89.info("Database migrations complete", { durationMs: Date.now() - migrationStart });
341998
+ log90.info("Database migrations complete", { durationMs: Date.now() - migrationStart });
341928
341999
  const eventBus = await connectToNats(db3);
341929
342000
  if (eventBus) {
341930
342001
  try {
@@ -341939,9 +342010,9 @@ async function main() {
341939
342010
  try {
341940
342011
  await services.settings.seedDefaults();
341941
342012
  } catch (error2) {
341942
- log89.error("Failed to seed default settings", { error: String(error2) });
342013
+ log90.error("Failed to seed default settings", { error: String(error2) });
341943
342014
  }
341944
- log89.info("Initializing API key");
342015
+ log90.info("Initializing API key");
341945
342016
  let apiKeyInfo;
341946
342017
  try {
341947
342018
  const keyResult = await services.apiKeys.initializePrimaryKey();
@@ -341951,17 +342022,17 @@ async function main() {
341951
342022
  isFromEnv: keyResult.isFromEnv
341952
342023
  };
341953
342024
  if (keyResult.isNew) {
341954
- log89.info("Generated new primary API key");
342025
+ log90.info("Generated new primary API key");
341955
342026
  } else if (keyResult.isFromEnv) {
341956
- log89.info("Using primary API key from environment");
342027
+ log90.info("Using primary API key from environment");
341957
342028
  } else {
341958
- log89.info("Using existing primary API key");
342029
+ log90.info("Using existing primary API key");
341959
342030
  }
341960
342031
  } catch (error2) {
341961
- log89.error("Failed to initialize primary API key", { error: String(error2) });
342032
+ log90.error("Failed to initialize primary API key", { error: String(error2) });
341962
342033
  }
341963
342034
  await setupEventBusServices(eventBus, services, db3);
341964
- log89.info("Starting scheduler");
342035
+ log90.info("Starting scheduler");
341965
342036
  setupScheduler(services, globalChannelRegistry);
341966
342037
  const server = startBunServer(app);
341967
342038
  printStartupBanner({
@@ -341975,7 +342046,7 @@ async function main() {
341975
342046
  });
341976
342047
  setupShutdownHandlers(server, earlyShutdown);
341977
342048
  }
341978
- var import__package3, log89, natsLog, pluginLog, shutdownLog, PORT, HOST, NATS_URL, globalEventBus = null, globalChannelRegistry = null, globalInstanceMonitor = null, globalDispatcherCleanup = null, globalInboxBridgeCleanup = null;
342049
+ var import__package3, log90, natsLog, pluginLog, shutdownLog, PORT, HOST, NATS_URL, globalEventBus = null, globalChannelRegistry = null, globalInstanceMonitor = null, globalDispatcherCleanup = null, globalInboxBridgeCleanup = null;
341979
342050
  var init_src7 = __esm(() => {
341980
342051
  init_instrument2();
341981
342052
  init_src();
@@ -341995,7 +342066,7 @@ var init_src7 = __esm(() => {
341995
342066
  level: process.env.LOG_LEVEL ?? "info",
341996
342067
  format: process.env.LOG_FORMAT ?? "auto"
341997
342068
  });
341998
- log89 = createLogger("api:startup");
342069
+ log90 = createLogger("api:startup");
341999
342070
  natsLog = createLogger("api:nats");
342000
342071
  pluginLog = createLogger("api:plugins");
342001
342072
  shutdownLog = createLogger("api:shutdown");
@@ -342003,7 +342074,7 @@ var init_src7 = __esm(() => {
342003
342074
  HOST = process.env.API_HOST ?? "0.0.0.0";
342004
342075
  NATS_URL = process.env.NATS_URL ?? "nats://localhost:4222";
342005
342076
  main().catch((error2) => {
342006
- log89.error("Failed to start API server", { error: String(error2) });
342077
+ log90.error("Failed to start API server", { error: String(error2) });
342007
342078
  process.exit(1);
342008
342079
  });
342009
342080
  });
@@ -458921,6 +458992,9 @@ function fromJid(jid) {
458921
458992
  const id = jid.split("@")[0] || "";
458922
458993
  return { id, isGroup, isUser, isBroadcast, isLid };
458923
458994
  }
458995
+ function isGroupJid(jid) {
458996
+ return jid.endsWith(JID_SUFFIX.GROUP);
458997
+ }
458924
458998
  function isUserJid(jid) {
458925
458999
  return jid.endsWith(JID_SUFFIX.USER);
458926
459000
  }
@@ -460300,7 +460374,6 @@ async function removeReaction4(sock, jid, targetMessageId, fromMe = true) {
460300
460374
 
460301
460375
  // ../channel-whatsapp/src/senders/stream.ts
460302
460376
  init_src();
460303
-
460304
460377
  // ../channel-whatsapp/src/utils/split-message.ts
460305
460378
  var DEFAULT_MAX_LENGTH2 = 65536;
460306
460379
  function splitByDelimiter(text, delimiter) {
@@ -460670,14 +460743,16 @@ class WhatsAppStreamSender {
460670
460743
  this.messageId = result?.key?.id ?? null;
460671
460744
  this.firstMessageSent = true;
460672
460745
  } else {
460673
- await this.getSock().sendMessage(this.jid, {
460674
- text,
460675
- edit: {
460676
- remoteJid: this.jid,
460677
- id: this.messageId,
460678
- fromMe: true
460679
- }
460680
- });
460746
+ const sock = this.getSock();
460747
+ const editKey = {
460748
+ remoteJid: this.jid,
460749
+ id: this.messageId,
460750
+ fromMe: true
460751
+ };
460752
+ if (isGroupJid(this.jid)) {
460753
+ editKey.participant = sock.user?.id;
460754
+ }
460755
+ await sock.sendMessage(this.jid, { text, edit: editKey });
460681
460756
  }
460682
460757
  this.lastRenderedText = text;
460683
460758
  this.lastEditAt = Date.now();
@@ -460693,14 +460768,16 @@ class WhatsAppStreamSender {
460693
460768
  async doEditRaw(text) {
460694
460769
  if (!this.messageId)
460695
460770
  throw new Error("No message to edit");
460696
- await this.getSock().sendMessage(this.jid, {
460697
- text,
460698
- edit: {
460699
- remoteJid: this.jid,
460700
- id: this.messageId,
460701
- fromMe: true
460702
- }
460703
- });
460771
+ const sock = this.getSock();
460772
+ const editKey = {
460773
+ remoteJid: this.jid,
460774
+ id: this.messageId,
460775
+ fromMe: true
460776
+ };
460777
+ if (isGroupJid(this.jid)) {
460778
+ editKey.participant = sock.user?.id;
460779
+ }
460780
+ await sock.sendMessage(this.jid, { text, edit: editKey });
460704
460781
  this.lastRenderedText = text;
460705
460782
  this.lastEditAt = Date.now();
460706
460783
  }
@@ -463229,11 +463306,33 @@ class WhatsAppPlugin extends BaseChannelPlugin {
463229
463306
  await this.humanDelay(instanceId);
463230
463307
  const sock = this.getSocket(instanceId);
463231
463308
  const jid = toJid(chatJid);
463232
- await sock.sendMessage(jid, {
463233
- edit: { remoteJid: jid, id: messageId, fromMe },
463234
- text: newText
463235
- });
463236
- this.logger.info("Message edited", { instanceId, chatJid: jid, messageId, fromMe });
463309
+ const editKey = {
463310
+ remoteJid: jid,
463311
+ id: messageId,
463312
+ fromMe
463313
+ };
463314
+ if (isGroupJid(jid) && fromMe) {
463315
+ editKey.participant = sock.user?.id;
463316
+ }
463317
+ try {
463318
+ const result = await sock.sendMessage(jid, { edit: editKey, text: newText });
463319
+ this.logger.info("Message edited", {
463320
+ instanceId,
463321
+ chatJid: jid,
463322
+ messageId,
463323
+ fromMe,
463324
+ resultKeyId: result?.key?.id
463325
+ });
463326
+ } catch (error) {
463327
+ this.logger.error("Failed to edit message via Baileys", {
463328
+ instanceId,
463329
+ chatJid: jid,
463330
+ messageId,
463331
+ fromMe,
463332
+ error: error instanceof Error ? error.message : String(error)
463333
+ });
463334
+ throw mapBaileysError(error);
463335
+ }
463237
463336
  }
463238
463337
  getSocket(instanceId) {
463239
463338
  const sock = this.sockets.get(instanceId);