@automagik/omni 2.260317.2 → 2.260320.1
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.
- package/dist/index.js +38 -16
- package/dist/resolve.d.ts.map +1 -1
- package/dist/server/index.js +406 -304
- package/package.json +9 -9
package/dist/server/index.js
CHANGED
|
@@ -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
|
|
27907
|
-
if (
|
|
27908
|
-
return
|
|
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:
|
|
27932
|
+
messages: messagesResult
|
|
27920
27933
|
}
|
|
27921
27934
|
};
|
|
27922
27935
|
}
|
|
@@ -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.
|
|
222920
|
+
version: "2.260320.1",
|
|
222908
222921
|
type: "module",
|
|
222909
222922
|
exports: {
|
|
222910
222923
|
".": {
|
|
@@ -323029,6 +323042,8 @@ function loadEnvVersion() {
|
|
|
323029
323042
|
return process.env.OMNI_VERSION ?? process.env.OMNI_SERVER_VERSION ?? process.env.npm_package_version ?? process.env.PACKAGE_VERSION ?? undefined;
|
|
323030
323043
|
}
|
|
323031
323044
|
function resolveFallbackVersion() {
|
|
323045
|
+
if (EMBEDDED_VERSION && EMBEDDED_VERSION !== "0.0.0")
|
|
323046
|
+
return EMBEDDED_VERSION;
|
|
323032
323047
|
return loadRepoPackageVersion() ?? loadEnvVersion() ?? LAST_RESORT_VERSION;
|
|
323033
323048
|
}
|
|
323034
323049
|
function loadServerVersionInfo() {
|
|
@@ -323052,9 +323067,11 @@ function loadServerVersionInfo() {
|
|
|
323052
323067
|
commit: FALLBACK_COMMIT
|
|
323053
323068
|
};
|
|
323054
323069
|
}
|
|
323055
|
-
var LAST_RESORT_VERSION = "2.0.0-dev.1", FALLBACK_COMMIT = "unknown", SERVER_VERSION_INFO, versionHeadersMiddleware;
|
|
323070
|
+
var import__package, EMBEDDED_VERSION, LAST_RESORT_VERSION = "2.0.0-dev.1", FALLBACK_COMMIT = "unknown", SERVER_VERSION_INFO, versionHeadersMiddleware;
|
|
323056
323071
|
var init_version_headers = __esm(() => {
|
|
323057
323072
|
init_factory2();
|
|
323073
|
+
import__package = __toESM(require_package8(), 1);
|
|
323074
|
+
EMBEDDED_VERSION = import__package.default?.version;
|
|
323058
323075
|
SERVER_VERSION_INFO = loadServerVersionInfo();
|
|
323059
323076
|
versionHeadersMiddleware = createMiddleware(async (c, next) => {
|
|
323060
323077
|
const cliVersion = c.req.header("x-omni-cli-version");
|
|
@@ -323096,13 +323113,13 @@ var init_webhook_auth = __esm(() => {
|
|
|
323096
323113
|
});
|
|
323097
323114
|
|
|
323098
323115
|
// ../api/src/routes/health.ts
|
|
323099
|
-
var
|
|
323116
|
+
var import__package2, VERSION4, startTime2, healthRoutes;
|
|
323100
323117
|
var init_health = __esm(() => {
|
|
323101
323118
|
init_src4();
|
|
323102
323119
|
init_drizzle_orm();
|
|
323103
323120
|
init_dist2();
|
|
323104
|
-
|
|
323105
|
-
VERSION4 =
|
|
323121
|
+
import__package2 = __toESM(require_package8(), 1);
|
|
323122
|
+
VERSION4 = import__package2.default.version;
|
|
323106
323123
|
startTime2 = Date.now();
|
|
323107
323124
|
healthRoutes = new Hono2;
|
|
323108
323125
|
healthRoutes.get("/health", async (c) => {
|
|
@@ -331861,7 +331878,7 @@ var init_instances3 = __esm(() => {
|
|
|
331861
331878
|
slackAppToken: exports_external.string().optional().nullable().describe("Slack app token (persisted for reconnection)"),
|
|
331862
331879
|
slackSigningSecret: exports_external.string().optional().nullable().describe("Slack signing secret (persisted for reconnection)"),
|
|
331863
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)"),
|
|
331864
|
-
groupHistorySize: exports_external.number().int().min(0).max(200).default(50).describe("Number of context messages to include
|
|
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)"),
|
|
331865
331882
|
reactionAck: exports_external.enum(["on", "off"]).default("off").describe("Reaction ack mode: on to send a reaction while agent processes"),
|
|
331866
331883
|
reactionAckEmoji: exports_external.record(exports_external.string()).optional().nullable().describe('Per-channel emoji map for reaction ack (e.g. {"whatsapp":"\\u2705"})'),
|
|
331867
331884
|
ackTimeoutMs: exports_external.number().int().min(0).max(120000).default(30000).describe("Ack timeout in milliseconds (max 120000)")
|
|
@@ -333752,6 +333769,19 @@ async function resolveMessageFromRef(services, ref) {
|
|
|
333752
333769
|
}
|
|
333753
333770
|
return found;
|
|
333754
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
|
+
}
|
|
333755
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;
|
|
333756
333786
|
var init_messages5 = __esm(() => {
|
|
333757
333787
|
init_dist6();
|
|
@@ -335031,10 +335061,28 @@ var init_messages5 = __esm(() => {
|
|
|
335031
335061
|
recoverable: false
|
|
335032
335062
|
});
|
|
335033
335063
|
}
|
|
335034
|
-
|
|
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
|
+
}
|
|
335035
335083
|
return c.json({
|
|
335036
335084
|
success: true,
|
|
335037
|
-
data: { messageId, edited: true }
|
|
335085
|
+
data: { messageId, externalId: resolvedMessageId, edited: true }
|
|
335038
335086
|
});
|
|
335039
335087
|
});
|
|
335040
335088
|
messagesRoutes.post("/delete-channel", zValidator("json", deleteMessageChannelSchema), async (c) => {
|
|
@@ -337607,6 +337655,93 @@ function buildWhatsAppMessageContext(rawPayload, chatId, instance4, text3) {
|
|
|
337607
337655
|
return { isDirectMessage, mentionsBot, isReplyToBot, text: text3 };
|
|
337608
337656
|
}
|
|
337609
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
|
+
|
|
337610
337745
|
// ../api/src/plugins/session-storage.ts
|
|
337611
337746
|
function scopeSessionKey(providerId, sessionKey) {
|
|
337612
337747
|
return `provider:${providerId}:session:${sessionKey}`;
|
|
@@ -337695,7 +337830,7 @@ class RateLimiter {
|
|
|
337695
337830
|
let timestamps = this.counters.get(key) ?? [];
|
|
337696
337831
|
timestamps = timestamps.filter((ts) => now - ts < this.windowMs);
|
|
337697
337832
|
if (timestamps.length >= maxPerMinute) {
|
|
337698
|
-
|
|
337833
|
+
log84.debug("Rate limit exceeded", { key, count: timestamps.length, limit: maxPerMinute });
|
|
337699
337834
|
return false;
|
|
337700
337835
|
}
|
|
337701
337836
|
timestamps.push(now);
|
|
@@ -337727,7 +337862,7 @@ class ReactionDedup {
|
|
|
337727
337862
|
}
|
|
337728
337863
|
const msgCount = this.messageCounters.get(messageId) ?? 0;
|
|
337729
337864
|
if (msgCount >= this.maxPerMessage) {
|
|
337730
|
-
|
|
337865
|
+
log84.debug("Reaction per-message limit reached", { messageId, count: msgCount });
|
|
337731
337866
|
return true;
|
|
337732
337867
|
}
|
|
337733
337868
|
this.seen.set(key, Date.now());
|
|
@@ -337750,73 +337885,6 @@ class ReactionDedup {
|
|
|
337750
337885
|
return false;
|
|
337751
337886
|
}
|
|
337752
337887
|
}
|
|
337753
|
-
|
|
337754
|
-
class MessageDebouncer {
|
|
337755
|
-
buffers = new Map;
|
|
337756
|
-
timers = new Map;
|
|
337757
|
-
onFlush;
|
|
337758
|
-
constructor(onFlush) {
|
|
337759
|
-
this.onFlush = onFlush;
|
|
337760
|
-
}
|
|
337761
|
-
getChatKey(instanceId, chatId) {
|
|
337762
|
-
return `${instanceId}:${chatId}`;
|
|
337763
|
-
}
|
|
337764
|
-
buffer(instanceId, chatId, message2, config4) {
|
|
337765
|
-
const chatKey = this.getChatKey(instanceId, chatId);
|
|
337766
|
-
const buffer3 = this.buffers.get(chatKey) ?? [];
|
|
337767
|
-
buffer3.push(message2);
|
|
337768
|
-
this.buffers.set(chatKey, buffer3);
|
|
337769
|
-
this.restartTimer(chatKey, config4);
|
|
337770
|
-
}
|
|
337771
|
-
onUserTyping(instanceId, chatId, config4) {
|
|
337772
|
-
const chatKey = this.getChatKey(instanceId, chatId);
|
|
337773
|
-
if (config4.restartOnTyping && this.buffers.has(chatKey)) {
|
|
337774
|
-
log83.debug("Restarting debounce timer on user typing", { chatKey });
|
|
337775
|
-
this.restartTimer(chatKey, config4);
|
|
337776
|
-
}
|
|
337777
|
-
}
|
|
337778
|
-
restartTimer(chatKey, config4) {
|
|
337779
|
-
const existing = this.timers.get(chatKey);
|
|
337780
|
-
if (config4.mode === "fixed" && existing)
|
|
337781
|
-
return;
|
|
337782
|
-
if (existing)
|
|
337783
|
-
clearTimeout(existing);
|
|
337784
|
-
let delay2;
|
|
337785
|
-
switch (config4.mode) {
|
|
337786
|
-
case "disabled":
|
|
337787
|
-
delay2 = 0;
|
|
337788
|
-
break;
|
|
337789
|
-
case "fixed":
|
|
337790
|
-
delay2 = config4.minMs;
|
|
337791
|
-
break;
|
|
337792
|
-
case "randomized":
|
|
337793
|
-
delay2 = config4.minMs + Math.random() * (config4.maxMs - config4.minMs);
|
|
337794
|
-
break;
|
|
337795
|
-
default:
|
|
337796
|
-
delay2 = 0;
|
|
337797
|
-
}
|
|
337798
|
-
const timer2 = setTimeout(() => this.flush(chatKey), delay2);
|
|
337799
|
-
this.timers.set(chatKey, timer2);
|
|
337800
|
-
}
|
|
337801
|
-
async flush(chatKey) {
|
|
337802
|
-
const messages4 = this.buffers.get(chatKey);
|
|
337803
|
-
this.buffers.delete(chatKey);
|
|
337804
|
-
this.timers.delete(chatKey);
|
|
337805
|
-
if (messages4?.length) {
|
|
337806
|
-
try {
|
|
337807
|
-
await this.onFlush(chatKey, messages4);
|
|
337808
|
-
} catch (error2) {
|
|
337809
|
-
log83.error("Error flushing debounced messages", { chatKey, error: String(error2) });
|
|
337810
|
-
}
|
|
337811
|
-
}
|
|
337812
|
-
}
|
|
337813
|
-
clear() {
|
|
337814
|
-
for (const timer2 of this.timers.values())
|
|
337815
|
-
clearTimeout(timer2);
|
|
337816
|
-
this.buffers.clear();
|
|
337817
|
-
this.timers.clear();
|
|
337818
|
-
}
|
|
337819
|
-
}
|
|
337820
337888
|
function getDebounceConfig(instance4) {
|
|
337821
337889
|
return {
|
|
337822
337890
|
mode: instance4.messageDebounceMode ?? "disabled",
|
|
@@ -337902,7 +337970,7 @@ async function sendTypingPresence(channel4, instanceId, chatId, state) {
|
|
|
337902
337970
|
await plugin6.sendTyping(instanceId, chatId, duration);
|
|
337903
337971
|
}
|
|
337904
337972
|
} catch (error2) {
|
|
337905
|
-
|
|
337973
|
+
log84.debug("Failed to send typing presence", { error: String(error2) });
|
|
337906
337974
|
}
|
|
337907
337975
|
}
|
|
337908
337976
|
async function sendTextMessage5(channel4, instanceId, chatId, text3, messageFormatMode = "convert", replyTo, correlationId, senderAgentId) {
|
|
@@ -337918,7 +337986,7 @@ async function sendTextMessage5(channel4, instanceId, chatId, text3, messageForm
|
|
|
337918
337986
|
}
|
|
337919
337987
|
async function sendErrorFeedback(channel4, instanceId, chatId, error2) {
|
|
337920
337988
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
337921
|
-
|
|
337989
|
+
log84.error("agent_dispatch_error", { channel: channel4, instanceId, chatId, error: errorMsg });
|
|
337922
337990
|
const text3 = "\u26A0\uFE0F Sorry, I ran into an issue processing your message. Please try again.";
|
|
337923
337991
|
await sendTextMessage5(channel4, instanceId, chatId, text3);
|
|
337924
337992
|
}
|
|
@@ -337968,7 +338036,7 @@ function resolveMediaPath2(mediaUrl) {
|
|
|
337968
338036
|
const fullPath = resolve2(MEDIA_BASE_PATH3, relativePath);
|
|
337969
338037
|
const basePath = resolve2(MEDIA_BASE_PATH3);
|
|
337970
338038
|
if (!fullPath.startsWith(`${basePath}/`) && fullPath !== basePath) {
|
|
337971
|
-
|
|
338039
|
+
log84.warn("Path traversal attempt blocked", { mediaUrl, resolved: fullPath, basePath });
|
|
337972
338040
|
return null;
|
|
337973
338041
|
}
|
|
337974
338042
|
return fullPath;
|
|
@@ -338025,7 +338093,7 @@ async function waitForMediaProcessing(services, instanceId, chatId, externalId,
|
|
|
338025
338093
|
return MEDIA_WAIT_NULL;
|
|
338026
338094
|
const chat2 = await services.chats.findByExternalIdSmart(instanceId, chatId);
|
|
338027
338095
|
if (!chat2) {
|
|
338028
|
-
|
|
338096
|
+
log84.warn("Chat not found for media wait", { instanceId, chatId });
|
|
338029
338097
|
return MEDIA_WAIT_NULL;
|
|
338030
338098
|
}
|
|
338031
338099
|
const deadline = Date.now() + 60000;
|
|
@@ -338033,14 +338101,14 @@ async function waitForMediaProcessing(services, instanceId, chatId, externalId,
|
|
|
338033
338101
|
const msg = await services.messages.getByExternalId(chat2.id, externalId);
|
|
338034
338102
|
const result = checkProcessedColumn(msg, column2);
|
|
338035
338103
|
if (result === "error") {
|
|
338036
|
-
|
|
338104
|
+
log84.warn("Media processing failed", { instanceId, chatId, externalId, error: msg?.[column2] });
|
|
338037
338105
|
return MEDIA_WAIT_NULL;
|
|
338038
338106
|
}
|
|
338039
338107
|
if (result !== "pending")
|
|
338040
338108
|
return result;
|
|
338041
338109
|
await sleep4(pollMs);
|
|
338042
338110
|
}
|
|
338043
|
-
|
|
338111
|
+
log84.warn("Media processing wait timed out", { instanceId, chatId, externalId, contentType });
|
|
338044
338112
|
return MEDIA_WAIT_NULL;
|
|
338045
338113
|
}
|
|
338046
338114
|
function formatProcessedMedia(contentType, fullPath, processedText, includePath, sendMediaPathTypes) {
|
|
@@ -338078,12 +338146,11 @@ async function resolveQuotedMessage(services, instanceId, chatId, replyToId) {
|
|
|
338078
338146
|
const content = getMessageContentText(quoted);
|
|
338079
338147
|
if (!content)
|
|
338080
338148
|
return null;
|
|
338081
|
-
const
|
|
338082
|
-
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;
|
|
338083
338150
|
const timeStr = time3 ? ` at ${time3}` : "";
|
|
338084
338151
|
return `[Quoting ${sender}${timeStr}: ${truncated}]`;
|
|
338085
338152
|
} catch (error2) {
|
|
338086
|
-
|
|
338153
|
+
log84.debug("Failed to resolve quoted message", { replyToId, error: String(error2) });
|
|
338087
338154
|
return null;
|
|
338088
338155
|
}
|
|
338089
338156
|
}
|
|
@@ -338156,11 +338223,11 @@ async function resolveContactName2(services, instanceId, jid, cacheMap) {
|
|
|
338156
338223
|
try {
|
|
338157
338224
|
const chat2 = await services.chats.findByExternalIdSmart(instanceId, jid);
|
|
338158
338225
|
if (chat2?.name) {
|
|
338159
|
-
|
|
338226
|
+
log84.debug("Contact name from DB fallback", { jid, name: chat2.name });
|
|
338160
338227
|
return chat2.name;
|
|
338161
338228
|
}
|
|
338162
338229
|
} catch (error2) {
|
|
338163
|
-
|
|
338230
|
+
log84.warn("Failed to query DB for contact", { jid, error: String(error2) });
|
|
338164
338231
|
}
|
|
338165
338232
|
return null;
|
|
338166
338233
|
}
|
|
@@ -338192,14 +338259,14 @@ async function applyJidMentionReplacement(services, instanceId, jid, jidToName,
|
|
|
338192
338259
|
async function replaceMentionsWithContactNames(services, instanceId, text3, mentionedJids, mentionedContacts) {
|
|
338193
338260
|
if (!mentionedJids?.length)
|
|
338194
338261
|
return text3;
|
|
338195
|
-
|
|
338262
|
+
log84.debug("Starting mention replacement", { mentionCount: mentionedJids.length });
|
|
338196
338263
|
const jidToName = buildJidNameMap(mentionedContacts);
|
|
338197
338264
|
const stats = { resolved: 0, replaced: 0, unresolved: 0, skipped: 0 };
|
|
338198
338265
|
let replacedText = text3;
|
|
338199
338266
|
for (const jid of mentionedJids) {
|
|
338200
338267
|
replacedText = await applyJidMentionReplacement(services, instanceId, jid, jidToName, replacedText, stats);
|
|
338201
338268
|
}
|
|
338202
|
-
|
|
338269
|
+
log84.debug("Mention replacement complete", {
|
|
338203
338270
|
original: text3,
|
|
338204
338271
|
replaced: replacedText,
|
|
338205
338272
|
mentionCount: mentionedJids.length,
|
|
@@ -338268,7 +338335,7 @@ async function fetchSenderMetadata(services, channel4, instanceId, senderId) {
|
|
|
338268
338335
|
platformUsername: identity?.platformUsername ?? undefined
|
|
338269
338336
|
};
|
|
338270
338337
|
} catch (error2) {
|
|
338271
|
-
|
|
338338
|
+
log84.debug("Failed to fetch sender identity metadata", { error: String(error2) });
|
|
338272
338339
|
return {};
|
|
338273
338340
|
}
|
|
338274
338341
|
}
|
|
@@ -338282,7 +338349,7 @@ async function fetchChatMetadata(services, instanceId, chatId, chatType) {
|
|
|
338282
338349
|
participantCount: chat2?.participantCount ?? undefined
|
|
338283
338350
|
};
|
|
338284
338351
|
} catch (error2) {
|
|
338285
|
-
|
|
338352
|
+
log84.debug("Failed to fetch chat metadata", { error: String(error2) });
|
|
338286
338353
|
return {};
|
|
338287
338354
|
}
|
|
338288
338355
|
}
|
|
@@ -338304,7 +338371,7 @@ async function routeStreamDelta(sender, delta) {
|
|
|
338304
338371
|
}
|
|
338305
338372
|
async function resolveStreamingCapabilities(services, instance4, channel4, chatId, traceId, db2) {
|
|
338306
338373
|
if (!instance4.agentStreamMode) {
|
|
338307
|
-
|
|
338374
|
+
log84.debug("Stream guard: agentStreamMode is falsy", {
|
|
338308
338375
|
instanceId: instance4.id,
|
|
338309
338376
|
agentStreamMode: instance4.agentStreamMode,
|
|
338310
338377
|
chatId
|
|
@@ -338313,7 +338380,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
338313
338380
|
}
|
|
338314
338381
|
const provider = await getAgentProvider(services, instance4, db2);
|
|
338315
338382
|
if (!provider?.triggerStream) {
|
|
338316
|
-
|
|
338383
|
+
log84.debug("Stream guard: provider has no triggerStream", {
|
|
338317
338384
|
instanceId: instance4.id,
|
|
338318
338385
|
hasProvider: !!provider,
|
|
338319
338386
|
chatId
|
|
@@ -338322,7 +338389,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
338322
338389
|
}
|
|
338323
338390
|
const plugin6 = await getPlugin(channel4);
|
|
338324
338391
|
if (!plugin6?.capabilities?.canStreamResponse || !plugin6.createStreamSender) {
|
|
338325
|
-
|
|
338392
|
+
log84.debug("Stream guard: channel does not support streaming", {
|
|
338326
338393
|
channel: channel4,
|
|
338327
338394
|
canStream: plugin6?.capabilities?.canStreamResponse,
|
|
338328
338395
|
chatId
|
|
@@ -338331,7 +338398,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
338331
338398
|
}
|
|
338332
338399
|
const streamKey = `${instance4.id}:${chatId}`;
|
|
338333
338400
|
if (activeStreams.has(streamKey)) {
|
|
338334
|
-
|
|
338401
|
+
log84.info("Stream guard: parallel stream blocked, falling back to accumulate", {
|
|
338335
338402
|
instanceId: instance4.id,
|
|
338336
338403
|
chatId,
|
|
338337
338404
|
traceId
|
|
@@ -338354,7 +338421,7 @@ async function consumeStream(generator, sender, instanceId, chatId, traceId) {
|
|
|
338354
338421
|
hadContent = true;
|
|
338355
338422
|
await routeStreamDelta(sender, delta);
|
|
338356
338423
|
}
|
|
338357
|
-
|
|
338424
|
+
log84.info("Streaming response complete", {
|
|
338358
338425
|
instanceId,
|
|
338359
338426
|
chatId,
|
|
338360
338427
|
durationMs: Date.now() - startTime3,
|
|
@@ -338482,7 +338549,7 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
|
|
|
338482
338549
|
}
|
|
338483
338550
|
return streamResult;
|
|
338484
338551
|
} catch (err) {
|
|
338485
|
-
|
|
338552
|
+
log84.error("Streaming dispatch failed, falling back", {
|
|
338486
338553
|
instanceId: instance4.id,
|
|
338487
338554
|
chatId,
|
|
338488
338555
|
error: String(err),
|
|
@@ -338532,20 +338599,26 @@ async function buildContextMessages(services, instance4, chatId, currentMessageI
|
|
|
338532
338599
|
if (!chat2) {
|
|
338533
338600
|
return [];
|
|
338534
338601
|
}
|
|
338602
|
+
const effectiveLimit = chat2.chatType === "group" ? historyLimit : Math.min(historyLimit, DM_HISTORY_LIMIT);
|
|
338535
338603
|
const messagesResult = await services.messages.list({
|
|
338536
338604
|
chatId: chat2.id,
|
|
338537
|
-
limit:
|
|
338605
|
+
limit: effectiveLimit
|
|
338538
338606
|
});
|
|
338539
338607
|
const recentMessages = messagesResult.items;
|
|
338540
338608
|
if (!recentMessages || recentMessages.length === 0) {
|
|
338541
338609
|
return [];
|
|
338542
338610
|
}
|
|
338543
338611
|
const lastBotMessageIndex = recentMessages.findIndex((msg) => msg.isFromMe === true);
|
|
338544
|
-
if (lastBotMessageIndex === -1 || lastBotMessageIndex === 0) {
|
|
338545
|
-
return [];
|
|
338546
|
-
}
|
|
338547
338612
|
const currentMessageIdSet = new Set(currentMessageIds.filter(Boolean));
|
|
338548
|
-
|
|
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
|
+
}
|
|
338549
338622
|
if (contextMsgs.length === 0) {
|
|
338550
338623
|
return [];
|
|
338551
338624
|
}
|
|
@@ -338560,7 +338633,7 @@ async function buildContextMessages(services, instance4, chatId, currentMessageI
|
|
|
338560
338633
|
return `[${name}${time3 ? ` - ${time3}` : ""}] ${text3}`;
|
|
338561
338634
|
});
|
|
338562
338635
|
} catch (error2) {
|
|
338563
|
-
|
|
338636
|
+
log84.warn("Failed to build context messages", { error: error2, chatId, instanceId: instance4.id });
|
|
338564
338637
|
return [];
|
|
338565
338638
|
}
|
|
338566
338639
|
}
|
|
@@ -338595,7 +338668,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
338595
338668
|
return false;
|
|
338596
338669
|
const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
|
|
338597
338670
|
if (!messageTexts.length && !mediaFiles.length) {
|
|
338598
|
-
|
|
338671
|
+
log84.debug("No text or media content for provider trigger, skipping");
|
|
338599
338672
|
return false;
|
|
338600
338673
|
}
|
|
338601
338674
|
if (!messageTexts.length && mediaFiles.length) {
|
|
@@ -338631,7 +338704,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
338631
338704
|
recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
|
|
338632
338705
|
await forwardToChainedInstance(instance4, parts, correlationId, messages4);
|
|
338633
338706
|
}
|
|
338634
|
-
|
|
338707
|
+
log84.info("Agent response via IAgentProvider", {
|
|
338635
338708
|
instanceId: instance4.id,
|
|
338636
338709
|
chatId,
|
|
338637
338710
|
parts: result?.parts.length ?? 0,
|
|
@@ -338645,14 +338718,14 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
338645
338718
|
async function dispatchViaLegacy(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId) {
|
|
338646
338719
|
const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
|
|
338647
338720
|
if (perThreadExtraContext?.length) {
|
|
338648
|
-
|
|
338721
|
+
log84.warn("per_thread context available but legacy dispatch path has limited support \u2014 prepending as text", {
|
|
338649
338722
|
instanceId: instance4.id,
|
|
338650
338723
|
contextCount: perThreadExtraContext.length
|
|
338651
338724
|
});
|
|
338652
338725
|
messageTexts.unshift(...perThreadExtraContext);
|
|
338653
338726
|
}
|
|
338654
338727
|
if (!messageTexts.length && !mediaFiles.length) {
|
|
338655
|
-
|
|
338728
|
+
log84.debug("No text or media content in messages, skipping agent call");
|
|
338656
338729
|
return;
|
|
338657
338730
|
}
|
|
338658
338731
|
if (!messageTexts.length && mediaFiles.length) {
|
|
@@ -338686,7 +338759,7 @@ async function dispatchViaLegacy(services, instance4, messages4, triggerType, ch
|
|
|
338686
338759
|
recordJourneyCheckpoint(correlationId, "T8", JOURNEY_STAGES.T8);
|
|
338687
338760
|
await sendResponseParts(channel4, instance4.id, chatId, parts, getSplitDelayConfig(instance4), _fmtMode, replyTo, correlationId, senderAgentId);
|
|
338688
338761
|
recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
|
|
338689
|
-
|
|
338762
|
+
log84.info("Agent response via legacy runner", {
|
|
338690
338763
|
instanceId: instance4.id,
|
|
338691
338764
|
chatId,
|
|
338692
338765
|
parts: result.parts.length,
|
|
@@ -338706,14 +338779,14 @@ async function performSessionReset(instance4, sessionId, chatId, services, db2,
|
|
|
338706
338779
|
sessionActuallyReset = true;
|
|
338707
338780
|
}
|
|
338708
338781
|
} catch (err) {
|
|
338709
|
-
|
|
338782
|
+
log84.warn("Failed to reset provider session", { error: String(err), instanceId: instance4.id, sessionId });
|
|
338710
338783
|
}
|
|
338711
338784
|
if (sessionActuallyReset) {
|
|
338712
338785
|
sessionActivityStore.recordReset(instance4.id, sessionId, Date.now());
|
|
338713
338786
|
eventBus.publish("session.reset", { instanceId: instance4.id, sessionId, timestamp: Date.now() }, { instanceId: instance4.id, channelType: channel4 }).catch((err) => {
|
|
338714
|
-
|
|
338787
|
+
log84.warn("Failed to publish session.reset event", { error: String(err), instanceId: instance4.id, sessionId });
|
|
338715
338788
|
});
|
|
338716
|
-
|
|
338789
|
+
log84.info("Session reset triggered", {
|
|
338717
338790
|
instanceId: instance4.id,
|
|
338718
338791
|
sessionId,
|
|
338719
338792
|
strategy: resetStrategy,
|
|
@@ -338756,7 +338829,7 @@ async function markPerThreadSessionInitialized(db2, instanceId, sessionId) {
|
|
|
338756
338829
|
target: [agentSessions.instanceId, agentSessions.sessionKey],
|
|
338757
338830
|
set: { lastUsedAt: now, updatedAt: now }
|
|
338758
338831
|
});
|
|
338759
|
-
|
|
338832
|
+
log84.info("per_thread session initialized", { instanceId, sessionId });
|
|
338760
338833
|
}
|
|
338761
338834
|
function mimeToContentType(mimeType) {
|
|
338762
338835
|
if (mimeType.startsWith("audio/"))
|
|
@@ -338795,7 +338868,7 @@ async function processMediaFile(msg, mimeType, mediaService) {
|
|
|
338795
338868
|
const result = await mediaService.process(localPath, mimeType, { caption: msg.content.caption });
|
|
338796
338869
|
return result.success && result.content ? result.content : null;
|
|
338797
338870
|
} catch (err) {
|
|
338798
|
-
|
|
338871
|
+
log84.debug("Media processing failed for history message", { error: String(err), messageId: msg.externalId });
|
|
338799
338872
|
return null;
|
|
338800
338873
|
} finally {
|
|
338801
338874
|
if (ownedTempFile) {
|
|
@@ -338832,7 +338905,7 @@ async function processHistoryMessage2(msg, mediaService, reactFn, unreactFn) {
|
|
|
338832
338905
|
async function fetchAndProcessThreadHistory(services, instance4, channel4, chatId, threadId2) {
|
|
338833
338906
|
const plugin6 = await getPlugin(channel4);
|
|
338834
338907
|
if (!plugin6?.fetchHistory) {
|
|
338835
|
-
|
|
338908
|
+
log84.debug("Channel plugin does not support fetchHistory", { instanceId: instance4.id, channel: channel4 });
|
|
338836
338909
|
return [];
|
|
338837
338910
|
}
|
|
338838
338911
|
let historyResult;
|
|
@@ -338843,7 +338916,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
338843
338916
|
limit: 200
|
|
338844
338917
|
});
|
|
338845
338918
|
} catch (err) {
|
|
338846
|
-
|
|
338919
|
+
log84.warn("fetchHistory failed, proceeding without thread context", {
|
|
338847
338920
|
error: String(err),
|
|
338848
338921
|
instanceId: instance4.id,
|
|
338849
338922
|
channel: channel4
|
|
@@ -338873,7 +338946,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
338873
338946
|
const results = await Promise.all(batch.map((msg) => processHistoryMessage2(msg, mediaService, reactFn, unreactFn)));
|
|
338874
338947
|
contextMessages.push(...results);
|
|
338875
338948
|
}
|
|
338876
|
-
|
|
338949
|
+
log84.info("Thread history fetched", {
|
|
338877
338950
|
instanceId: instance4.id,
|
|
338878
338951
|
channel: channel4,
|
|
338879
338952
|
chatId,
|
|
@@ -338884,7 +338957,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
338884
338957
|
return contextMessages;
|
|
338885
338958
|
}
|
|
338886
338959
|
async function handlePerThreadLazyInit(services, instance4, channel4, chatId, threadId2, sessionId, db2) {
|
|
338887
|
-
|
|
338960
|
+
log84.info("per_thread lazy init", {
|
|
338888
338961
|
instanceId: instance4.id,
|
|
338889
338962
|
channel: channel4,
|
|
338890
338963
|
chatId,
|
|
@@ -338895,7 +338968,7 @@ async function handlePerThreadLazyInit(services, instance4, channel4, chatId, th
|
|
|
338895
338968
|
try {
|
|
338896
338969
|
await markPerThreadSessionInitialized(db2, instance4.id, sessionId);
|
|
338897
338970
|
} catch (err) {
|
|
338898
|
-
|
|
338971
|
+
log84.warn("Failed to mark per_thread session initialized", {
|
|
338899
338972
|
error: String(err),
|
|
338900
338973
|
instanceId: instance4.id,
|
|
338901
338974
|
sessionId
|
|
@@ -338937,7 +339010,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
338937
339010
|
const ackHandle = startAck(plugin6, ackProvider, instance4.id, chatId, messageId, channel4, ackConfig);
|
|
338938
339011
|
const personId = await resolvePersonId(services, channel4, instance4.id, senderId, firstMessage.metadata.personId);
|
|
338939
339012
|
if (!personId) {
|
|
338940
|
-
|
|
339013
|
+
log84.warn("Could not resolve person ID, skipping agent", {
|
|
338941
339014
|
instanceId: instance4.id,
|
|
338942
339015
|
chatId,
|
|
338943
339016
|
senderId
|
|
@@ -338950,7 +339023,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
338950
339023
|
const pushName = rawPayload.pushName ?? rawPayload.displayName;
|
|
338951
339024
|
const senderName = await services.agentRunner.getSenderName(personId, pushName);
|
|
338952
339025
|
const senderAgentId = await resolveDispatchSenderAgentId(db2, instance4);
|
|
338953
|
-
|
|
339026
|
+
log84.info("Dispatching to agent", {
|
|
338954
339027
|
instanceId: instance4.id,
|
|
338955
339028
|
chatId,
|
|
338956
339029
|
messageCount: messages4.length,
|
|
@@ -338963,7 +339036,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
338963
339036
|
const agentAckMessage = inst.agentAckMessage ?? null;
|
|
338964
339037
|
if (agentAckMessage) {
|
|
338965
339038
|
sendTextMessage5(channel4, instance4.id, chatId, agentAckMessage).catch((err) => {
|
|
338966
|
-
|
|
339039
|
+
log84.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
|
|
338967
339040
|
});
|
|
338968
339041
|
}
|
|
338969
339042
|
const perThreadExtraContext = await resolvePerThreadExtraContext(db2, services, instance4, channel4, chatId, senderId, firstMessage);
|
|
@@ -338976,7 +339049,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
338976
339049
|
handled = await dispatchViaProvider(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, rawEvent, db2, perThreadExtraContext, senderAgentId);
|
|
338977
339050
|
}
|
|
338978
339051
|
} catch (providerError) {
|
|
338979
|
-
|
|
339052
|
+
log84.error("Provider dispatch failed, falling back to legacy", {
|
|
338980
339053
|
instanceId: instance4.id,
|
|
338981
339054
|
chatId,
|
|
338982
339055
|
error: String(providerError),
|
|
@@ -338987,12 +339060,12 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
338987
339060
|
ackHandle.remove();
|
|
338988
339061
|
return;
|
|
338989
339062
|
}
|
|
338990
|
-
|
|
339063
|
+
log84.debug("No IAgentProvider resolved or provider failed, using legacy agentRunner path", {
|
|
338991
339064
|
instanceId: instance4.id
|
|
338992
339065
|
});
|
|
338993
339066
|
await dispatchViaLegacy(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId);
|
|
338994
339067
|
} catch (error2) {
|
|
338995
|
-
|
|
339068
|
+
log84.error("Failed to process agent response", {
|
|
338996
339069
|
instanceId: instance4.id,
|
|
338997
339070
|
chatId,
|
|
338998
339071
|
error: String(error2),
|
|
@@ -339036,7 +339109,7 @@ function createOpenClawProviderInstance(provider, instance4) {
|
|
|
339036
339109
|
}
|
|
339037
339110
|
function createAgnoProvider(provider, instance4) {
|
|
339038
339111
|
if (!provider.apiKey) {
|
|
339039
|
-
|
|
339112
|
+
log84.warn("Provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
339040
339113
|
return null;
|
|
339041
339114
|
}
|
|
339042
339115
|
const client = createProviderClient({
|
|
@@ -339058,7 +339131,7 @@ function createClaudeCodeProviderInstance(provider, instance4, db2) {
|
|
|
339058
339131
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
339059
339132
|
const projectPath = schemaConfig.projectPath;
|
|
339060
339133
|
if (!projectPath) {
|
|
339061
|
-
|
|
339134
|
+
log84.error("Claude Code provider missing projectPath", { providerId: provider.id });
|
|
339062
339135
|
throw new Error("Claude Code provider requires schemaConfig.projectPath");
|
|
339063
339136
|
}
|
|
339064
339137
|
return new ClaudeCodeAgentProvider(provider.id, provider.name, {
|
|
@@ -339089,7 +339162,7 @@ function createWebhookProvider(provider) {
|
|
|
339089
339162
|
}
|
|
339090
339163
|
function createAgUiProviderInstance(provider, instance4) {
|
|
339091
339164
|
if (!provider.apiKey) {
|
|
339092
|
-
|
|
339165
|
+
log84.warn("AG-UI provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
339093
339166
|
return null;
|
|
339094
339167
|
}
|
|
339095
339168
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
@@ -339108,7 +339181,7 @@ function createAgUiProviderInstance(provider, instance4) {
|
|
|
339108
339181
|
}
|
|
339109
339182
|
function createA2AProviderInstance(provider, instance4) {
|
|
339110
339183
|
if (!provider.apiKey) {
|
|
339111
|
-
|
|
339184
|
+
log84.warn("A2A provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
339112
339185
|
return null;
|
|
339113
339186
|
}
|
|
339114
339187
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
@@ -339130,7 +339203,7 @@ function createGenieProviderInstance(provider, instance4) {
|
|
|
339130
339203
|
const agentName = typeof schemaConfig.agentName === "string" ? schemaConfig.agentName : "";
|
|
339131
339204
|
const targetAgent = typeof schemaConfig.targetAgent === "string" ? schemaConfig.targetAgent : "";
|
|
339132
339205
|
if (!agentName || !targetAgent) {
|
|
339133
|
-
|
|
339206
|
+
log84.error("Genie provider missing agentName or targetAgent in schemaConfig", { providerId: provider.id });
|
|
339134
339207
|
return null;
|
|
339135
339208
|
}
|
|
339136
339209
|
const teamName = typeof schemaConfig.teamName === "string" ? schemaConfig.teamName : "genie";
|
|
@@ -339169,7 +339242,7 @@ function resolveProvider(provider, instance4, db2) {
|
|
|
339169
339242
|
agentProvider = createGenieProviderInstance(provider, instance4);
|
|
339170
339243
|
break;
|
|
339171
339244
|
default:
|
|
339172
|
-
|
|
339245
|
+
log84.debug("Provider schema not supported for IAgentProvider dispatch", {
|
|
339173
339246
|
schema: provider.schema,
|
|
339174
339247
|
providerId: provider.id
|
|
339175
339248
|
});
|
|
@@ -339189,7 +339262,7 @@ async function getAgentProvider(services, instance4, db2) {
|
|
|
339189
339262
|
return null;
|
|
339190
339263
|
return resolveProvider(provider, instance4, db2);
|
|
339191
339264
|
} catch (error2) {
|
|
339192
|
-
|
|
339265
|
+
log84.warn("Failed to resolve agent provider, falling back to legacy", {
|
|
339193
339266
|
instanceId: instance4.id,
|
|
339194
339267
|
providerId: instance4.agentProviderId,
|
|
339195
339268
|
error: String(error2)
|
|
@@ -339223,7 +339296,7 @@ async function applyInstanceFkAndReturn(db2, instance4) {
|
|
|
339223
339296
|
}
|
|
339224
339297
|
async function resolveEffectiveInstance(services, db2, instance4, chatId, personId) {
|
|
339225
339298
|
if (!chatId) {
|
|
339226
|
-
|
|
339299
|
+
log84.debug("No internal chatId \u2014 using instance default agent", { instanceId: instance4.id, personId });
|
|
339227
339300
|
return applyInstanceFkAndReturn(db2, instance4);
|
|
339228
339301
|
}
|
|
339229
339302
|
const route = await services.routeResolver.resolve(instance4.id, chatId, personId);
|
|
@@ -339247,7 +339320,7 @@ async function resolveEffectiveInstance(services, db2, instance4, chatId, person
|
|
|
339247
339320
|
if (effectiveAgentFkId) {
|
|
339248
339321
|
await applyAgentFkOverrides(db2, effectiveAgentFkId, effectiveInstance);
|
|
339249
339322
|
}
|
|
339250
|
-
|
|
339323
|
+
log84.debug("Route resolved and merged", {
|
|
339251
339324
|
instanceId: instance4.id,
|
|
339252
339325
|
chatId,
|
|
339253
339326
|
personId,
|
|
@@ -339267,7 +339340,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
339267
339340
|
const chat2 = await services.chats.findByExternalIdSmart(baseInstance.id, externalChatId);
|
|
339268
339341
|
const internalChatId = chat2?.id;
|
|
339269
339342
|
const { instance: instance4, routeId: _routeId } = await resolveEffectiveInstance(services, db2, baseInstance, internalChatId, metadata.personId);
|
|
339270
|
-
|
|
339343
|
+
log84.info("Dispatching reaction trigger", {
|
|
339271
339344
|
instanceId: instance4.id,
|
|
339272
339345
|
chatId: externalChatId,
|
|
339273
339346
|
routeChatId: internalChatId ?? "none",
|
|
@@ -339307,7 +339380,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
339307
339380
|
const _fmtMode = instance4.messageFormatMode ?? "convert";
|
|
339308
339381
|
await sendResponseParts(channel4, instance4.id, externalChatId, result2.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
|
|
339309
339382
|
}
|
|
339310
|
-
|
|
339383
|
+
log84.info("Reaction trigger response via provider", {
|
|
339311
339384
|
instanceId: instance4.id,
|
|
339312
339385
|
chatId: externalChatId,
|
|
339313
339386
|
routeChatId: internalChatId,
|
|
@@ -339319,7 +339392,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
339319
339392
|
});
|
|
339320
339393
|
return;
|
|
339321
339394
|
}
|
|
339322
|
-
|
|
339395
|
+
log84.debug("No IAgentProvider resolved, using legacy agentRunner path", {
|
|
339323
339396
|
instanceId: instance4.id
|
|
339324
339397
|
});
|
|
339325
339398
|
const personId = await resolvePersonId(services, channel4, instance4.id, payload.from, metadata.personId);
|
|
@@ -339345,7 +339418,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
339345
339418
|
const _fmtMode = instance4.messageFormatMode ?? "convert";
|
|
339346
339419
|
await sendResponseParts(channel4, instance4.id, externalChatId, result.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
|
|
339347
339420
|
}
|
|
339348
|
-
|
|
339421
|
+
log84.info("Reaction trigger response via legacy runner", {
|
|
339349
339422
|
instanceId: instance4.id,
|
|
339350
339423
|
chatId: externalChatId,
|
|
339351
339424
|
routeChatId: internalChatId,
|
|
@@ -339354,7 +339427,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
339354
339427
|
traceId: metadata.traceId
|
|
339355
339428
|
});
|
|
339356
339429
|
} catch (error2) {
|
|
339357
|
-
|
|
339430
|
+
log84.error("Failed to process reaction trigger", {
|
|
339358
339431
|
instanceId: instance4.id,
|
|
339359
339432
|
chatId: externalChatId,
|
|
339360
339433
|
routeChatId: internalChatId,
|
|
@@ -339396,7 +339469,7 @@ async function resolveLidMentionBot(chatsService, instanceId, ownerIdentifier, m
|
|
|
339396
339469
|
for (const lidJid of lidMentions) {
|
|
339397
339470
|
if (ownerIsLid && extractPhoneFromJid(lidJid) === ownerPhone) {
|
|
339398
339471
|
messageContext.mentionsBot = true;
|
|
339399
|
-
|
|
339472
|
+
log84.debug("LID mention matches owner LID directly", { lidJid, ownerIdentifier });
|
|
339400
339473
|
break;
|
|
339401
339474
|
}
|
|
339402
339475
|
try {
|
|
@@ -339405,14 +339478,14 @@ async function resolveLidMentionBot(chatsService, instanceId, ownerIdentifier, m
|
|
|
339405
339478
|
const resolvedPhone = extractPhoneFromJid(mapping);
|
|
339406
339479
|
if (resolvedPhone === ownerPhone) {
|
|
339407
339480
|
messageContext.mentionsBot = true;
|
|
339408
|
-
|
|
339481
|
+
log84.debug("LID resolved to instance owner via DB", { lidJid, resolvedPhone, ownerPhone });
|
|
339409
339482
|
break;
|
|
339410
339483
|
}
|
|
339411
339484
|
if (ownerIsLid) {
|
|
339412
339485
|
const ownerMapping = await chatsService.findLidMapping(instanceId, ownerIdentifier);
|
|
339413
339486
|
if (ownerMapping && extractPhoneFromJid(ownerMapping) === resolvedPhone) {
|
|
339414
339487
|
messageContext.mentionsBot = true;
|
|
339415
|
-
|
|
339488
|
+
log84.debug("LID resolved to owner via reverse mapping", { lidJid, resolvedPhone, ownerIdentifier });
|
|
339416
339489
|
break;
|
|
339417
339490
|
}
|
|
339418
339491
|
}
|
|
@@ -339446,15 +339519,15 @@ function needsLidMentionCheck(messageContext, instance4) {
|
|
|
339446
339519
|
}
|
|
339447
339520
|
async function shouldProcessMessage3(agentRunner, accessService, chatsService, messagesService, routeResolver, rateLimiter, payload, metadata) {
|
|
339448
339521
|
if (!metadata.instanceId) {
|
|
339449
|
-
|
|
339522
|
+
log84.debug("No instanceId in metadata", { from: payload.from, chatId: payload.chatId });
|
|
339450
339523
|
return null;
|
|
339451
339524
|
}
|
|
339452
339525
|
if (payload.from === metadata.platformIdentityId) {
|
|
339453
|
-
|
|
339526
|
+
log84.debug("Message from self, skipping", { instanceId: metadata.instanceId, from: payload.from });
|
|
339454
339527
|
return null;
|
|
339455
339528
|
}
|
|
339456
339529
|
if (isTrashEmojiOnly(payload.content?.text)) {
|
|
339457
|
-
|
|
339530
|
+
log84.debug("Skipping trash emoji message (session-cleaner handles this)", {
|
|
339458
339531
|
instanceId: metadata.instanceId,
|
|
339459
339532
|
chatId: payload.chatId
|
|
339460
339533
|
});
|
|
@@ -339462,16 +339535,16 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
339462
339535
|
}
|
|
339463
339536
|
const chatId = payload.chatId ?? "";
|
|
339464
339537
|
if (isBroadcastOrNewsletter(chatId)) {
|
|
339465
|
-
|
|
339538
|
+
log84.debug("Skipping newsletter/broadcast message", { instanceId: metadata.instanceId, chatId });
|
|
339466
339539
|
return null;
|
|
339467
339540
|
}
|
|
339468
339541
|
const instance4 = await agentRunner.getInstanceWithProvider(metadata.instanceId);
|
|
339469
339542
|
if (!instance4?.agentId) {
|
|
339470
|
-
|
|
339543
|
+
log84.debug("Instance has no agentId", { instanceId: metadata.instanceId });
|
|
339471
339544
|
return null;
|
|
339472
339545
|
}
|
|
339473
339546
|
if (!instanceTriggersOnEvent(instance4, "message.received")) {
|
|
339474
|
-
|
|
339547
|
+
log84.debug("Instance does not trigger on message.received", { instanceId: instance4.id });
|
|
339475
339548
|
return null;
|
|
339476
339549
|
}
|
|
339477
339550
|
const messageContext = buildMessageContext(payload, instance4);
|
|
@@ -339481,7 +339554,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
339481
339554
|
await resolveLidMentionBot(chatsService, metadata.instanceId, instance4.ownerIdentifier, mentionedJids, messageContext);
|
|
339482
339555
|
}
|
|
339483
339556
|
await resolveSlackThreadReply(chatsService, messagesService, instance4, payload, messageContext);
|
|
339484
|
-
|
|
339557
|
+
log84.debug("Message context built", {
|
|
339485
339558
|
instanceId: instance4.id,
|
|
339486
339559
|
chatId: payload.chatId,
|
|
339487
339560
|
isDirectMessage: messageContext.isDirectMessage,
|
|
@@ -339491,7 +339564,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
339491
339564
|
});
|
|
339492
339565
|
const effectiveReplyFilter = await resolveEffectiveReplyFilter(chatsService, routeResolver, instance4.id, payload.chatId, instance4.agentReplyFilter);
|
|
339493
339566
|
if (!shouldAgentReply(effectiveReplyFilter, messageContext)) {
|
|
339494
|
-
|
|
339567
|
+
log84.debug("Message did not pass reply filter", {
|
|
339495
339568
|
instanceId: instance4.id,
|
|
339496
339569
|
chatId: payload.chatId,
|
|
339497
339570
|
messageContext,
|
|
@@ -339502,7 +339575,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
339502
339575
|
const channel4 = metadata.channelType ?? "whatsapp";
|
|
339503
339576
|
const rateLimit = instance4.triggerRateLimit;
|
|
339504
339577
|
if (!rateLimiter.isAllowed(payload.from, channel4, instance4.id, rateLimit ?? DEFAULT_RATE_LIMIT)) {
|
|
339505
|
-
|
|
339578
|
+
log84.info("Rate limited", { instanceId: instance4.id, from: payload.from, channel: channel4 });
|
|
339506
339579
|
return null;
|
|
339507
339580
|
}
|
|
339508
339581
|
const accessDenied = await checkAccessWithFallback(accessService, instance4, payload, channel4);
|
|
@@ -339520,7 +339593,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
339520
339593
|
const primaryId = payload.from ?? "";
|
|
339521
339594
|
let accessResult = await accessService.checkAccess(instance4, primaryId, channel4);
|
|
339522
339595
|
if (!accessResult.allowed && participantAlt && participantAlt !== primaryId) {
|
|
339523
|
-
|
|
339596
|
+
log84.warn("Access fallback to participantAlt", {
|
|
339524
339597
|
instanceId: instance4.id,
|
|
339525
339598
|
primaryId,
|
|
339526
339599
|
participantAlt,
|
|
@@ -339529,7 +339602,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
339529
339602
|
accessResult = await accessService.checkAccess(instance4, participantAlt, channel4);
|
|
339530
339603
|
}
|
|
339531
339604
|
if (!accessResult.allowed && resolvedSenderPhone && resolvedSenderPhone !== primaryId && resolvedSenderPhone !== participantAlt) {
|
|
339532
|
-
|
|
339605
|
+
log84.debug("Access fallback to resolvedSenderPhone (LID\u2192phone)", {
|
|
339533
339606
|
instanceId: instance4.id,
|
|
339534
339607
|
primaryId,
|
|
339535
339608
|
resolvedSenderPhone,
|
|
@@ -339539,7 +339612,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
339539
339612
|
}
|
|
339540
339613
|
if (accessResult.allowed)
|
|
339541
339614
|
return false;
|
|
339542
|
-
|
|
339615
|
+
log84.info("Access denied", {
|
|
339543
339616
|
instanceId: instance4.id,
|
|
339544
339617
|
chatId: payload.chatId,
|
|
339545
339618
|
from: payload.from,
|
|
@@ -339548,7 +339621,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
339548
339621
|
});
|
|
339549
339622
|
if (accessResult.mode === "allowlist" && !accessResult.rule && primaryId) {
|
|
339550
339623
|
accessService.requestPairing(instance4.id, primaryId).catch((err) => {
|
|
339551
|
-
|
|
339624
|
+
log84.warn("Failed to create pairing request", { instanceId: instance4.id, from: primaryId, error: String(err) });
|
|
339552
339625
|
});
|
|
339553
339626
|
}
|
|
339554
339627
|
if (accessResult.rule?.action !== "silent_block" && accessResult.rule?.blockMessage) {
|
|
@@ -339565,20 +339638,20 @@ async function shouldProcessReaction(agentRunner, accessService, rateLimiter, re
|
|
|
339565
339638
|
if (!instanceTriggersOnEvent(instance4, eventType))
|
|
339566
339639
|
return null;
|
|
339567
339640
|
if (!isReactionTrigger(instance4, payload.emoji)) {
|
|
339568
|
-
|
|
339641
|
+
log84.debug("Reaction emoji not in trigger list", { instanceId: instance4.id, emoji: payload.emoji });
|
|
339569
339642
|
return null;
|
|
339570
339643
|
}
|
|
339571
339644
|
const channel4 = metadata.channelType ?? "whatsapp";
|
|
339572
339645
|
const rateLimit = instance4.triggerRateLimit;
|
|
339573
339646
|
if (!rateLimiter.isAllowed(payload.from, channel4, instance4.id, rateLimit ?? DEFAULT_RATE_LIMIT)) {
|
|
339574
|
-
|
|
339647
|
+
log84.info("Rate limited reaction trigger", { instanceId: instance4.id, from: payload.from });
|
|
339575
339648
|
return null;
|
|
339576
339649
|
}
|
|
339577
339650
|
const accessDenied = await checkAccessWithFallback(accessService, instance4, payload, channel4);
|
|
339578
339651
|
if (accessDenied)
|
|
339579
339652
|
return null;
|
|
339580
339653
|
if (reactionDedup.isDuplicate(payload.messageId, payload.emoji, payload.from)) {
|
|
339581
|
-
|
|
339654
|
+
log84.debug("Duplicate reaction, skipping", {
|
|
339582
339655
|
instanceId: instance4.id,
|
|
339583
339656
|
messageId: payload.messageId,
|
|
339584
339657
|
emoji: payload.emoji
|
|
@@ -339611,7 +339684,7 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
339611
339684
|
try {
|
|
339612
339685
|
const apiKey = await settings.getSecret("gemini.api_key", "GEMINI_API_KEY");
|
|
339613
339686
|
if (!apiKey) {
|
|
339614
|
-
|
|
339687
|
+
log84.warn("Gate: no Gemini API key, fail-open", { traceId });
|
|
339615
339688
|
return true;
|
|
339616
339689
|
}
|
|
339617
339690
|
const controller = new AbortController;
|
|
@@ -339629,13 +339702,13 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
339629
339702
|
});
|
|
339630
339703
|
clearTimeout(timeout);
|
|
339631
339704
|
if (!res.ok) {
|
|
339632
|
-
|
|
339705
|
+
log84.warn("Gate: API error, fail-open", { traceId, status: res.status, durationMs: Date.now() - startMs });
|
|
339633
339706
|
return true;
|
|
339634
339707
|
}
|
|
339635
339708
|
const data = await res.json();
|
|
339636
339709
|
const answer = data.candidates?.[0]?.content?.parts?.[0]?.text?.trim().toLowerCase() ?? "";
|
|
339637
339710
|
const shouldRespond = !answer.startsWith("skip");
|
|
339638
|
-
|
|
339711
|
+
log84.info("Gate decision", {
|
|
339639
339712
|
traceId,
|
|
339640
339713
|
decision: shouldRespond ? "respond" : "skip",
|
|
339641
339714
|
rawAnswer: answer,
|
|
@@ -339649,14 +339722,14 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
339649
339722
|
clearTimeout(timeout);
|
|
339650
339723
|
const errName = fetchError.name;
|
|
339651
339724
|
if (errName === "AbortError") {
|
|
339652
|
-
|
|
339725
|
+
log84.warn("Gate: timeout, fail-open", { traceId, durationMs: Date.now() - startMs });
|
|
339653
339726
|
} else {
|
|
339654
|
-
|
|
339727
|
+
log84.warn("Gate: fetch error, fail-open", { traceId, error: String(fetchError) });
|
|
339655
339728
|
}
|
|
339656
339729
|
return true;
|
|
339657
339730
|
}
|
|
339658
339731
|
} catch (error2) {
|
|
339659
|
-
|
|
339732
|
+
log84.warn("Gate: unexpected error, fail-open", { traceId, error: String(error2) });
|
|
339660
339733
|
return true;
|
|
339661
339734
|
}
|
|
339662
339735
|
}
|
|
@@ -339666,7 +339739,7 @@ async function shouldSkipViaGate(triggerType, firstMsg, instance4, messages4, se
|
|
|
339666
339739
|
const chatType = determineChatType(firstMsg.payload.chatId, firstMsg.metadata.channelType ?? "whatsapp", firstMsg.payload.rawPayload ?? {});
|
|
339667
339740
|
const shouldRespond = await shouldRespondViaGate(instance4, messages4, chatType, services.settings);
|
|
339668
339741
|
if (!shouldRespond) {
|
|
339669
|
-
|
|
339742
|
+
log84.info("Gate skipped response", {
|
|
339670
339743
|
instanceId: instance4.id,
|
|
339671
339744
|
chatId: firstMsg.payload.chatId,
|
|
339672
339745
|
triggerType,
|
|
@@ -339689,7 +339762,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339689
339762
|
const instanceId = firstMsg.metadata.instanceId;
|
|
339690
339763
|
const baseInstance = await agentRunner.getInstanceWithProvider(instanceId);
|
|
339691
339764
|
if (!baseInstance) {
|
|
339692
|
-
|
|
339765
|
+
log84.warn("Instance not found for debounced messages", { instanceId });
|
|
339693
339766
|
return;
|
|
339694
339767
|
}
|
|
339695
339768
|
const externalChatId = firstMsg.payload.chatId;
|
|
@@ -339737,7 +339810,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339737
339810
|
timestamp: event.timestamp
|
|
339738
339811
|
}, effectiveDebounceConfig);
|
|
339739
339812
|
} catch (error2) {
|
|
339740
|
-
|
|
339813
|
+
log84.error("Error processing message for dispatch", {
|
|
339741
339814
|
instanceId: metadata.instanceId,
|
|
339742
339815
|
error: String(error2)
|
|
339743
339816
|
});
|
|
@@ -339766,7 +339839,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339766
339839
|
traceId
|
|
339767
339840
|
}, event, db2);
|
|
339768
339841
|
} catch (error2) {
|
|
339769
|
-
|
|
339842
|
+
log84.error("Error processing reaction for dispatch", {
|
|
339770
339843
|
instanceId: metadata.instanceId,
|
|
339771
339844
|
error: String(error2)
|
|
339772
339845
|
});
|
|
@@ -339795,7 +339868,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339795
339868
|
traceId
|
|
339796
339869
|
}, event, db2);
|
|
339797
339870
|
} catch (error2) {
|
|
339798
|
-
|
|
339871
|
+
log84.error("Error processing reaction removal for dispatch", {
|
|
339799
339872
|
instanceId: metadata.instanceId,
|
|
339800
339873
|
error: String(error2)
|
|
339801
339874
|
});
|
|
@@ -339822,7 +339895,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339822
339895
|
debouncer.onUserTyping(metadata.instanceId, payload.chatId, debounceConfig);
|
|
339823
339896
|
}
|
|
339824
339897
|
} catch (error2) {
|
|
339825
|
-
|
|
339898
|
+
log84.debug("Error handling typing event", { error: String(error2) });
|
|
339826
339899
|
}
|
|
339827
339900
|
}, {
|
|
339828
339901
|
durable: "agent-dispatcher-typing",
|
|
@@ -339831,22 +339904,22 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339831
339904
|
startFrom: "last",
|
|
339832
339905
|
concurrency: 10
|
|
339833
339906
|
});
|
|
339834
|
-
|
|
339907
|
+
log84.info("Agent dispatcher initialized (message + reaction + reaction-removed triggers)");
|
|
339835
339908
|
} catch (error2) {
|
|
339836
|
-
|
|
339909
|
+
log84.error("Failed to set up agent dispatcher", { error: String(error2) });
|
|
339837
339910
|
clearInterval(cleanupInterval2);
|
|
339838
339911
|
debouncer.clear();
|
|
339839
339912
|
throw error2;
|
|
339840
339913
|
}
|
|
339841
339914
|
return async () => {
|
|
339842
|
-
|
|
339915
|
+
log84.info("Shutting down agent dispatcher");
|
|
339843
339916
|
clearInterval(cleanupInterval2);
|
|
339844
339917
|
debouncer.clear();
|
|
339845
339918
|
const disposePromises = [];
|
|
339846
339919
|
for (const [key, provider] of providerCache.entries()) {
|
|
339847
339920
|
if (provider.dispose) {
|
|
339848
339921
|
disposePromises.push(provider.dispose().catch((err) => {
|
|
339849
|
-
|
|
339922
|
+
log84.warn("Error disposing provider", { key, error: String(err) });
|
|
339850
339923
|
}));
|
|
339851
339924
|
}
|
|
339852
339925
|
}
|
|
@@ -339856,7 +339929,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339856
339929
|
try {
|
|
339857
339930
|
client.stop();
|
|
339858
339931
|
} catch (err) {
|
|
339859
|
-
|
|
339932
|
+
log84.warn("Error stopping OpenClaw client", { providerId: id, error: String(err) });
|
|
339860
339933
|
}
|
|
339861
339934
|
}));
|
|
339862
339935
|
}
|
|
@@ -339864,7 +339937,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339864
339937
|
let timeoutId;
|
|
339865
339938
|
const timeoutGuard = new Promise((resolve3) => {
|
|
339866
339939
|
timeoutId = setTimeout(() => {
|
|
339867
|
-
|
|
339940
|
+
log84.warn("Dispatcher shutdown timed out after 5s, proceeding");
|
|
339868
339941
|
resolve3([]);
|
|
339869
339942
|
}, 5000);
|
|
339870
339943
|
});
|
|
@@ -339877,10 +339950,10 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
339877
339950
|
}
|
|
339878
339951
|
providerCache.clear();
|
|
339879
339952
|
openclawClientPool.clear();
|
|
339880
|
-
|
|
339953
|
+
log84.info("Agent dispatcher shutdown complete");
|
|
339881
339954
|
};
|
|
339882
339955
|
}
|
|
339883
|
-
var
|
|
339956
|
+
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;
|
|
339884
339957
|
var init_agent_dispatcher = __esm(() => {
|
|
339885
339958
|
init_src2();
|
|
339886
339959
|
init_src();
|
|
@@ -339891,9 +339964,10 @@ var init_agent_dispatcher = __esm(() => {
|
|
|
339891
339964
|
init_sentry_scrub();
|
|
339892
339965
|
init_agent_runner();
|
|
339893
339966
|
init_loader2();
|
|
339967
|
+
init_message_debouncer();
|
|
339894
339968
|
init_session_storage();
|
|
339895
339969
|
init_src6();
|
|
339896
|
-
|
|
339970
|
+
log84 = createLogger("agent-dispatcher");
|
|
339897
339971
|
CHANNEL_MESSAGE_LIMITS = {
|
|
339898
339972
|
discord: 2000,
|
|
339899
339973
|
"whatsapp-baileys": 65536,
|
|
@@ -339963,7 +340037,7 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
339963
340037
|
await eventBus.subscribe("sync.started", async (event) => {
|
|
339964
340038
|
const payload = event.payload;
|
|
339965
340039
|
const { jobId, instanceId, type, config: config4 } = payload;
|
|
339966
|
-
|
|
340040
|
+
log85.info("Processing sync job", { jobId, instanceId, type });
|
|
339967
340041
|
try {
|
|
339968
340042
|
await services.syncJobs.start(jobId);
|
|
339969
340043
|
const instance4 = await services.instances.getById(instanceId);
|
|
@@ -339990,12 +340064,12 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
339990
340064
|
case "history-push":
|
|
339991
340065
|
break;
|
|
339992
340066
|
default:
|
|
339993
|
-
|
|
340067
|
+
log85.warn("Unknown sync type", { jobId, type });
|
|
339994
340068
|
await services.syncJobs.fail(jobId, `Unknown sync type: ${type}`);
|
|
339995
340069
|
}
|
|
339996
340070
|
} catch (error2) {
|
|
339997
340071
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
339998
|
-
|
|
340072
|
+
log85.error("Sync job failed", { jobId, error: errorMessage });
|
|
339999
340073
|
await services.syncJobs.fail(jobId, errorMessage);
|
|
340000
340074
|
}
|
|
340001
340075
|
}, {
|
|
@@ -340003,15 +340077,15 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
340003
340077
|
queue: "sync-workers",
|
|
340004
340078
|
startFrom: "new"
|
|
340005
340079
|
});
|
|
340006
|
-
|
|
340080
|
+
log85.info("Sync worker initialized - listening for sync.started events");
|
|
340007
340081
|
} catch (error2) {
|
|
340008
|
-
|
|
340082
|
+
log85.error("Failed to set up sync worker", { error: String(error2) });
|
|
340009
340083
|
throw error2;
|
|
340010
340084
|
}
|
|
340011
340085
|
}
|
|
340012
340086
|
async function buildWhatsAppAnchors(instanceId, _services) {
|
|
340013
340087
|
if (!db2) {
|
|
340014
|
-
|
|
340088
|
+
log85.warn("Database not available for building anchors");
|
|
340015
340089
|
return [];
|
|
340016
340090
|
}
|
|
340017
340091
|
const result = await db2.execute(sql`
|
|
@@ -340047,20 +340121,20 @@ async function buildWhatsAppAnchors(instanceId, _services) {
|
|
|
340047
340121
|
});
|
|
340048
340122
|
}
|
|
340049
340123
|
}
|
|
340050
|
-
|
|
340124
|
+
log85.info("Built WhatsApp anchors", { instanceId, anchorCount: anchors.length });
|
|
340051
340125
|
return anchors;
|
|
340052
340126
|
}
|
|
340053
340127
|
function buildAnchorsForExplicitChatJids(jobId, chatJids, dbAnchors) {
|
|
340054
|
-
|
|
340128
|
+
log85.info("Using explicit chatJids for sync", { jobId, chatJids });
|
|
340055
340129
|
const anchors = [];
|
|
340056
340130
|
for (const jid of chatJids) {
|
|
340057
340131
|
const dbAnchor = dbAnchors.find((a3) => a3.chatJid === jid);
|
|
340058
340132
|
if (dbAnchor) {
|
|
340059
|
-
|
|
340133
|
+
log85.debug("Found DB anchor for chatJid", { jobId, chatJid: jid, anchorId: dbAnchor.messageKey.id });
|
|
340060
340134
|
anchors.push(dbAnchor);
|
|
340061
340135
|
continue;
|
|
340062
340136
|
}
|
|
340063
|
-
|
|
340137
|
+
log85.debug("No DB anchor for chatJid, will fetch recent", { jobId, chatJid: jid });
|
|
340064
340138
|
anchors.push({
|
|
340065
340139
|
chatJid: jid,
|
|
340066
340140
|
messageKey: { remoteJid: jid, id: "", fromMe: false },
|
|
@@ -340086,7 +340160,7 @@ async function discoverAnchorsFromPlugin(jobId, instanceId, plugin6, dbAnchors,
|
|
|
340086
340160
|
discovered.push({ chatJid: jid, messageKey: { remoteJid: jid, id: "", fromMe: false }, timestamp: Date.now() });
|
|
340087
340161
|
}
|
|
340088
340162
|
if (discovered.length > 0) {
|
|
340089
|
-
|
|
340163
|
+
log85.info("Discovered chats from DB + Baileys not in anchors", {
|
|
340090
340164
|
jobId,
|
|
340091
340165
|
discoveredCount: discovered.length,
|
|
340092
340166
|
fromDb: dbExternalIds.length,
|
|
@@ -340107,7 +340181,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340107
340181
|
throw new Error(`No plugin found for channel type: ${channelType}`);
|
|
340108
340182
|
}
|
|
340109
340183
|
if (!("fetchHistory" in plugin6) || typeof plugin6.fetchHistory !== "function") {
|
|
340110
|
-
|
|
340184
|
+
log85.warn("Plugin does not support fetchHistory", { channelType });
|
|
340111
340185
|
await services.syncJobs.complete(jobId);
|
|
340112
340186
|
return;
|
|
340113
340187
|
}
|
|
@@ -340116,7 +340190,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340116
340190
|
let fetched = 0;
|
|
340117
340191
|
let stored = 0;
|
|
340118
340192
|
let duplicates = 0;
|
|
340119
|
-
|
|
340193
|
+
log85.info("Starting message sync", {
|
|
340120
340194
|
jobId,
|
|
340121
340195
|
instanceId,
|
|
340122
340196
|
channelType,
|
|
@@ -340126,13 +340200,13 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340126
340200
|
if (channelType === "whatsapp-baileys" && config4.chatJids?.length) {
|
|
340127
340201
|
const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
|
|
340128
340202
|
anchors = await resolveWhatsAppAnchors(jobId, instanceId, config4, plugin6, dbAnchors, services);
|
|
340129
|
-
|
|
340203
|
+
log85.info("WhatsApp per-chat active sync", { jobId, anchorCount: anchors.length, chatJids: config4.chatJids });
|
|
340130
340204
|
} else if (channelType === "whatsapp-baileys") {
|
|
340131
340205
|
const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
|
|
340132
340206
|
const discoveredAnchors = await discoverAnchorsFromPlugin(jobId, instanceId, plugin6, dbAnchors, services);
|
|
340133
340207
|
anchors = [...dbAnchors, ...discoveredAnchors];
|
|
340134
340208
|
if (anchors.length > 0) {
|
|
340135
|
-
|
|
340209
|
+
log85.info("WhatsApp default sync with DB+cache discovery", {
|
|
340136
340210
|
jobId,
|
|
340137
340211
|
instanceId,
|
|
340138
340212
|
dbAnchorCount: dbAnchors.length,
|
|
@@ -340140,7 +340214,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340140
340214
|
totalAnchors: anchors.length
|
|
340141
340215
|
});
|
|
340142
340216
|
} else {
|
|
340143
|
-
|
|
340217
|
+
log85.info("WhatsApp passive sync (no prior data)", { jobId, instanceId });
|
|
340144
340218
|
}
|
|
340145
340219
|
}
|
|
340146
340220
|
const fetchOptions = {
|
|
@@ -340182,7 +340256,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340182
340256
|
});
|
|
340183
340257
|
stored++;
|
|
340184
340258
|
} catch (error2) {
|
|
340185
|
-
|
|
340259
|
+
log85.warn("Failed to store synced message", {
|
|
340186
340260
|
externalId: msg.externalId,
|
|
340187
340261
|
error: String(error2)
|
|
340188
340262
|
});
|
|
@@ -340199,7 +340273,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
340199
340273
|
duplicates
|
|
340200
340274
|
});
|
|
340201
340275
|
await services.syncJobs.complete(jobId);
|
|
340202
|
-
|
|
340276
|
+
log85.info("Message sync completed", {
|
|
340203
340277
|
jobId,
|
|
340204
340278
|
fetched,
|
|
340205
340279
|
stored,
|
|
@@ -340246,14 +340320,14 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
340246
340320
|
throw new Error(`No plugin found for channel type: ${channelType}`);
|
|
340247
340321
|
}
|
|
340248
340322
|
if (!("fetchContacts" in plugin6) || typeof plugin6.fetchContacts !== "function") {
|
|
340249
|
-
|
|
340323
|
+
log85.warn("Plugin does not support fetchContacts", { channelType });
|
|
340250
340324
|
await services.syncJobs.complete(jobId);
|
|
340251
340325
|
return;
|
|
340252
340326
|
}
|
|
340253
340327
|
let fetched = 0;
|
|
340254
340328
|
let stored = 0;
|
|
340255
340329
|
let linked = 0;
|
|
340256
|
-
|
|
340330
|
+
log85.info("Starting contacts sync", {
|
|
340257
340331
|
jobId,
|
|
340258
340332
|
instanceId,
|
|
340259
340333
|
channelType
|
|
@@ -340292,7 +340366,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
340292
340366
|
await updateDmChatName(services, instanceId, c.platformUserId, c.name);
|
|
340293
340367
|
}
|
|
340294
340368
|
} catch (error2) {
|
|
340295
|
-
|
|
340369
|
+
log85.warn("Failed to store synced contact", {
|
|
340296
340370
|
platformUserId: c.platformUserId,
|
|
340297
340371
|
error: String(error2)
|
|
340298
340372
|
});
|
|
@@ -340309,7 +340383,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
340309
340383
|
duplicates: 0
|
|
340310
340384
|
});
|
|
340311
340385
|
await services.syncJobs.complete(jobId);
|
|
340312
|
-
|
|
340386
|
+
log85.info("Contacts sync completed", {
|
|
340313
340387
|
jobId,
|
|
340314
340388
|
fetched,
|
|
340315
340389
|
stored,
|
|
@@ -340323,7 +340397,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
340323
340397
|
}
|
|
340324
340398
|
const fetchMethod = channelType === "discord" ? "fetchGuilds" : "fetchGroups";
|
|
340325
340399
|
if (!(fetchMethod in plugin6) || typeof plugin6[fetchMethod] !== "function") {
|
|
340326
|
-
|
|
340400
|
+
log85.warn(`Plugin does not support ${fetchMethod}`, { channelType });
|
|
340327
340401
|
await services.syncJobs.complete(jobId);
|
|
340328
340402
|
return;
|
|
340329
340403
|
}
|
|
@@ -340334,7 +340408,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
340334
340408
|
let fetched = 0;
|
|
340335
340409
|
let stored = 0;
|
|
340336
340410
|
let updated = 0;
|
|
340337
|
-
|
|
340411
|
+
log85.info("Starting groups sync", {
|
|
340338
340412
|
jobId,
|
|
340339
340413
|
instanceId,
|
|
340340
340414
|
channelType
|
|
@@ -340384,7 +340458,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
340384
340458
|
stored++;
|
|
340385
340459
|
}
|
|
340386
340460
|
} catch (error2) {
|
|
340387
|
-
|
|
340461
|
+
log85.warn("Failed to store synced group", {
|
|
340388
340462
|
externalId: g2.externalId,
|
|
340389
340463
|
error: String(error2)
|
|
340390
340464
|
});
|
|
@@ -340425,7 +340499,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
340425
340499
|
stored++;
|
|
340426
340500
|
}
|
|
340427
340501
|
} catch (error2) {
|
|
340428
|
-
|
|
340502
|
+
log85.warn("Failed to store synced guild", {
|
|
340429
340503
|
externalId: g2.externalId,
|
|
340430
340504
|
error: String(error2)
|
|
340431
340505
|
});
|
|
@@ -340440,7 +340514,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
340440
340514
|
duplicates: updated
|
|
340441
340515
|
});
|
|
340442
340516
|
await services.syncJobs.complete(jobId);
|
|
340443
|
-
|
|
340517
|
+
log85.info("Groups sync completed", {
|
|
340444
340518
|
jobId,
|
|
340445
340519
|
fetched,
|
|
340446
340520
|
stored,
|
|
@@ -340550,12 +340624,12 @@ async function setupHistoryPushTracker(eventBus, services) {
|
|
|
340550
340624
|
throw error2;
|
|
340551
340625
|
}
|
|
340552
340626
|
}
|
|
340553
|
-
var
|
|
340627
|
+
var log85, RATE_LIMITS2, db2 = null, historyPushLog;
|
|
340554
340628
|
var init_sync_worker = __esm(() => {
|
|
340555
340629
|
init_src();
|
|
340556
340630
|
init_src4();
|
|
340557
340631
|
init_drizzle_orm();
|
|
340558
|
-
|
|
340632
|
+
log85 = createLogger("sync-worker");
|
|
340559
340633
|
RATE_LIMITS2 = {
|
|
340560
340634
|
"whatsapp-baileys": 30,
|
|
340561
340635
|
discord: 50,
|
|
@@ -340619,15 +340693,15 @@ async function handleTrashEmojiMessage(services, db3, event) {
|
|
|
340619
340693
|
return;
|
|
340620
340694
|
if (!isTrashEmojiOnly2(content.text))
|
|
340621
340695
|
return;
|
|
340622
|
-
|
|
340696
|
+
log86.info("Trash emoji detected, clearing session", { instanceId, chatId, from });
|
|
340623
340697
|
try {
|
|
340624
340698
|
const { sessionId, sessionStrategy } = await clearAgentSession(services, db3, instanceId, from, chatId);
|
|
340625
|
-
|
|
340699
|
+
log86.info("Session cleared successfully", { instanceId, sessionId, sessionStrategy });
|
|
340626
340700
|
try {
|
|
340627
340701
|
await sendMessage(services, instanceId, chatId, "\u2705 Conversa limpa! Sua sess\xE3o com o assistente foi resetada.");
|
|
340628
|
-
|
|
340702
|
+
log86.info("Sent session cleared confirmation", { instanceId, chatId });
|
|
340629
340703
|
} catch (sendError) {
|
|
340630
|
-
|
|
340704
|
+
log86.error("Failed to send confirmation message", { instanceId, chatId, error: String(sendError) });
|
|
340631
340705
|
}
|
|
340632
340706
|
} catch (error2) {
|
|
340633
340707
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -340638,14 +340712,14 @@ async function handleTrashEmojiMessage(services, db3, event) {
|
|
|
340638
340712
|
"Session clearing not supported for"
|
|
340639
340713
|
];
|
|
340640
340714
|
if (skippableErrors.some((e) => errorMessage.includes(e))) {
|
|
340641
|
-
|
|
340715
|
+
log86.debug("Session clearing skipped", { instanceId, reason: errorMessage });
|
|
340642
340716
|
return;
|
|
340643
340717
|
}
|
|
340644
|
-
|
|
340718
|
+
log86.error("Failed to clear session", { instanceId, chatId, error: errorMessage });
|
|
340645
340719
|
try {
|
|
340646
340720
|
await sendMessage(services, instanceId, chatId, "\u274C Erro ao limpar sess\xE3o. Tente novamente.");
|
|
340647
340721
|
} catch (sendError) {
|
|
340648
|
-
|
|
340722
|
+
log86.error("Failed to send error message", { instanceId, chatId, error: String(sendError) });
|
|
340649
340723
|
}
|
|
340650
340724
|
}
|
|
340651
340725
|
}
|
|
@@ -340659,13 +340733,13 @@ async function setupSessionCleaner(eventBus, services, db3) {
|
|
|
340659
340733
|
startFrom: "last",
|
|
340660
340734
|
concurrency: 5
|
|
340661
340735
|
});
|
|
340662
|
-
|
|
340736
|
+
log86.info("Session cleaner initialized");
|
|
340663
340737
|
} catch (error2) {
|
|
340664
|
-
|
|
340738
|
+
log86.error("Failed to set up session cleaner", { error: String(error2) });
|
|
340665
340739
|
throw error2;
|
|
340666
340740
|
}
|
|
340667
340741
|
}
|
|
340668
|
-
var
|
|
340742
|
+
var log86;
|
|
340669
340743
|
var init_session_cleaner = __esm(() => {
|
|
340670
340744
|
init_src();
|
|
340671
340745
|
init_src4();
|
|
@@ -340673,7 +340747,7 @@ var init_session_cleaner = __esm(() => {
|
|
|
340673
340747
|
init_agent_runner();
|
|
340674
340748
|
init_agent_dispatcher();
|
|
340675
340749
|
init_loader2();
|
|
340676
|
-
|
|
340750
|
+
log86 = createLogger("session-cleaner");
|
|
340677
340751
|
});
|
|
340678
340752
|
|
|
340679
340753
|
// ../api/src/plugins/instance-monitor.ts
|
|
@@ -341211,14 +341285,14 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
|
|
|
341211
341285
|
return "ok";
|
|
341212
341286
|
const parsed = parseMetadata(msg.text);
|
|
341213
341287
|
if (!parsed.instance || !parsed.chat || !parsed.channel) {
|
|
341214
|
-
|
|
341288
|
+
log87.debug("Skipping message \u2014 missing routing metadata", { team, inboxName, from: msg.from });
|
|
341215
341289
|
return "ok";
|
|
341216
341290
|
}
|
|
341217
341291
|
if (!parsed.cleanText)
|
|
341218
341292
|
return "ok";
|
|
341219
341293
|
const plugin6 = channelRegistry2.get(parsed.channel);
|
|
341220
341294
|
if (!plugin6) {
|
|
341221
|
-
|
|
341295
|
+
log87.warn("Channel plugin not found", { channel: parsed.channel, team, inboxName });
|
|
341222
341296
|
return "ok";
|
|
341223
341297
|
}
|
|
341224
341298
|
const outgoing = {
|
|
@@ -341230,7 +341304,7 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
|
|
|
341230
341304
|
try {
|
|
341231
341305
|
const result = await plugin6.sendMessage(parsed.instance, outgoing);
|
|
341232
341306
|
if (result.success) {
|
|
341233
|
-
|
|
341307
|
+
log87.info("Forwarded reply", {
|
|
341234
341308
|
team,
|
|
341235
341309
|
inboxName,
|
|
341236
341310
|
channel: parsed.channel,
|
|
@@ -341240,11 +341314,11 @@ async function sendInboxMessage(msg, inboxName, team, channelRegistry2, patterns
|
|
|
341240
341314
|
messageId: result.messageId
|
|
341241
341315
|
});
|
|
341242
341316
|
} else {
|
|
341243
|
-
|
|
341317
|
+
log87.error("sendMessage failed", { team, inboxName, channel: parsed.channel, error: result.error });
|
|
341244
341318
|
}
|
|
341245
341319
|
return "ok";
|
|
341246
341320
|
} catch (err) {
|
|
341247
|
-
|
|
341321
|
+
log87.error("sendMessage threw", { team, inboxName, error: String(err) });
|
|
341248
341322
|
return "retry";
|
|
341249
341323
|
}
|
|
341250
341324
|
}
|
|
@@ -341268,7 +341342,7 @@ async function processInbox(inboxName, team, state, channelRegistry2, patterns)
|
|
|
341268
341342
|
const entry = state.cursors[cursorKey] ?? { lastIndex: 0 };
|
|
341269
341343
|
let { lastIndex } = entry;
|
|
341270
341344
|
if (lastIndex > inbox.length) {
|
|
341271
|
-
|
|
341345
|
+
log87.warn("Inbox shrank (truncated/rotated), resetting cursor", {
|
|
341272
341346
|
team,
|
|
341273
341347
|
inboxName,
|
|
341274
341348
|
oldCursor: lastIndex,
|
|
@@ -341321,20 +341395,20 @@ async function setupInboxBridge(services, channelRegistry2) {
|
|
|
341321
341395
|
let patterns = [];
|
|
341322
341396
|
try {
|
|
341323
341397
|
patterns = await discoverAgentPatterns(services);
|
|
341324
|
-
|
|
341398
|
+
log87.info("Inbox bridge started", {
|
|
341325
341399
|
patterns: patterns.map((p2) => ({ raw: p2.raw, isTemplate: p2.isTemplate, prefix: p2.prefix }))
|
|
341326
341400
|
});
|
|
341327
341401
|
} catch (err) {
|
|
341328
|
-
|
|
341402
|
+
log87.warn("Initial agent discovery failed", { error: String(err) });
|
|
341329
341403
|
}
|
|
341330
341404
|
const discoveryTimer = setInterval(async () => {
|
|
341331
341405
|
try {
|
|
341332
341406
|
patterns = await discoverAgentPatterns(services);
|
|
341333
|
-
|
|
341407
|
+
log87.debug("Agent patterns refreshed", {
|
|
341334
341408
|
patterns: patterns.map((p2) => ({ raw: p2.raw, isTemplate: p2.isTemplate, prefix: p2.prefix }))
|
|
341335
341409
|
});
|
|
341336
341410
|
} catch (err) {
|
|
341337
|
-
|
|
341411
|
+
log87.warn("Agent discovery refresh failed", { error: String(err) });
|
|
341338
341412
|
}
|
|
341339
341413
|
}, DISCOVERY_INTERVAL_MS);
|
|
341340
341414
|
discoveryTimer.unref();
|
|
@@ -341346,7 +341420,7 @@ async function setupInboxBridge(services, channelRegistry2) {
|
|
|
341346
341420
|
try {
|
|
341347
341421
|
await pollInboxes(patterns, channelRegistry2);
|
|
341348
341422
|
} catch (err) {
|
|
341349
|
-
|
|
341423
|
+
log87.error("Poll cycle error", { error: String(err) });
|
|
341350
341424
|
} finally {
|
|
341351
341425
|
polling = false;
|
|
341352
341426
|
}
|
|
@@ -341355,13 +341429,13 @@ async function setupInboxBridge(services, channelRegistry2) {
|
|
|
341355
341429
|
return async () => {
|
|
341356
341430
|
clearInterval(discoveryTimer);
|
|
341357
341431
|
clearInterval(pollTimer);
|
|
341358
|
-
|
|
341432
|
+
log87.info("Inbox bridge stopped");
|
|
341359
341433
|
};
|
|
341360
341434
|
}
|
|
341361
|
-
var
|
|
341435
|
+
var log87, CLAUDE_TEAMS_DIR, BRIDGE_STATE_PATH, POLL_INTERVAL_MS2 = 2000, DISCOVERY_INTERVAL_MS = 60000, CURSOR_TTL_MS;
|
|
341362
341436
|
var init_inbox_bridge = __esm(() => {
|
|
341363
341437
|
init_src();
|
|
341364
|
-
|
|
341438
|
+
log87 = createLogger("inbox-bridge");
|
|
341365
341439
|
CLAUDE_TEAMS_DIR = join25(homedir3(), ".claude", "teams");
|
|
341366
341440
|
BRIDGE_STATE_PATH = join25(homedir3(), ".claude", "bridge", "state.json");
|
|
341367
341441
|
CURSOR_TTL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -341394,7 +341468,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341394
341468
|
recordScheduledJob("dead-letter-auto-retry", "success", durationSec);
|
|
341395
341469
|
const pendingCount = await services.deadLetters.getPendingCount();
|
|
341396
341470
|
deadLettersPending.set(pendingCount);
|
|
341397
|
-
|
|
341471
|
+
log88.info("Dead letter auto-retry completed", result);
|
|
341398
341472
|
} catch (err) {
|
|
341399
341473
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341400
341474
|
recordScheduledJob("dead-letter-auto-retry", "failure", durationSec);
|
|
@@ -341416,7 +341490,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341416
341490
|
recordScheduledJob("payload-cleanup", "success", durationSec);
|
|
341417
341491
|
const stats = await services.payloadStore.getStats();
|
|
341418
341492
|
payloadStorageSize.set(stats.totalSizeCompressed);
|
|
341419
|
-
|
|
341493
|
+
log88.info("Payload cleanup completed", { deleted });
|
|
341420
341494
|
} catch (err) {
|
|
341421
341495
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341422
341496
|
recordScheduledJob("payload-cleanup", "failure", durationSec);
|
|
@@ -341436,7 +341510,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341436
341510
|
const deleted = await services.deadLetters.cleanupExpired();
|
|
341437
341511
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341438
341512
|
recordScheduledJob("dead-letter-cleanup", "success", durationSec);
|
|
341439
|
-
|
|
341513
|
+
log88.info("Dead letter cleanup completed", { deleted });
|
|
341440
341514
|
} catch (err) {
|
|
341441
341515
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341442
341516
|
recordScheduledJob("dead-letter-cleanup", "failure", durationSec);
|
|
@@ -341465,7 +341539,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341465
341539
|
});
|
|
341466
341540
|
jobsCreated++;
|
|
341467
341541
|
} catch (err) {
|
|
341468
|
-
|
|
341542
|
+
log88.warn("Failed to create contacts sync job for instance", {
|
|
341469
341543
|
instanceId: instance4.id,
|
|
341470
341544
|
error: String(err)
|
|
341471
341545
|
});
|
|
@@ -341473,7 +341547,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341473
341547
|
}
|
|
341474
341548
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341475
341549
|
recordScheduledJob("contacts-sync-daily", "success", durationSec);
|
|
341476
|
-
|
|
341550
|
+
log88.info("Daily contacts sync jobs created", { jobsCreated, instanceCount: instances2.length });
|
|
341477
341551
|
} catch (err) {
|
|
341478
341552
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341479
341553
|
recordScheduledJob("contacts-sync-daily", "failure", durationSec);
|
|
@@ -341502,7 +341576,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341502
341576
|
});
|
|
341503
341577
|
jobsCreated++;
|
|
341504
341578
|
} catch (err) {
|
|
341505
|
-
|
|
341579
|
+
log88.warn("Failed to create groups sync job for instance", {
|
|
341506
341580
|
instanceId: instance4.id,
|
|
341507
341581
|
error: String(err)
|
|
341508
341582
|
});
|
|
@@ -341510,7 +341584,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341510
341584
|
}
|
|
341511
341585
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341512
341586
|
recordScheduledJob("groups-sync-daily", "success", durationSec);
|
|
341513
|
-
|
|
341587
|
+
log88.info("Daily groups sync jobs created", { jobsCreated, instanceCount: instances2.length });
|
|
341514
341588
|
} catch (err) {
|
|
341515
341589
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341516
341590
|
recordScheduledJob("groups-sync-daily", "failure", durationSec);
|
|
@@ -341539,7 +341613,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341539
341613
|
}
|
|
341540
341614
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341541
341615
|
recordScheduledJob("unread-count-refresh", "success", durationSec);
|
|
341542
|
-
|
|
341616
|
+
log88.debug("Refreshed unread counts", { instanceCount: waInstances.length });
|
|
341543
341617
|
} catch (err) {
|
|
341544
341618
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
341545
341619
|
recordScheduledJob("unread-count-refresh", "failure", durationSec);
|
|
@@ -341550,7 +341624,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
341550
341624
|
});
|
|
341551
341625
|
updateSchedulerMetrics();
|
|
341552
341626
|
scheduler.start();
|
|
341553
|
-
|
|
341627
|
+
log88.info("Scheduler started", {
|
|
341554
341628
|
jobs: scheduler.listJobs().map((j) => ({
|
|
341555
341629
|
name: j.name,
|
|
341556
341630
|
cron: j.cron,
|
|
@@ -341570,14 +341644,14 @@ function updateSchedulerMetrics() {
|
|
|
341570
341644
|
function stopScheduler() {
|
|
341571
341645
|
const scheduler = getScheduler();
|
|
341572
341646
|
scheduler.stop();
|
|
341573
|
-
|
|
341647
|
+
log88.info("Scheduler stopped");
|
|
341574
341648
|
}
|
|
341575
|
-
var
|
|
341649
|
+
var log88;
|
|
341576
341650
|
var init_scheduler2 = __esm(() => {
|
|
341577
341651
|
init_src();
|
|
341578
341652
|
init_esm5();
|
|
341579
341653
|
init_sentry_scrub();
|
|
341580
|
-
|
|
341654
|
+
log88 = createLogger("scheduler:setup");
|
|
341581
341655
|
});
|
|
341582
341656
|
|
|
341583
341657
|
// ../api/src/utils/startup-banner.ts
|
|
@@ -341651,12 +341725,12 @@ function printStartupBanner(options) {
|
|
|
341651
341725
|
process.stdout.write(`${line3}
|
|
341652
341726
|
`);
|
|
341653
341727
|
}
|
|
341654
|
-
|
|
341728
|
+
log89.info("Server ready", { host, port, version: version4 });
|
|
341655
341729
|
}
|
|
341656
|
-
var
|
|
341730
|
+
var log89, COLORS3, BOX, ANSI_ESCAPE_PATTERN;
|
|
341657
341731
|
var init_startup_banner = __esm(() => {
|
|
341658
341732
|
init_src();
|
|
341659
|
-
|
|
341733
|
+
log89 = createLogger("api:startup");
|
|
341660
341734
|
COLORS3 = {
|
|
341661
341735
|
reset: "\x1B[0m",
|
|
341662
341736
|
dim: "\x1B[2m",
|
|
@@ -341816,84 +341890,84 @@ function setupShutdownHandlers(server, earlyShutdown) {
|
|
|
341816
341890
|
}
|
|
341817
341891
|
async function setupEventBusServices(eventBus, services, db3) {
|
|
341818
341892
|
if (!eventBus) {
|
|
341819
|
-
|
|
341893
|
+
log90.warn("Skipping event bus services (no event bus)");
|
|
341820
341894
|
return;
|
|
341821
341895
|
}
|
|
341822
341896
|
try {
|
|
341823
341897
|
await setupMessagePersistence(eventBus, services);
|
|
341824
341898
|
} catch (error2) {
|
|
341825
|
-
|
|
341899
|
+
log90.error("Failed to set up message persistence", { error: String(error2) });
|
|
341826
341900
|
}
|
|
341827
341901
|
try {
|
|
341828
341902
|
await setupMediaProcessor(eventBus, db3, services);
|
|
341829
341903
|
} catch (error2) {
|
|
341830
|
-
|
|
341904
|
+
log90.error("Failed to set up media processor", { error: String(error2) });
|
|
341831
341905
|
}
|
|
341832
341906
|
try {
|
|
341833
341907
|
globalDispatcherCleanup = await setupAgentResponder(eventBus, services, db3);
|
|
341834
341908
|
} catch (error2) {
|
|
341835
|
-
|
|
341909
|
+
log90.error("Failed to set up agent dispatcher", { error: String(error2) });
|
|
341836
341910
|
}
|
|
341837
341911
|
if (globalChannelRegistry) {
|
|
341838
341912
|
try {
|
|
341839
341913
|
globalInboxBridgeCleanup = await setupInboxBridge(services, globalChannelRegistry);
|
|
341840
341914
|
} catch (error2) {
|
|
341841
|
-
|
|
341915
|
+
log90.error("Failed to set up inbox bridge", { error: String(error2) });
|
|
341842
341916
|
}
|
|
341843
341917
|
}
|
|
341844
341918
|
try {
|
|
341845
341919
|
await services.automations.startEngine({});
|
|
341846
341920
|
} catch (error2) {
|
|
341847
|
-
|
|
341921
|
+
log90.error("Failed to start automation engine", { error: String(error2) });
|
|
341848
341922
|
}
|
|
341849
341923
|
try {
|
|
341850
341924
|
await setupSessionCleaner(eventBus, services, db3);
|
|
341851
341925
|
} catch (error2) {
|
|
341852
|
-
|
|
341926
|
+
log90.error("Failed to set up session cleaner", { error: String(error2) });
|
|
341853
341927
|
}
|
|
341854
341928
|
if (globalChannelRegistry) {
|
|
341855
341929
|
try {
|
|
341856
341930
|
await setupSyncWorker(eventBus, services, globalChannelRegistry, db3);
|
|
341857
341931
|
} catch (error2) {
|
|
341858
|
-
|
|
341932
|
+
log90.error("Failed to set up sync worker", { error: String(error2) });
|
|
341859
341933
|
}
|
|
341860
341934
|
}
|
|
341861
341935
|
try {
|
|
341862
341936
|
await setupHistoryPushTracker(eventBus, services);
|
|
341863
341937
|
} catch (error2) {
|
|
341864
|
-
|
|
341938
|
+
log90.error("Failed to set up history-push tracker", { error: String(error2) });
|
|
341865
341939
|
}
|
|
341866
341940
|
}
|
|
341867
341941
|
async function waitForDatabaseReady(db3, maxAttempts = 30) {
|
|
341868
|
-
|
|
341942
|
+
log90.info("Waiting for database readiness");
|
|
341869
341943
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
341870
341944
|
try {
|
|
341871
341945
|
await db3.execute(sql`SELECT 1`);
|
|
341872
|
-
|
|
341946
|
+
log90.info("Database ready", { attempt });
|
|
341873
341947
|
return;
|
|
341874
341948
|
} catch {
|
|
341875
341949
|
if (attempt === maxAttempts) {
|
|
341876
341950
|
throw new Error(`Database not ready after ${maxAttempts} attempts`);
|
|
341877
341951
|
}
|
|
341878
|
-
|
|
341952
|
+
log90.warn("Database not ready, retrying...", { attempt });
|
|
341879
341953
|
await new Promise((resolve3) => setTimeout(resolve3, 1000));
|
|
341880
341954
|
}
|
|
341881
341955
|
}
|
|
341882
341956
|
}
|
|
341883
341957
|
async function main() {
|
|
341884
|
-
|
|
341958
|
+
log90.info("Starting Omni API v2");
|
|
341885
341959
|
enableDefaultMetrics();
|
|
341886
341960
|
const pgserveConfig = resolvePgserveConfig();
|
|
341887
341961
|
const databaseUrl = await startEmbeddedPgserve(pgserveConfig);
|
|
341888
|
-
|
|
341962
|
+
log90.info("Connecting to database");
|
|
341889
341963
|
const db3 = createDb({ url: databaseUrl });
|
|
341890
341964
|
const earlyShutdown = async () => {
|
|
341891
|
-
|
|
341965
|
+
log90.info("Shutdown during startup \u2014 cleaning up");
|
|
341892
341966
|
try {
|
|
341893
341967
|
await closeDb();
|
|
341894
341968
|
await stopEmbeddedPgserve();
|
|
341895
341969
|
} catch (err) {
|
|
341896
|
-
|
|
341970
|
+
log90.error("Cleanup failed during early shutdown", { error: String(err) });
|
|
341897
341971
|
} finally {
|
|
341898
341972
|
process.exit(1);
|
|
341899
341973
|
}
|
|
@@ -341907,7 +341981,7 @@ async function main() {
|
|
|
341907
341981
|
await stopEmbeddedPgserve();
|
|
341908
341982
|
throw error2;
|
|
341909
341983
|
}
|
|
341910
|
-
|
|
341984
|
+
log90.info("Running database migrations");
|
|
341911
341985
|
const migrationStart = Date.now();
|
|
341912
341986
|
const MIGRATION_TIMEOUT_MS = 60000;
|
|
341913
341987
|
try {
|
|
@@ -341920,7 +341994,7 @@ async function main() {
|
|
|
341920
341994
|
await stopEmbeddedPgserve();
|
|
341921
341995
|
throw error2;
|
|
341922
341996
|
}
|
|
341923
|
-
|
|
341997
|
+
log90.info("Database migrations complete", { durationMs: Date.now() - migrationStart });
|
|
341924
341998
|
const eventBus = await connectToNats(db3);
|
|
341925
341999
|
if (eventBus) {
|
|
341926
342000
|
try {
|
|
@@ -341935,9 +342009,9 @@ async function main() {
|
|
|
341935
342009
|
try {
|
|
341936
342010
|
await services.settings.seedDefaults();
|
|
341937
342011
|
} catch (error2) {
|
|
341938
|
-
|
|
342012
|
+
log90.error("Failed to seed default settings", { error: String(error2) });
|
|
341939
342013
|
}
|
|
341940
|
-
|
|
342014
|
+
log90.info("Initializing API key");
|
|
341941
342015
|
let apiKeyInfo;
|
|
341942
342016
|
try {
|
|
341943
342017
|
const keyResult = await services.apiKeys.initializePrimaryKey();
|
|
@@ -341947,21 +342021,21 @@ async function main() {
|
|
|
341947
342021
|
isFromEnv: keyResult.isFromEnv
|
|
341948
342022
|
};
|
|
341949
342023
|
if (keyResult.isNew) {
|
|
341950
|
-
|
|
342024
|
+
log90.info("Generated new primary API key");
|
|
341951
342025
|
} else if (keyResult.isFromEnv) {
|
|
341952
|
-
|
|
342026
|
+
log90.info("Using primary API key from environment");
|
|
341953
342027
|
} else {
|
|
341954
|
-
|
|
342028
|
+
log90.info("Using existing primary API key");
|
|
341955
342029
|
}
|
|
341956
342030
|
} catch (error2) {
|
|
341957
|
-
|
|
342031
|
+
log90.error("Failed to initialize primary API key", { error: String(error2) });
|
|
341958
342032
|
}
|
|
341959
342033
|
await setupEventBusServices(eventBus, services, db3);
|
|
341960
|
-
|
|
342034
|
+
log90.info("Starting scheduler");
|
|
341961
342035
|
setupScheduler(services, globalChannelRegistry);
|
|
341962
342036
|
const server = startBunServer(app);
|
|
341963
342037
|
printStartupBanner({
|
|
341964
|
-
version:
|
|
342038
|
+
version: import__package3.default.version,
|
|
341965
342039
|
host: HOST,
|
|
341966
342040
|
port: PORT,
|
|
341967
342041
|
docsPath: "/api/v2/docs",
|
|
@@ -341971,7 +342045,7 @@ async function main() {
|
|
|
341971
342045
|
});
|
|
341972
342046
|
setupShutdownHandlers(server, earlyShutdown);
|
|
341973
342047
|
}
|
|
341974
|
-
var
|
|
342048
|
+
var import__package3, log90, natsLog, pluginLog, shutdownLog, PORT, HOST, NATS_URL, globalEventBus = null, globalChannelRegistry = null, globalInstanceMonitor = null, globalDispatcherCleanup = null, globalInboxBridgeCleanup = null;
|
|
341975
342049
|
var init_src7 = __esm(() => {
|
|
341976
342050
|
init_instrument2();
|
|
341977
342051
|
init_src();
|
|
@@ -341986,12 +342060,12 @@ var init_src7 = __esm(() => {
|
|
|
341986
342060
|
init_startup_banner();
|
|
341987
342061
|
init_app();
|
|
341988
342062
|
init_services();
|
|
341989
|
-
|
|
342063
|
+
import__package3 = __toESM(require_package8(), 1);
|
|
341990
342064
|
configureLogging({
|
|
341991
342065
|
level: process.env.LOG_LEVEL ?? "info",
|
|
341992
342066
|
format: process.env.LOG_FORMAT ?? "auto"
|
|
341993
342067
|
});
|
|
341994
|
-
|
|
342068
|
+
log90 = createLogger("api:startup");
|
|
341995
342069
|
natsLog = createLogger("api:nats");
|
|
341996
342070
|
pluginLog = createLogger("api:plugins");
|
|
341997
342071
|
shutdownLog = createLogger("api:shutdown");
|
|
@@ -341999,7 +342073,7 @@ var init_src7 = __esm(() => {
|
|
|
341999
342073
|
HOST = process.env.API_HOST ?? "0.0.0.0";
|
|
342000
342074
|
NATS_URL = process.env.NATS_URL ?? "nats://localhost:4222";
|
|
342001
342075
|
main().catch((error2) => {
|
|
342002
|
-
|
|
342076
|
+
log90.error("Failed to start API server", { error: String(error2) });
|
|
342003
342077
|
process.exit(1);
|
|
342004
342078
|
});
|
|
342005
342079
|
});
|
|
@@ -458917,6 +458991,9 @@ function fromJid(jid) {
|
|
|
458917
458991
|
const id = jid.split("@")[0] || "";
|
|
458918
458992
|
return { id, isGroup, isUser, isBroadcast, isLid };
|
|
458919
458993
|
}
|
|
458994
|
+
function isGroupJid(jid) {
|
|
458995
|
+
return jid.endsWith(JID_SUFFIX.GROUP);
|
|
458996
|
+
}
|
|
458920
458997
|
function isUserJid(jid) {
|
|
458921
458998
|
return jid.endsWith(JID_SUFFIX.USER);
|
|
458922
458999
|
}
|
|
@@ -460296,7 +460373,6 @@ async function removeReaction4(sock, jid, targetMessageId, fromMe = true) {
|
|
|
460296
460373
|
|
|
460297
460374
|
// ../channel-whatsapp/src/senders/stream.ts
|
|
460298
460375
|
init_src();
|
|
460299
|
-
|
|
460300
460376
|
// ../channel-whatsapp/src/utils/split-message.ts
|
|
460301
460377
|
var DEFAULT_MAX_LENGTH2 = 65536;
|
|
460302
460378
|
function splitByDelimiter(text, delimiter) {
|
|
@@ -460666,14 +460742,16 @@ class WhatsAppStreamSender {
|
|
|
460666
460742
|
this.messageId = result?.key?.id ?? null;
|
|
460667
460743
|
this.firstMessageSent = true;
|
|
460668
460744
|
} else {
|
|
460669
|
-
|
|
460670
|
-
|
|
460671
|
-
|
|
460672
|
-
|
|
460673
|
-
|
|
460674
|
-
|
|
460675
|
-
|
|
460676
|
-
|
|
460745
|
+
const sock = this.getSock();
|
|
460746
|
+
const editKey = {
|
|
460747
|
+
remoteJid: this.jid,
|
|
460748
|
+
id: this.messageId,
|
|
460749
|
+
fromMe: true
|
|
460750
|
+
};
|
|
460751
|
+
if (isGroupJid(this.jid)) {
|
|
460752
|
+
editKey.participant = sock.user?.id;
|
|
460753
|
+
}
|
|
460754
|
+
await sock.sendMessage(this.jid, { text, edit: editKey });
|
|
460677
460755
|
}
|
|
460678
460756
|
this.lastRenderedText = text;
|
|
460679
460757
|
this.lastEditAt = Date.now();
|
|
@@ -460689,14 +460767,16 @@ class WhatsAppStreamSender {
|
|
|
460689
460767
|
async doEditRaw(text) {
|
|
460690
460768
|
if (!this.messageId)
|
|
460691
460769
|
throw new Error("No message to edit");
|
|
460692
|
-
|
|
460693
|
-
|
|
460694
|
-
|
|
460695
|
-
|
|
460696
|
-
|
|
460697
|
-
|
|
460698
|
-
|
|
460699
|
-
|
|
460770
|
+
const sock = this.getSock();
|
|
460771
|
+
const editKey = {
|
|
460772
|
+
remoteJid: this.jid,
|
|
460773
|
+
id: this.messageId,
|
|
460774
|
+
fromMe: true
|
|
460775
|
+
};
|
|
460776
|
+
if (isGroupJid(this.jid)) {
|
|
460777
|
+
editKey.participant = sock.user?.id;
|
|
460778
|
+
}
|
|
460779
|
+
await sock.sendMessage(this.jid, { text, edit: editKey });
|
|
460700
460780
|
this.lastRenderedText = text;
|
|
460701
460781
|
this.lastEditAt = Date.now();
|
|
460702
460782
|
}
|
|
@@ -463225,11 +463305,33 @@ class WhatsAppPlugin extends BaseChannelPlugin {
|
|
|
463225
463305
|
await this.humanDelay(instanceId);
|
|
463226
463306
|
const sock = this.getSocket(instanceId);
|
|
463227
463307
|
const jid = toJid(chatJid);
|
|
463228
|
-
|
|
463229
|
-
|
|
463230
|
-
|
|
463231
|
-
|
|
463232
|
-
|
|
463308
|
+
const editKey = {
|
|
463309
|
+
remoteJid: jid,
|
|
463310
|
+
id: messageId,
|
|
463311
|
+
fromMe
|
|
463312
|
+
};
|
|
463313
|
+
if (isGroupJid(jid) && fromMe) {
|
|
463314
|
+
editKey.participant = sock.user?.id;
|
|
463315
|
+
}
|
|
463316
|
+
try {
|
|
463317
|
+
const result = await sock.sendMessage(jid, { edit: editKey, text: newText });
|
|
463318
|
+
this.logger.info("Message edited", {
|
|
463319
|
+
instanceId,
|
|
463320
|
+
chatJid: jid,
|
|
463321
|
+
messageId,
|
|
463322
|
+
fromMe,
|
|
463323
|
+
resultKeyId: result?.key?.id
|
|
463324
|
+
});
|
|
463325
|
+
} catch (error) {
|
|
463326
|
+
this.logger.error("Failed to edit message via Baileys", {
|
|
463327
|
+
instanceId,
|
|
463328
|
+
chatJid: jid,
|
|
463329
|
+
messageId,
|
|
463330
|
+
fromMe,
|
|
463331
|
+
error: error instanceof Error ? error.message : String(error)
|
|
463332
|
+
});
|
|
463333
|
+
throw mapBaileysError(error);
|
|
463334
|
+
}
|
|
463233
463335
|
}
|
|
463234
463336
|
getSocket(instanceId) {
|
|
463235
463337
|
const sock = this.sockets.get(instanceId);
|