@automagik/omni 2.260429.3 → 2.260429.4
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 +1 -1
- package/dist/server/index.js +493 -413
- package/package.json +10 -10
package/dist/server/index.js
CHANGED
|
@@ -224554,7 +224554,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
224554
224554
|
var require_package8 = __commonJS((exports, module) => {
|
|
224555
224555
|
module.exports = {
|
|
224556
224556
|
name: "@omni/api",
|
|
224557
|
-
version: "2.260429.
|
|
224557
|
+
version: "2.260429.4",
|
|
224558
224558
|
type: "module",
|
|
224559
224559
|
exports: {
|
|
224560
224560
|
".": {
|
|
@@ -280888,6 +280888,52 @@ var init_follow_up_sweeper = __esm(() => {
|
|
|
280888
280888
|
log84 = createLogger("follow-up-sweeper");
|
|
280889
280889
|
});
|
|
280890
280890
|
|
|
280891
|
+
// ../api/src/services/genie-hosts.ts
|
|
280892
|
+
class GenieHostsService {
|
|
280893
|
+
db;
|
|
280894
|
+
constructor(db2) {
|
|
280895
|
+
this.db = db2;
|
|
280896
|
+
}
|
|
280897
|
+
async register(input) {
|
|
280898
|
+
const existing = await this.findByPubkey(input.pubkey);
|
|
280899
|
+
if (existing) {
|
|
280900
|
+
log85.info("genie host handshake \u2014 idempotent reuse", { hostId: existing.id, hostname: existing.hostname });
|
|
280901
|
+
return existing;
|
|
280902
|
+
}
|
|
280903
|
+
const [created] = await this.db.insert(genieHosts).values({
|
|
280904
|
+
pubkey: input.pubkey,
|
|
280905
|
+
hostname: input.hostname,
|
|
280906
|
+
capabilities: input.capabilities ?? {}
|
|
280907
|
+
}).returning();
|
|
280908
|
+
if (!created) {
|
|
280909
|
+
throw new Error("failed to insert genie host");
|
|
280910
|
+
}
|
|
280911
|
+
log85.info("genie host registered", { hostId: created.id, hostname: created.hostname });
|
|
280912
|
+
return created;
|
|
280913
|
+
}
|
|
280914
|
+
async findByPubkey(pubkey) {
|
|
280915
|
+
const [row] = await this.db.select().from(genieHosts).where(eq(genieHosts.pubkey, pubkey)).limit(1);
|
|
280916
|
+
return row ?? null;
|
|
280917
|
+
}
|
|
280918
|
+
async findById(id) {
|
|
280919
|
+
const [row] = await this.db.select().from(genieHosts).where(eq(genieHosts.id, id)).limit(1);
|
|
280920
|
+
return row ?? null;
|
|
280921
|
+
}
|
|
280922
|
+
async listActive(limit2 = 100) {
|
|
280923
|
+
return this.db.select().from(genieHosts).where(isNull2(genieHosts.revokedAt)).orderBy(genieHosts.createdAt).limit(limit2);
|
|
280924
|
+
}
|
|
280925
|
+
async touchLastSeen(id) {
|
|
280926
|
+
await this.db.update(genieHosts).set({ lastSeenAt: new Date, updatedAt: new Date }).where(and2(eq(genieHosts.id, id), isNull2(genieHosts.revokedAt)));
|
|
280927
|
+
}
|
|
280928
|
+
}
|
|
280929
|
+
var log85;
|
|
280930
|
+
var init_genie_hosts = __esm(() => {
|
|
280931
|
+
init_src();
|
|
280932
|
+
init_src5();
|
|
280933
|
+
init_drizzle_orm();
|
|
280934
|
+
log85 = createLogger("genie-hosts");
|
|
280935
|
+
});
|
|
280936
|
+
|
|
280891
280937
|
// ../api/src/services/instances.ts
|
|
280892
280938
|
class InstanceService {
|
|
280893
280939
|
db;
|
|
@@ -281441,12 +281487,12 @@ class PayloadStoreService {
|
|
|
281441
281487
|
const { eventId, eventType, stage, payload } = options;
|
|
281442
281488
|
const config4 = await this.getConfig(eventType);
|
|
281443
281489
|
if (!shouldStoreStage(stage, config4)) {
|
|
281444
|
-
|
|
281490
|
+
log86.debug("Skipping payload storage", { eventId, eventType, stage, reason: "config-disabled" });
|
|
281445
281491
|
return null;
|
|
281446
281492
|
}
|
|
281447
281493
|
const insertData = preparePayloadInsert({ eventId, eventType, stage, payload });
|
|
281448
281494
|
const [result] = await this.db.insert(eventPayloads).values(insertData).returning();
|
|
281449
|
-
|
|
281495
|
+
log86.debug("Payload stored", {
|
|
281450
281496
|
eventId,
|
|
281451
281497
|
stage,
|
|
281452
281498
|
originalSize: result?.payloadSizeOriginal,
|
|
@@ -281478,7 +281524,7 @@ class PayloadStoreService {
|
|
|
281478
281524
|
deleteReason: reason,
|
|
281479
281525
|
payloadCompressed: ""
|
|
281480
281526
|
}).where(and2(eq(eventPayloads.eventId, eventId), isNull2(eventPayloads.deletedAt))).returning({ id: eventPayloads.id });
|
|
281481
|
-
|
|
281527
|
+
log86.info("Payloads soft-deleted", { eventId, count: result.length, deletedBy, reason });
|
|
281482
281528
|
return result.length;
|
|
281483
281529
|
}
|
|
281484
281530
|
async listConfigs() {
|
|
@@ -281500,7 +281546,7 @@ class PayloadStoreService {
|
|
|
281500
281546
|
}
|
|
281501
281547
|
}).returning();
|
|
281502
281548
|
this.configCache.delete(eventType);
|
|
281503
|
-
|
|
281549
|
+
log86.info("Payload storage config updated", { eventType });
|
|
281504
281550
|
if (!result) {
|
|
281505
281551
|
throw new Error("Failed to create/update payload storage config");
|
|
281506
281552
|
}
|
|
@@ -281552,17 +281598,17 @@ class PayloadStoreService {
|
|
|
281552
281598
|
totalDeleted += deleted.length;
|
|
281553
281599
|
}
|
|
281554
281600
|
if (totalDeleted > 0) {
|
|
281555
|
-
|
|
281601
|
+
log86.info("Cleaned up expired payloads", { count: totalDeleted });
|
|
281556
281602
|
}
|
|
281557
281603
|
return totalDeleted;
|
|
281558
281604
|
}
|
|
281559
281605
|
}
|
|
281560
|
-
var
|
|
281606
|
+
var log86;
|
|
281561
281607
|
var init_payload_store2 = __esm(() => {
|
|
281562
281608
|
init_src();
|
|
281563
281609
|
init_src5();
|
|
281564
281610
|
init_drizzle_orm();
|
|
281565
|
-
|
|
281611
|
+
log86 = createLogger("payload-store");
|
|
281566
281612
|
});
|
|
281567
281613
|
|
|
281568
281614
|
// ../api/src/services/persons.ts
|
|
@@ -281958,23 +282004,23 @@ var init_persons = __esm(() => {
|
|
|
281958
282004
|
// ../api/src/lib/idempotency.ts
|
|
281959
282005
|
async function withIdempotency(db2, eventId, handler, fn) {
|
|
281960
282006
|
if (!eventId) {
|
|
281961
|
-
|
|
282007
|
+
log87.warn("idempotency: missing event id, running without dedupe", { handler });
|
|
281962
282008
|
await fn();
|
|
281963
282009
|
return { executed: true };
|
|
281964
282010
|
}
|
|
281965
282011
|
const claim = await db2.insert(processedEvents).values({ eventId, handler }).onConflictDoNothing().returning({ eventId: processedEvents.eventId });
|
|
281966
282012
|
if (claim.length === 0) {
|
|
281967
|
-
|
|
282013
|
+
log87.info("idempotency: skipping replay", { eventId, handler });
|
|
281968
282014
|
return { executed: false };
|
|
281969
282015
|
}
|
|
281970
282016
|
await fn();
|
|
281971
282017
|
return { executed: true };
|
|
281972
282018
|
}
|
|
281973
|
-
var
|
|
282019
|
+
var log87;
|
|
281974
282020
|
var init_idempotency = __esm(() => {
|
|
281975
282021
|
init_src();
|
|
281976
282022
|
init_src5();
|
|
281977
|
-
|
|
282023
|
+
log87 = createLogger("idempotency");
|
|
281978
282024
|
});
|
|
281979
282025
|
|
|
281980
282026
|
// ../api/src/services/message-context.ts
|
|
@@ -282008,9 +282054,9 @@ async function initTurnEvents(natsUrl) {
|
|
|
282008
282054
|
maxReconnectAttempts: -1,
|
|
282009
282055
|
reconnectTimeWait: 2000
|
|
282010
282056
|
});
|
|
282011
|
-
|
|
282057
|
+
log88.info("Turn events NATS connected", { url: natsUrl });
|
|
282012
282058
|
} catch (error2) {
|
|
282013
|
-
|
|
282059
|
+
log88.warn("Failed to connect NATS for turn events", { error: String(error2) });
|
|
282014
282060
|
}
|
|
282015
282061
|
}
|
|
282016
282062
|
async function closeTurnEvents() {
|
|
@@ -282021,7 +282067,7 @@ async function closeTurnEvents() {
|
|
|
282021
282067
|
}
|
|
282022
282068
|
function publish(topic, payload) {
|
|
282023
282069
|
if (!nc || nc.isClosed()) {
|
|
282024
|
-
|
|
282070
|
+
log88.warn("Cannot publish turn event: NATS not connected", { topic });
|
|
282025
282071
|
return;
|
|
282026
282072
|
}
|
|
282027
282073
|
nc.publish(topic, sc2.encode(JSON.stringify(payload)));
|
|
@@ -282029,33 +282075,33 @@ function publish(topic, payload) {
|
|
|
282029
282075
|
function publishTurnOpen(instanceId, chatId, event) {
|
|
282030
282076
|
const topic = `omni.turn.open.${instanceId}.${chatId}`;
|
|
282031
282077
|
publish(topic, event);
|
|
282032
|
-
|
|
282078
|
+
log88.debug("Published turn.open", { turnId: event.turnId, instanceId, chatId });
|
|
282033
282079
|
}
|
|
282034
282080
|
function publishTurnDone(instanceId, chatId, event) {
|
|
282035
282081
|
const topic = `omni.turn.done.${instanceId}.${chatId}`;
|
|
282036
282082
|
publish(topic, event);
|
|
282037
|
-
|
|
282083
|
+
log88.debug("Published turn.done", { turnId: event.turnId, action: event.action, instanceId });
|
|
282038
282084
|
}
|
|
282039
282085
|
function publishTurnNudge(instanceId, chatId, event) {
|
|
282040
282086
|
const topic = `omni.turn.nudge.${instanceId}.${chatId}`;
|
|
282041
282087
|
publish(topic, event);
|
|
282042
|
-
|
|
282088
|
+
log88.debug("Published turn.nudge", { turnId: event.turnId, nudgeCount: event.nudgeCount, instanceId });
|
|
282043
282089
|
}
|
|
282044
282090
|
function publishTurnStalled(instanceId, chatId, event) {
|
|
282045
282091
|
const topic = `omni.turn.stalled.${instanceId}.${chatId}`;
|
|
282046
282092
|
publish(topic, event);
|
|
282047
|
-
|
|
282093
|
+
log88.debug("Published turn.stalled", { turnId: event.turnId, instanceId, chatId });
|
|
282048
282094
|
}
|
|
282049
282095
|
function publishTurnTimeout(instanceId, chatId, event) {
|
|
282050
282096
|
const topic = `omni.turn.timeout.${instanceId}.${chatId}`;
|
|
282051
282097
|
publish(topic, event);
|
|
282052
|
-
|
|
282098
|
+
log88.debug("Published turn.timeout", { turnId: event.turnId, instanceId });
|
|
282053
282099
|
}
|
|
282054
|
-
var import_nats7,
|
|
282100
|
+
var import_nats7, log88, sc2, nc = null;
|
|
282055
282101
|
var init_turn_events = __esm(() => {
|
|
282056
282102
|
init_src();
|
|
282057
282103
|
import_nats7 = __toESM(require_mod4(), 1);
|
|
282058
|
-
|
|
282104
|
+
log88 = createLogger("turn-events");
|
|
282059
282105
|
sc2 = import_nats7.StringCodec();
|
|
282060
282106
|
});
|
|
282061
282107
|
|
|
@@ -282092,7 +282138,7 @@ class DatabasePluginStorage {
|
|
|
282092
282138
|
const result = await this.db.select().from(pluginStorage).where(and2(eq(pluginStorage.pluginId, this.pluginId), eq(pluginStorage.key, fullKey), or2(isNull2(pluginStorage.expiresAt), gt(pluginStorage.expiresAt, new Date)))).limit(1);
|
|
282093
282139
|
const elapsed = Date.now() - t0;
|
|
282094
282140
|
if (elapsed > 500) {
|
|
282095
|
-
|
|
282141
|
+
log89.warn("Slow storage.get", {
|
|
282096
282142
|
pluginId: this.pluginId,
|
|
282097
282143
|
key: fullKey.slice(-80),
|
|
282098
282144
|
elapsedMs: elapsed
|
|
@@ -282226,19 +282272,19 @@ function getPluginStorage(pluginId) {
|
|
|
282226
282272
|
if (globalDb) {
|
|
282227
282273
|
storage = new DatabasePluginStorage(globalDb, pluginId);
|
|
282228
282274
|
} else {
|
|
282229
|
-
|
|
282275
|
+
log89.warn("Database not available, using in-memory storage", { pluginId });
|
|
282230
282276
|
storage = new InMemoryPluginStorage(pluginId);
|
|
282231
282277
|
}
|
|
282232
282278
|
storageInstances.set(pluginId, storage);
|
|
282233
282279
|
}
|
|
282234
282280
|
return storage;
|
|
282235
282281
|
}
|
|
282236
|
-
var
|
|
282282
|
+
var log89, globalDb = null, storageInstances;
|
|
282237
282283
|
var init_storage = __esm(() => {
|
|
282238
282284
|
init_src();
|
|
282239
282285
|
init_src5();
|
|
282240
282286
|
init_drizzle_orm();
|
|
282241
|
-
|
|
282287
|
+
log89 = createLogger("api:storage");
|
|
282242
282288
|
storageInstances = new Map;
|
|
282243
282289
|
});
|
|
282244
282290
|
|
|
@@ -282246,7 +282292,7 @@ var init_storage = __esm(() => {
|
|
|
282246
282292
|
function createPluginDatabase(db2) {
|
|
282247
282293
|
return {
|
|
282248
282294
|
async execute(_sql, _params) {
|
|
282249
|
-
|
|
282295
|
+
log90.warn("PluginDatabase execute() is not implemented. Use getDrizzle() for queries.");
|
|
282250
282296
|
return [];
|
|
282251
282297
|
},
|
|
282252
282298
|
getDrizzle() {
|
|
@@ -282275,12 +282321,12 @@ function createPluginContext(options) {
|
|
|
282275
282321
|
db: createPluginDatabase(db2)
|
|
282276
282322
|
};
|
|
282277
282323
|
}
|
|
282278
|
-
var
|
|
282324
|
+
var log90;
|
|
282279
282325
|
var init_context3 = __esm(() => {
|
|
282280
282326
|
init_src();
|
|
282281
282327
|
init_logger5();
|
|
282282
282328
|
init_storage();
|
|
282283
|
-
|
|
282329
|
+
log90 = createLogger("api:plugin-context");
|
|
282284
282330
|
});
|
|
282285
282331
|
|
|
282286
282332
|
// ../api/src/plugins/loader.ts
|
|
@@ -282407,7 +282453,7 @@ class MessageDebouncer {
|
|
|
282407
282453
|
if (this.inFlight.has(chatKey))
|
|
282408
282454
|
return;
|
|
282409
282455
|
if (config4.restartOnTyping && this.buffers.has(chatKey)) {
|
|
282410
|
-
|
|
282456
|
+
log91.debug("Restarting debounce timer on user typing", { chatKey });
|
|
282411
282457
|
this.restartTimer(chatKey, config4, true);
|
|
282412
282458
|
}
|
|
282413
282459
|
}
|
|
@@ -282447,7 +282493,7 @@ class MessageDebouncer {
|
|
|
282447
282493
|
try {
|
|
282448
282494
|
await this.onFlush(chatKey, messages4);
|
|
282449
282495
|
} catch (error2) {
|
|
282450
|
-
|
|
282496
|
+
log91.error("Error flushing debounced messages", { chatKey, error: String(error2) });
|
|
282451
282497
|
} finally {
|
|
282452
282498
|
this.inFlight.delete(chatKey);
|
|
282453
282499
|
const pending = this.buffers.get(chatKey);
|
|
@@ -282464,10 +282510,10 @@ class MessageDebouncer {
|
|
|
282464
282510
|
this.inFlight.clear();
|
|
282465
282511
|
}
|
|
282466
282512
|
}
|
|
282467
|
-
var
|
|
282513
|
+
var log91;
|
|
282468
282514
|
var init_message_debouncer = __esm(() => {
|
|
282469
282515
|
init_src();
|
|
282470
|
-
|
|
282516
|
+
log91 = createLogger("message-debouncer");
|
|
282471
282517
|
});
|
|
282472
282518
|
|
|
282473
282519
|
// ../api/src/plugins/message-persistence.ts
|
|
@@ -282575,7 +282621,7 @@ async function processSenderIdentity(services, payload, metadata, channel4) {
|
|
|
282575
282621
|
matchByChannel: channel4
|
|
282576
282622
|
});
|
|
282577
282623
|
if (isNew) {
|
|
282578
|
-
|
|
282624
|
+
log92.debug("Auto-created identity for sender", {
|
|
282579
282625
|
platformUserId: payload.from,
|
|
282580
282626
|
identityId: identity.id,
|
|
282581
282627
|
personId: person2?.id
|
|
@@ -282593,14 +282639,14 @@ async function fetchAndUpdateProfile(services, channel4, instanceId, userId, ide
|
|
|
282593
282639
|
const profile = await fetchProfile.call(plugin7, instanceId, userId);
|
|
282594
282640
|
if (profile.avatarUrl || profile.bio || profile.platformData) {
|
|
282595
282641
|
await services.persons.updateIdentityProfile(identityId, profile);
|
|
282596
|
-
|
|
282642
|
+
log92.debug("Updated identity with profile data", {
|
|
282597
282643
|
identityId,
|
|
282598
282644
|
hasAvatar: !!profile.avatarUrl,
|
|
282599
282645
|
hasBio: !!profile.bio
|
|
282600
282646
|
});
|
|
282601
282647
|
}
|
|
282602
282648
|
} catch (error2) {
|
|
282603
|
-
|
|
282649
|
+
log92.warn("Failed to fetch profile for new identity", { identityId, error: String(error2) });
|
|
282604
282650
|
}
|
|
282605
282651
|
}
|
|
282606
282652
|
function shouldUpdateChatName(current, incoming) {
|
|
@@ -282614,7 +282660,7 @@ async function persistLidMappings(services, chat2, chatExternalId, instanceId, r
|
|
|
282614
282660
|
const originalLidJid = rawPayload?.originalLidJid;
|
|
282615
282661
|
if (originalLidJid && chatExternalId.endsWith("@s.whatsapp.net")) {
|
|
282616
282662
|
services.chats.upsertLidMapping(instanceId, originalLidJid, chatExternalId).catch((err) => {
|
|
282617
|
-
|
|
282663
|
+
log92.debug("Failed to persist LID mapping (non-critical)", { error: String(err) });
|
|
282618
282664
|
});
|
|
282619
282665
|
if (!chat2.canonicalId) {
|
|
282620
282666
|
await services.chats.update(chat2.id, { canonicalId: chatExternalId });
|
|
@@ -282624,14 +282670,14 @@ async function persistLidMappings(services, chat2, chatExternalId, instanceId, r
|
|
|
282624
282670
|
const resolvedPhoneJid = rawPayload?.resolvedPhoneJid;
|
|
282625
282671
|
if (chatExternalId.endsWith("@lid") && resolvedPhoneJid) {
|
|
282626
282672
|
services.chats.upsertLidMapping(instanceId, chatExternalId, resolvedPhoneJid).catch((err) => {
|
|
282627
|
-
|
|
282673
|
+
log92.debug("Failed to persist LID\u2194phone mapping for LID-canonical chat (non-critical)", { error: String(err) });
|
|
282628
282674
|
});
|
|
282629
282675
|
if (!chat2.canonicalId) {
|
|
282630
282676
|
try {
|
|
282631
282677
|
await services.chats.update(chat2.id, { canonicalId: resolvedPhoneJid });
|
|
282632
282678
|
chat2.canonicalId = resolvedPhoneJid;
|
|
282633
282679
|
} catch (err) {
|
|
282634
|
-
|
|
282680
|
+
log92.debug("canonicalId backfill skipped \u2014 already claimed by another chat", {
|
|
282635
282681
|
chatId: chat2.id,
|
|
282636
282682
|
resolvedPhoneJid,
|
|
282637
282683
|
error: String(err)
|
|
@@ -282695,10 +282741,10 @@ function maybeUpdateRecency(services, instanceId, chatId, rawPayload, payload, p
|
|
|
282695
282741
|
const preview = sanitizeText(buildChatPreview(payload, rawPayload)) ?? "";
|
|
282696
282742
|
const isFromMe2 = rawPayload?.isFromMe === true;
|
|
282697
282743
|
services.chats.updateLastMessage(chatId, preview, platformTimestamp, isFromMe2).catch((error2) => {
|
|
282698
|
-
|
|
282744
|
+
log92.debug("Failed to update chat lastMessage (non-critical)", { error: String(error2) });
|
|
282699
282745
|
});
|
|
282700
282746
|
services.instances.updateLastMessageAt(instanceId, platformTimestamp).catch((error2) => {
|
|
282701
|
-
|
|
282747
|
+
log92.debug("Failed to update instance lastMessageAt (non-critical)", { error: String(error2) });
|
|
282702
282748
|
});
|
|
282703
282749
|
}
|
|
282704
282750
|
async function resolveOrCreateChat(services, instanceId, chatExternalId, chatType, channel4, effectiveName, canonicalId, rawPayload) {
|
|
@@ -282707,7 +282753,7 @@ async function resolveOrCreateChat(services, instanceId, chatExternalId, chatTyp
|
|
|
282707
282753
|
return services.chats.findByExternalIdSmart(instanceId, resolvedPhoneJid).then((phoneChat) => {
|
|
282708
282754
|
if (phoneChat) {
|
|
282709
282755
|
services.chats.upsertLidMapping(instanceId, chatExternalId, resolvedPhoneJid).catch((err) => {
|
|
282710
|
-
|
|
282756
|
+
log92.debug("Failed to persist LID mapping during chat pre-check (non-critical)", { error: String(err) });
|
|
282711
282757
|
});
|
|
282712
282758
|
return { chat: phoneChat, created: false };
|
|
282713
282759
|
}
|
|
@@ -282766,7 +282812,7 @@ async function handleMessageReceived(services, payload, metadata, eventTimestamp
|
|
|
282766
282812
|
});
|
|
282767
282813
|
await maybeRecordMessageEdit(services, created, rawPayload, message2.id, sanitizeText(payload.content.text) ?? undefined, platformTimestamp, payload.from);
|
|
282768
282814
|
if (created) {
|
|
282769
|
-
|
|
282815
|
+
log92.debug("Created message", { externalId: payload.externalId, chatId: chat2.id });
|
|
282770
282816
|
}
|
|
282771
282817
|
await maybeRecordParticipantActivity(services, chat2.id, payload.from);
|
|
282772
282818
|
maybeUpdateRecency(services, metadata.instanceId, chat2.id, rawPayload, payload, platformTimestamp);
|
|
@@ -282775,7 +282821,7 @@ function logMessageReceivedError(payload, error2) {
|
|
|
282775
282821
|
const rawPayload = payload.rawPayload;
|
|
282776
282822
|
const quotedMsg = rawPayload?.quotedMessage;
|
|
282777
282823
|
const longFields = findLongStrings(rawPayload, "raw.");
|
|
282778
|
-
|
|
282824
|
+
log92.error("Failed to persist message.received to unified model", {
|
|
282779
282825
|
externalId: payload.externalId,
|
|
282780
282826
|
error: String(error2),
|
|
282781
282827
|
fieldLengths: {
|
|
@@ -282797,7 +282843,7 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282797
282843
|
const payload = event.payload;
|
|
282798
282844
|
const metadata = event.metadata;
|
|
282799
282845
|
if (!metadata.instanceId) {
|
|
282800
|
-
|
|
282846
|
+
log92.debug("Skipping message without instanceId", { externalId: payload.externalId });
|
|
282801
282847
|
return;
|
|
282802
282848
|
}
|
|
282803
282849
|
try {
|
|
@@ -282827,7 +282873,7 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282827
282873
|
const metadata = event.metadata;
|
|
282828
282874
|
try {
|
|
282829
282875
|
if (!metadata.instanceId) {
|
|
282830
|
-
|
|
282876
|
+
log92.debug("Skipping sent message without instanceId", { externalId: payload.externalId });
|
|
282831
282877
|
return;
|
|
282832
282878
|
}
|
|
282833
282879
|
const chatExternalId = truncate3(payload.chatId, 255) ?? payload.chatId;
|
|
@@ -282850,18 +282896,18 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282850
282896
|
replyToExternalId: truncate3(payload.replyToId, 255)
|
|
282851
282897
|
});
|
|
282852
282898
|
if (created) {
|
|
282853
|
-
|
|
282899
|
+
log92.debug("Created sent message", {
|
|
282854
282900
|
messageId: message2.id,
|
|
282855
282901
|
externalId: payload.externalId,
|
|
282856
282902
|
chatId: chat2.id
|
|
282857
282903
|
});
|
|
282858
282904
|
}
|
|
282859
|
-
services.chats.updateLastMessage(chat2.id, sanitizeText(payload.content.text ?? "") ?? "", new Date(event.timestamp), true).catch((err) =>
|
|
282905
|
+
services.chats.updateLastMessage(chat2.id, sanitizeText(payload.content.text ?? "") ?? "", new Date(event.timestamp), true).catch((err) => log92.debug("Failed to update chat recency (sent)", { error: String(err) }));
|
|
282860
282906
|
if (metadata.streamSequence) {
|
|
282861
282907
|
await services.consumerOffsets.updateOffset("message-persistence-sent", "MESSAGE", metadata.streamSequence, event.id);
|
|
282862
282908
|
}
|
|
282863
282909
|
} catch (error2) {
|
|
282864
|
-
|
|
282910
|
+
log92.error("Failed to persist message.sent to unified model", {
|
|
282865
282911
|
externalId: payload.externalId,
|
|
282866
282912
|
error: String(error2)
|
|
282867
282913
|
});
|
|
@@ -282885,18 +282931,18 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282885
282931
|
return;
|
|
282886
282932
|
const chat2 = await services.chats.findByExternalIdSmart(metadata.instanceId, payload.chatId);
|
|
282887
282933
|
if (!chat2) {
|
|
282888
|
-
|
|
282934
|
+
log92.debug("Chat not found for message.delivered", { chatId: payload.chatId });
|
|
282889
282935
|
return;
|
|
282890
282936
|
}
|
|
282891
282937
|
const message2 = await services.messages.getByExternalId(chat2.id, payload.externalId);
|
|
282892
282938
|
if (!message2) {
|
|
282893
|
-
|
|
282939
|
+
log92.debug("Message not found for message.delivered", { externalId: payload.externalId });
|
|
282894
282940
|
return;
|
|
282895
282941
|
}
|
|
282896
282942
|
await services.messages.updateDeliveryStatus(message2.id, "delivered");
|
|
282897
|
-
|
|
282943
|
+
log92.debug("Updated message delivery status", { messageId: message2.id, status: "delivered" });
|
|
282898
282944
|
} catch (error2) {
|
|
282899
|
-
|
|
282945
|
+
log92.error("Failed to update delivery status", {
|
|
282900
282946
|
externalId: payload.externalId,
|
|
282901
282947
|
error: String(error2)
|
|
282902
282948
|
});
|
|
@@ -282919,18 +282965,18 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282919
282965
|
return;
|
|
282920
282966
|
const chat2 = await services.chats.findByExternalIdSmart(metadata.instanceId, payload.chatId);
|
|
282921
282967
|
if (!chat2) {
|
|
282922
|
-
|
|
282968
|
+
log92.debug("Chat not found for message.read", { chatId: payload.chatId });
|
|
282923
282969
|
return;
|
|
282924
282970
|
}
|
|
282925
282971
|
const message2 = await services.messages.getByExternalId(chat2.id, payload.externalId);
|
|
282926
282972
|
if (!message2) {
|
|
282927
|
-
|
|
282973
|
+
log92.debug("Message not found for message.read", { externalId: payload.externalId });
|
|
282928
282974
|
return;
|
|
282929
282975
|
}
|
|
282930
282976
|
await services.messages.updateDeliveryStatus(message2.id, "read");
|
|
282931
|
-
|
|
282977
|
+
log92.debug("Updated message delivery status", { messageId: message2.id, status: "read" });
|
|
282932
282978
|
} catch (error2) {
|
|
282933
|
-
|
|
282979
|
+
log92.error("Failed to update read status", {
|
|
282934
282980
|
externalId: payload.externalId,
|
|
282935
282981
|
error: String(error2)
|
|
282936
282982
|
});
|
|
@@ -282959,12 +283005,12 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282959
283005
|
if (gapMs > gapThresholdMs) {
|
|
282960
283006
|
const channelType = event.metadata.channelType ?? "whatsapp-baileys";
|
|
282961
283007
|
if (channelType === "discord") {
|
|
282962
|
-
|
|
283008
|
+
log92.info("Instance reconnected with message gap (Discord \u2014 skipping auto-backfill, use manual sync)", {
|
|
282963
283009
|
instanceId,
|
|
282964
283010
|
gapMinutes
|
|
282965
283011
|
});
|
|
282966
283012
|
} else {
|
|
282967
|
-
|
|
283013
|
+
log92.warn("Instance reconnected with message gap", {
|
|
282968
283014
|
instanceId,
|
|
282969
283015
|
lastMessageAt: lastMessageAt.toISOString(),
|
|
282970
283016
|
gapMinutes
|
|
@@ -282978,7 +283024,7 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282978
283024
|
until: new Date().toISOString()
|
|
282979
283025
|
}
|
|
282980
283026
|
});
|
|
282981
|
-
|
|
283027
|
+
log92.info("Post-reconnect backfill triggered", {
|
|
282982
283028
|
instanceId,
|
|
282983
283029
|
jobId: job.id,
|
|
282984
283030
|
since: lastMessageAt.toISOString(),
|
|
@@ -282986,10 +283032,10 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
282986
283032
|
});
|
|
282987
283033
|
}
|
|
282988
283034
|
} else {
|
|
282989
|
-
|
|
283035
|
+
log92.debug("Instance reconnected, gap within threshold", { instanceId, gapMinutes });
|
|
282990
283036
|
}
|
|
282991
283037
|
} catch (error2) {
|
|
282992
|
-
|
|
283038
|
+
log92.warn("Post-reconnect gap check failed (non-critical)", {
|
|
282993
283039
|
instanceId,
|
|
282994
283040
|
error: String(error2)
|
|
282995
283041
|
});
|
|
@@ -283002,12 +283048,12 @@ async function setupMessagePersistence(eventBus, services) {
|
|
|
283002
283048
|
startFrom: "first",
|
|
283003
283049
|
concurrency: 5
|
|
283004
283050
|
});
|
|
283005
|
-
|
|
283051
|
+
log92.info("Message persistence initialized - populating unified chats/messages");
|
|
283006
283052
|
detectStartupGaps(services).catch((error2) => {
|
|
283007
|
-
|
|
283053
|
+
log92.warn("Startup gap detection failed (non-critical)", { error: String(error2) });
|
|
283008
283054
|
});
|
|
283009
283055
|
} catch (error2) {
|
|
283010
|
-
|
|
283056
|
+
log92.error("Failed to set up message persistence", { error: String(error2) });
|
|
283011
283057
|
throw error2;
|
|
283012
283058
|
}
|
|
283013
283059
|
}
|
|
@@ -283021,17 +283067,17 @@ async function detectStartupGaps(services) {
|
|
|
283021
283067
|
for (const consumerName of consumers) {
|
|
283022
283068
|
const offset = await services.consumerOffsets.getOffset(consumerName);
|
|
283023
283069
|
if (offset > 0) {
|
|
283024
|
-
|
|
283070
|
+
log92.info("Consumer startup offset", { consumer: consumerName, lastSequence: offset });
|
|
283025
283071
|
}
|
|
283026
283072
|
}
|
|
283027
283073
|
}
|
|
283028
|
-
var
|
|
283074
|
+
var log92, CONTENT_TYPE_MAP, INTERNAL_JID_SUFFIXES, MEDIA_BADGES2;
|
|
283029
283075
|
var init_message_persistence = __esm(() => {
|
|
283030
283076
|
init_src();
|
|
283031
283077
|
init_esm5();
|
|
283032
283078
|
init_sentry_scrub();
|
|
283033
283079
|
init_loader2();
|
|
283034
|
-
|
|
283080
|
+
log92 = createLogger("message-persistence");
|
|
283035
283081
|
CONTENT_TYPE_MAP = {
|
|
283036
283082
|
audio: "audio",
|
|
283037
283083
|
image: "image",
|
|
@@ -283145,7 +283191,7 @@ class ReactionDedup {
|
|
|
283145
283191
|
}
|
|
283146
283192
|
const msgCount = this.messageCounters.get(messageId) ?? 0;
|
|
283147
283193
|
if (msgCount >= this.maxPerMessage) {
|
|
283148
|
-
|
|
283194
|
+
log93.debug("Reaction per-message limit reached", { messageId, count: msgCount });
|
|
283149
283195
|
return true;
|
|
283150
283196
|
}
|
|
283151
283197
|
this.seen.set(key, Date.now());
|
|
@@ -283253,7 +283299,7 @@ async function sendTypingPresence(channel4, instanceId, chatId, state) {
|
|
|
283253
283299
|
await plugin7.sendTyping(instanceId, chatId, duration);
|
|
283254
283300
|
}
|
|
283255
283301
|
} catch (error2) {
|
|
283256
|
-
|
|
283302
|
+
log93.debug("Failed to send typing presence", { error: String(error2) });
|
|
283257
283303
|
}
|
|
283258
283304
|
}
|
|
283259
283305
|
async function sendTextMessage5(channel4, instanceId, chatId, text3, messageFormatMode = "convert", replyTo, correlationId, senderAgentId) {
|
|
@@ -283272,7 +283318,7 @@ async function sendTextMessage5(channel4, instanceId, chatId, text3, messageForm
|
|
|
283272
283318
|
}
|
|
283273
283319
|
async function sendErrorFeedback(channel4, instanceId, chatId, error2) {
|
|
283274
283320
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
283275
|
-
|
|
283321
|
+
log93.error("agent_dispatch_error", { channel: channel4, instanceId, chatId, error: errorMsg });
|
|
283276
283322
|
const text3 = "\u26A0\uFE0F Sorry, I ran into an issue processing your message. Please try again.";
|
|
283277
283323
|
await sendTextMessage5(channel4, instanceId, chatId, text3);
|
|
283278
283324
|
}
|
|
@@ -283298,7 +283344,7 @@ async function runWithTransientDispatchRetry(fn, context15, options = {}) {
|
|
|
283298
283344
|
const delays = options.delaysMs ?? TRANSIENT_DISPATCH_RETRY_DELAYS_MS;
|
|
283299
283345
|
const transient = options.isTransient ?? isTransientDispatchError;
|
|
283300
283346
|
const sleeper = options.sleeper ?? sleep5;
|
|
283301
|
-
const logger7 = options.logger ??
|
|
283347
|
+
const logger7 = options.logger ?? log93;
|
|
283302
283348
|
let lastError;
|
|
283303
283349
|
for (let attempt = 0;attempt <= delays.length; attempt++) {
|
|
283304
283350
|
try {
|
|
@@ -283368,7 +283414,7 @@ function resolveMediaPath(mediaUrl) {
|
|
|
283368
283414
|
const fullPath = resolve3(MEDIA_BASE_PATH3, relativePath);
|
|
283369
283415
|
const basePath = resolve3(MEDIA_BASE_PATH3);
|
|
283370
283416
|
if (!fullPath.startsWith(`${basePath}/`) && fullPath !== basePath) {
|
|
283371
|
-
|
|
283417
|
+
log93.warn("Path traversal attempt blocked", { mediaUrl, resolved: fullPath, basePath });
|
|
283372
283418
|
return null;
|
|
283373
283419
|
}
|
|
283374
283420
|
return fullPath;
|
|
@@ -283438,17 +283484,17 @@ async function awaitMediaProcessing(services, instanceId, chatId, externalId, co
|
|
|
283438
283484
|
return MEDIA_WAIT_NULL;
|
|
283439
283485
|
const chat2 = await waitForRecord(() => services.chats.findByExternalIdSmart(instanceId, chatId));
|
|
283440
283486
|
if (!chat2) {
|
|
283441
|
-
|
|
283487
|
+
log93.warn("Chat not found for media wait", { instanceId, chatId });
|
|
283442
283488
|
return MEDIA_WAIT_NULL;
|
|
283443
283489
|
}
|
|
283444
283490
|
const msg = await waitForRecord(() => services.messages.getByExternalId(chat2.id, externalId));
|
|
283445
283491
|
if (!msg) {
|
|
283446
|
-
|
|
283492
|
+
log93.warn("Message not found for media wait after retries", { instanceId, chatId, externalId });
|
|
283447
283493
|
return MEDIA_WAIT_NULL;
|
|
283448
283494
|
}
|
|
283449
283495
|
const existing = checkProcessedColumn(msg, column2);
|
|
283450
283496
|
if (existing === "error") {
|
|
283451
|
-
|
|
283497
|
+
log93.warn("Media processing failed (DB)", { instanceId, chatId, externalId });
|
|
283452
283498
|
return MEDIA_WAIT_NULL;
|
|
283453
283499
|
}
|
|
283454
283500
|
if (existing !== "pending")
|
|
@@ -283509,7 +283555,7 @@ async function resolveQuotedMessage(services, instanceId, chatId, replyToId) {
|
|
|
283509
283555
|
const timeStr = time3 ? ` at ${time3}` : "";
|
|
283510
283556
|
return `[Quoting ${sender}${timeStr}: ${truncated}]`;
|
|
283511
283557
|
} catch (error2) {
|
|
283512
|
-
|
|
283558
|
+
log93.debug("Failed to resolve quoted message", { replyToId, error: String(error2) });
|
|
283513
283559
|
return null;
|
|
283514
283560
|
}
|
|
283515
283561
|
}
|
|
@@ -283550,7 +283596,7 @@ async function collectProcessedMedia(services, instance4, messages4) {
|
|
|
283550
283596
|
try {
|
|
283551
283597
|
result = await awaitMediaProcessing(services, instance4.id, m2.payload.chatId, m2.payload.externalId, contentType);
|
|
283552
283598
|
} catch (error2) {
|
|
283553
|
-
|
|
283599
|
+
log93.warn("Media await failed", { externalId: m2.payload.externalId, error: String(error2) });
|
|
283554
283600
|
result = MEDIA_WAIT_NULL;
|
|
283555
283601
|
}
|
|
283556
283602
|
if (result.content) {
|
|
@@ -283588,11 +283634,11 @@ async function resolveContactName(services, instanceId, jid, cacheMap) {
|
|
|
283588
283634
|
try {
|
|
283589
283635
|
const chat2 = await services.chats.findByExternalIdSmart(instanceId, jid);
|
|
283590
283636
|
if (chat2?.name) {
|
|
283591
|
-
|
|
283637
|
+
log93.debug("Contact name from DB fallback", { jid, name: chat2.name });
|
|
283592
283638
|
return chat2.name;
|
|
283593
283639
|
}
|
|
283594
283640
|
} catch (error2) {
|
|
283595
|
-
|
|
283641
|
+
log93.warn("Failed to query DB for contact", { jid, error: String(error2) });
|
|
283596
283642
|
}
|
|
283597
283643
|
return null;
|
|
283598
283644
|
}
|
|
@@ -283624,14 +283670,14 @@ async function applyJidMentionReplacement(services, instanceId, jid, jidToName,
|
|
|
283624
283670
|
async function replaceMentionsWithContactNames(services, instanceId, text3, mentionedJids, mentionedContacts) {
|
|
283625
283671
|
if (!mentionedJids?.length)
|
|
283626
283672
|
return text3;
|
|
283627
|
-
|
|
283673
|
+
log93.debug("Starting mention replacement", { mentionCount: mentionedJids.length });
|
|
283628
283674
|
const jidToName = buildJidNameMap(mentionedContacts);
|
|
283629
283675
|
const stats = { resolved: 0, replaced: 0, unresolved: 0, skipped: 0 };
|
|
283630
283676
|
let replacedText = text3;
|
|
283631
283677
|
for (const jid of mentionedJids) {
|
|
283632
283678
|
replacedText = await applyJidMentionReplacement(services, instanceId, jid, jidToName, replacedText, stats);
|
|
283633
283679
|
}
|
|
283634
|
-
|
|
283680
|
+
log93.debug("Mention replacement complete", {
|
|
283635
283681
|
original: text3,
|
|
283636
283682
|
replaced: replacedText,
|
|
283637
283683
|
mentionCount: mentionedJids.length,
|
|
@@ -283700,7 +283746,7 @@ async function fetchSenderMetadata(services, channel4, instanceId, senderId) {
|
|
|
283700
283746
|
platformUsername: identity?.platformUsername ?? undefined
|
|
283701
283747
|
};
|
|
283702
283748
|
} catch (error2) {
|
|
283703
|
-
|
|
283749
|
+
log93.debug("Failed to fetch sender identity metadata", { error: String(error2) });
|
|
283704
283750
|
return {};
|
|
283705
283751
|
}
|
|
283706
283752
|
}
|
|
@@ -283714,7 +283760,7 @@ async function fetchChatMetadata(services, instanceId, chatId, chatType) {
|
|
|
283714
283760
|
participantCount: chat2?.participantCount ?? undefined
|
|
283715
283761
|
};
|
|
283716
283762
|
} catch (error2) {
|
|
283717
|
-
|
|
283763
|
+
log93.debug("Failed to fetch chat metadata", { error: String(error2) });
|
|
283718
283764
|
return {};
|
|
283719
283765
|
}
|
|
283720
283766
|
}
|
|
@@ -283736,7 +283782,7 @@ async function routeStreamDelta(sender, delta) {
|
|
|
283736
283782
|
}
|
|
283737
283783
|
async function resolveStreamingCapabilities(services, instance4, channel4, chatId, traceId, db2) {
|
|
283738
283784
|
if (!instance4.agentStreamMode) {
|
|
283739
|
-
|
|
283785
|
+
log93.debug("Stream guard: agentStreamMode is falsy", {
|
|
283740
283786
|
instanceId: instance4.id,
|
|
283741
283787
|
agentStreamMode: instance4.agentStreamMode,
|
|
283742
283788
|
chatId
|
|
@@ -283745,7 +283791,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
283745
283791
|
}
|
|
283746
283792
|
const provider = await getAgentProvider(services, instance4, db2);
|
|
283747
283793
|
if (!provider?.triggerStream) {
|
|
283748
|
-
|
|
283794
|
+
log93.debug("Stream guard: provider has no triggerStream", {
|
|
283749
283795
|
instanceId: instance4.id,
|
|
283750
283796
|
hasProvider: !!provider,
|
|
283751
283797
|
chatId
|
|
@@ -283754,7 +283800,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
283754
283800
|
}
|
|
283755
283801
|
const plugin7 = await getPlugin(channel4);
|
|
283756
283802
|
if (!plugin7?.capabilities?.canStreamResponse || !plugin7.createStreamSender) {
|
|
283757
|
-
|
|
283803
|
+
log93.debug("Stream guard: channel does not support streaming", {
|
|
283758
283804
|
channel: channel4,
|
|
283759
283805
|
canStream: plugin7?.capabilities?.canStreamResponse,
|
|
283760
283806
|
chatId
|
|
@@ -283763,7 +283809,7 @@ async function resolveStreamingCapabilities(services, instance4, channel4, chatI
|
|
|
283763
283809
|
}
|
|
283764
283810
|
const streamKey = `${instance4.id}:${chatId}`;
|
|
283765
283811
|
if (activeStreams.has(streamKey)) {
|
|
283766
|
-
|
|
283812
|
+
log93.info("Stream guard: parallel stream blocked, falling back to accumulate", {
|
|
283767
283813
|
instanceId: instance4.id,
|
|
283768
283814
|
chatId,
|
|
283769
283815
|
traceId
|
|
@@ -283786,7 +283832,7 @@ async function consumeStream(generator, sender, instanceId, chatId, traceId) {
|
|
|
283786
283832
|
hadContent = true;
|
|
283787
283833
|
await routeStreamDelta(sender, delta);
|
|
283788
283834
|
}
|
|
283789
|
-
|
|
283835
|
+
log93.info("Streaming response complete", {
|
|
283790
283836
|
instanceId,
|
|
283791
283837
|
chatId,
|
|
283792
283838
|
durationMs: Date.now() - startTime2,
|
|
@@ -283919,7 +283965,7 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
|
|
|
283919
283965
|
}
|
|
283920
283966
|
return streamResult;
|
|
283921
283967
|
} catch (err) {
|
|
283922
|
-
|
|
283968
|
+
log93.error("Streaming dispatch failed, falling back", {
|
|
283923
283969
|
instanceId: instance4.id,
|
|
283924
283970
|
chatId,
|
|
283925
283971
|
error: String(err),
|
|
@@ -284003,7 +284049,7 @@ async function buildContextMessages(services, instance4, chatId, currentMessageI
|
|
|
284003
284049
|
return `[${name}${time3 ? ` - ${time3}` : ""}] ${text3}`;
|
|
284004
284050
|
});
|
|
284005
284051
|
} catch (error2) {
|
|
284006
|
-
|
|
284052
|
+
log93.warn("Failed to build context messages", { error: error2, chatId, instanceId: instance4.id });
|
|
284007
284053
|
return [];
|
|
284008
284054
|
}
|
|
284009
284055
|
}
|
|
@@ -284040,13 +284086,13 @@ async function dispatchViaTurnBasedProvider(services, instance4, provider, trigg
|
|
|
284040
284086
|
agentRecord = row;
|
|
284041
284087
|
}
|
|
284042
284088
|
if (!agentRecord) {
|
|
284043
|
-
|
|
284089
|
+
log93.error("Turn-based dispatch: agent not found", { instanceId: instance4.id, agentId: instance4.agentId });
|
|
284044
284090
|
return false;
|
|
284045
284091
|
}
|
|
284046
284092
|
const keyName = `agent:${agentRecord.name}`;
|
|
284047
284093
|
const scopedKey = await services.apiKeys.findByName(keyName);
|
|
284048
284094
|
if (!scopedKey) {
|
|
284049
|
-
|
|
284095
|
+
log93.error("Turn-based dispatch: scoped API key not found", { keyName, instanceId: instance4.id });
|
|
284050
284096
|
return false;
|
|
284051
284097
|
}
|
|
284052
284098
|
const turn = await services.turns.open({
|
|
@@ -284087,7 +284133,7 @@ async function dispatchViaTurnBasedProvider(services, instance4, provider, trigg
|
|
|
284087
284133
|
attributes: { provider_type: provider.schema, mode: "turn-based" }
|
|
284088
284134
|
});
|
|
284089
284135
|
}
|
|
284090
|
-
|
|
284136
|
+
log93.info("Turn-based dispatch: turn opened", {
|
|
284091
284137
|
turnId: turn.id,
|
|
284092
284138
|
instanceId: instance4.id,
|
|
284093
284139
|
chatId,
|
|
@@ -284103,7 +284149,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
284103
284149
|
return false;
|
|
284104
284150
|
const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
|
|
284105
284151
|
if (!messageTexts.length && !mediaFiles.length) {
|
|
284106
|
-
|
|
284152
|
+
log93.debug("No text or media content for provider trigger, skipping");
|
|
284107
284153
|
return false;
|
|
284108
284154
|
}
|
|
284109
284155
|
if (!messageTexts.length && mediaFiles.length) {
|
|
@@ -284144,12 +284190,12 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
284144
284190
|
recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
|
|
284145
284191
|
await forwardToChainedInstance(instance4, parts, correlationId, messages4);
|
|
284146
284192
|
} else if (handoffTriggered) {
|
|
284147
|
-
|
|
284193
|
+
log93.info("Agent response suppressed \u2014 handoff triggered during run", {
|
|
284148
284194
|
instanceId: instance4.id,
|
|
284149
284195
|
chatId
|
|
284150
284196
|
});
|
|
284151
284197
|
}
|
|
284152
|
-
|
|
284198
|
+
log93.info("Agent response via IAgentProvider", {
|
|
284153
284199
|
instanceId: instance4.id,
|
|
284154
284200
|
chatId,
|
|
284155
284201
|
parts: result?.parts.length ?? 0,
|
|
@@ -284163,14 +284209,14 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
284163
284209
|
async function dispatchViaLegacy(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId) {
|
|
284164
284210
|
const { messageTexts, mediaFiles } = await prepareAgentContent(services, instance4, messages4);
|
|
284165
284211
|
if (perThreadExtraContext?.length) {
|
|
284166
|
-
|
|
284212
|
+
log93.warn("per_thread context available but legacy dispatch path has limited support \u2014 prepending as text", {
|
|
284167
284213
|
instanceId: instance4.id,
|
|
284168
284214
|
contextCount: perThreadExtraContext.length
|
|
284169
284215
|
});
|
|
284170
284216
|
messageTexts.unshift(...perThreadExtraContext);
|
|
284171
284217
|
}
|
|
284172
284218
|
if (!messageTexts.length && !mediaFiles.length) {
|
|
284173
|
-
|
|
284219
|
+
log93.debug("No text or media content in messages, skipping agent call");
|
|
284174
284220
|
return;
|
|
284175
284221
|
}
|
|
284176
284222
|
if (!messageTexts.length && mediaFiles.length) {
|
|
@@ -284204,7 +284250,7 @@ async function dispatchViaLegacy(services, instance4, messages4, triggerType, ch
|
|
|
284204
284250
|
recordJourneyCheckpoint(correlationId, "T8", JOURNEY_STAGES.T8);
|
|
284205
284251
|
await sendResponseParts(channel4, instance4.id, chatId, parts, getSplitDelayConfig(instance4), _fmtMode, replyTo, correlationId, senderAgentId);
|
|
284206
284252
|
recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
|
|
284207
|
-
|
|
284253
|
+
log93.info("Agent response via legacy runner", {
|
|
284208
284254
|
instanceId: instance4.id,
|
|
284209
284255
|
chatId,
|
|
284210
284256
|
parts: result.parts.length,
|
|
@@ -284224,14 +284270,14 @@ async function performSessionReset(instance4, sessionId, chatId, services, db2,
|
|
|
284224
284270
|
sessionActuallyReset = true;
|
|
284225
284271
|
}
|
|
284226
284272
|
} catch (err) {
|
|
284227
|
-
|
|
284273
|
+
log93.warn("Failed to reset provider session", { error: String(err), instanceId: instance4.id, sessionId });
|
|
284228
284274
|
}
|
|
284229
284275
|
if (sessionActuallyReset) {
|
|
284230
284276
|
sessionActivityStore.recordReset(instance4.id, sessionId, Date.now());
|
|
284231
284277
|
eventBus.publish("session.reset", { instanceId: instance4.id, sessionId, timestamp: Date.now() }, { instanceId: instance4.id, channelType: channel4 }).catch((err) => {
|
|
284232
|
-
|
|
284278
|
+
log93.warn("Failed to publish session.reset event", { error: String(err), instanceId: instance4.id, sessionId });
|
|
284233
284279
|
});
|
|
284234
|
-
|
|
284280
|
+
log93.info("Session reset triggered", {
|
|
284235
284281
|
instanceId: instance4.id,
|
|
284236
284282
|
sessionId,
|
|
284237
284283
|
strategy: resetStrategy,
|
|
@@ -284274,7 +284320,7 @@ async function markPerThreadSessionInitialized(db2, instanceId, sessionId) {
|
|
|
284274
284320
|
target: [agentSessions.instanceId, agentSessions.sessionKey],
|
|
284275
284321
|
set: { lastUsedAt: now, updatedAt: now }
|
|
284276
284322
|
});
|
|
284277
|
-
|
|
284323
|
+
log93.info("per_thread session initialized", { instanceId, sessionId });
|
|
284278
284324
|
}
|
|
284279
284325
|
function mimeToContentType(mimeType) {
|
|
284280
284326
|
if (mimeType.startsWith("audio/"))
|
|
@@ -284313,7 +284359,7 @@ async function processMediaFile(msg, mimeType, mediaService) {
|
|
|
284313
284359
|
const result = await mediaService.process(localPath, mimeType, { caption: msg.content.caption });
|
|
284314
284360
|
return result.success && result.content ? result.content : null;
|
|
284315
284361
|
} catch (err) {
|
|
284316
|
-
|
|
284362
|
+
log93.debug("Media processing failed for history message", { error: String(err), messageId: msg.externalId });
|
|
284317
284363
|
return null;
|
|
284318
284364
|
} finally {
|
|
284319
284365
|
if (ownedTempFile) {
|
|
@@ -284350,7 +284396,7 @@ async function processHistoryMessage2(msg, mediaService, reactFn, unreactFn) {
|
|
|
284350
284396
|
async function fetchAndProcessThreadHistory(services, instance4, channel4, chatId, threadId2) {
|
|
284351
284397
|
const plugin7 = await getPlugin(channel4);
|
|
284352
284398
|
if (!plugin7?.fetchHistory) {
|
|
284353
|
-
|
|
284399
|
+
log93.debug("Channel plugin does not support fetchHistory", { instanceId: instance4.id, channel: channel4 });
|
|
284354
284400
|
return [];
|
|
284355
284401
|
}
|
|
284356
284402
|
let historyResult;
|
|
@@ -284361,7 +284407,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
284361
284407
|
limit: 200
|
|
284362
284408
|
});
|
|
284363
284409
|
} catch (err) {
|
|
284364
|
-
|
|
284410
|
+
log93.warn("fetchHistory failed, proceeding without thread context", {
|
|
284365
284411
|
error: String(err),
|
|
284366
284412
|
instanceId: instance4.id,
|
|
284367
284413
|
channel: channel4
|
|
@@ -284391,7 +284437,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
284391
284437
|
const results = await Promise.all(batch.map((msg) => processHistoryMessage2(msg, mediaService, reactFn, unreactFn)));
|
|
284392
284438
|
contextMessages.push(...results);
|
|
284393
284439
|
}
|
|
284394
|
-
|
|
284440
|
+
log93.info("Thread history fetched", {
|
|
284395
284441
|
instanceId: instance4.id,
|
|
284396
284442
|
channel: channel4,
|
|
284397
284443
|
chatId,
|
|
@@ -284402,7 +284448,7 @@ async function fetchAndProcessThreadHistory(services, instance4, channel4, chatI
|
|
|
284402
284448
|
return contextMessages;
|
|
284403
284449
|
}
|
|
284404
284450
|
async function handlePerThreadLazyInit(services, instance4, channel4, chatId, threadId2, sessionId, db2) {
|
|
284405
|
-
|
|
284451
|
+
log93.info("per_thread lazy init", {
|
|
284406
284452
|
instanceId: instance4.id,
|
|
284407
284453
|
channel: channel4,
|
|
284408
284454
|
chatId,
|
|
@@ -284413,7 +284459,7 @@ async function handlePerThreadLazyInit(services, instance4, channel4, chatId, th
|
|
|
284413
284459
|
try {
|
|
284414
284460
|
await markPerThreadSessionInitialized(db2, instance4.id, sessionId);
|
|
284415
284461
|
} catch (err) {
|
|
284416
|
-
|
|
284462
|
+
log93.warn("Failed to mark per_thread session initialized", {
|
|
284417
284463
|
error: String(err),
|
|
284418
284464
|
instanceId: instance4.id,
|
|
284419
284465
|
sessionId
|
|
@@ -284455,7 +284501,7 @@ async function dispatchToAgent(services, instance4, msgs, triggerType, channel4,
|
|
|
284455
284501
|
handled = await dispatchViaProvider(services, instance4, msgs, triggerType, channel4, chatId, senderId, personId, senderName, traceId, rawEvent, db2, perThreadExtraContext, senderAgentId);
|
|
284456
284502
|
}
|
|
284457
284503
|
} catch (providerError) {
|
|
284458
|
-
|
|
284504
|
+
log93.error("Provider dispatch failed, falling back to legacy", {
|
|
284459
284505
|
instanceId: instance4.id,
|
|
284460
284506
|
chatId,
|
|
284461
284507
|
error: String(providerError),
|
|
@@ -284464,7 +284510,7 @@ async function dispatchToAgent(services, instance4, msgs, triggerType, channel4,
|
|
|
284464
284510
|
}
|
|
284465
284511
|
if (handled)
|
|
284466
284512
|
return;
|
|
284467
|
-
|
|
284513
|
+
log93.debug("No IAgentProvider resolved or provider failed, using legacy agentRunner path", {
|
|
284468
284514
|
instanceId: instance4.id
|
|
284469
284515
|
});
|
|
284470
284516
|
await dispatchViaLegacy(services, instance4, msgs, triggerType, channel4, chatId, senderId, personId, senderName, traceId, perThreadExtraContext, senderAgentId);
|
|
@@ -284483,7 +284529,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
284483
284529
|
const ackHandle = startAck(plugin7, ackProvider, instance4.id, chatId, messageId, channel4, buildAckConfig(instance4));
|
|
284484
284530
|
const personId = await resolvePersonId(services, channel4, instance4.id, senderId, firstMessage.metadata.personId);
|
|
284485
284531
|
if (!personId) {
|
|
284486
|
-
|
|
284532
|
+
log93.warn("Could not resolve person ID, skipping agent", { instanceId: instance4.id, chatId, senderId });
|
|
284487
284533
|
ackHandle.remove();
|
|
284488
284534
|
return;
|
|
284489
284535
|
}
|
|
@@ -284491,7 +284537,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
284491
284537
|
const chatSettings = chatRecord?.settings;
|
|
284492
284538
|
const isAgentPaused = chatSettings?.agentPaused === true;
|
|
284493
284539
|
if (isAgentPaused) {
|
|
284494
|
-
|
|
284540
|
+
log93.debug("Agent paused (handoff active), skipping dispatch", { instanceId: instance4.id, chatId });
|
|
284495
284541
|
ackHandle.remove();
|
|
284496
284542
|
return;
|
|
284497
284543
|
}
|
|
@@ -284499,7 +284545,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
284499
284545
|
const resumedAt = new Date(chatSettings.agentResumedAt).getTime();
|
|
284500
284546
|
const msgTimestamp = extractPlatformTimestamp(firstMessage.payload.rawPayload, Date.now()).getTime();
|
|
284501
284547
|
if (msgTimestamp < resumedAt) {
|
|
284502
|
-
|
|
284548
|
+
log93.debug("Dropping pre-resume message (arrived during handoff window)", {
|
|
284503
284549
|
instanceId: instance4.id,
|
|
284504
284550
|
chatId,
|
|
284505
284551
|
msgTimestamp: new Date(msgTimestamp).toISOString(),
|
|
@@ -284514,7 +284560,7 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
284514
284560
|
const pushName = rawPayload.pushName ?? rawPayload.displayName ?? rawPayload.senderobj?.display ?? rawPayload.contextobj?.senderName;
|
|
284515
284561
|
const senderName = await services.agentRunner.getSenderName(personId, pushName);
|
|
284516
284562
|
const senderAgentId = await resolveDispatchSenderAgentId(db2, instance4);
|
|
284517
|
-
|
|
284563
|
+
log93.info("Dispatching to agent", {
|
|
284518
284564
|
instanceId: instance4.id,
|
|
284519
284565
|
chatId,
|
|
284520
284566
|
messageCount: messages4.length,
|
|
@@ -284528,14 +284574,14 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
|
|
|
284528
284574
|
const agentAckMessage = inst.agentAckMessage ?? null;
|
|
284529
284575
|
if (agentAckMessage) {
|
|
284530
284576
|
sendTextMessage5(channel4, instance4.id, chatId, agentAckMessage).catch((err) => {
|
|
284531
|
-
|
|
284577
|
+
log93.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
|
|
284532
284578
|
});
|
|
284533
284579
|
}
|
|
284534
284580
|
const perThreadExtraContext = await resolvePerThreadExtraContext(db2, services, instance4, channel4, chatId, senderId, firstMessage);
|
|
284535
284581
|
try {
|
|
284536
284582
|
await runWithTransientDispatchRetry(() => dispatchToAgent(services, instance4, messages4, triggerType, channel4, chatId, senderId, personId, senderName, traceId, senderAgentId, perThreadExtraContext, db2), { instanceId: instance4.id, chatId, traceId });
|
|
284537
284583
|
} catch (error2) {
|
|
284538
|
-
|
|
284584
|
+
log93.error("agent_dispatch_failed_after_retries", {
|
|
284539
284585
|
instanceId: instance4.id,
|
|
284540
284586
|
chatId,
|
|
284541
284587
|
error: String(error2),
|
|
@@ -284588,7 +284634,7 @@ function createOpenClawProviderInstance(provider, instance4) {
|
|
|
284588
284634
|
}
|
|
284589
284635
|
function createAgnoProvider(provider, instance4) {
|
|
284590
284636
|
if (!provider.apiKey) {
|
|
284591
|
-
|
|
284637
|
+
log93.warn("Provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
284592
284638
|
return null;
|
|
284593
284639
|
}
|
|
284594
284640
|
const client = createProviderClient({
|
|
@@ -284610,7 +284656,7 @@ function createClaudeCodeProviderInstance(provider, instance4, db2) {
|
|
|
284610
284656
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
284611
284657
|
const projectPath = schemaConfig.projectPath;
|
|
284612
284658
|
if (!projectPath) {
|
|
284613
|
-
|
|
284659
|
+
log93.error("Claude Code provider missing projectPath", { providerId: provider.id });
|
|
284614
284660
|
throw new Error("Claude Code provider requires schemaConfig.projectPath");
|
|
284615
284661
|
}
|
|
284616
284662
|
return new ClaudeCodeAgentProvider(provider.id, provider.name, {
|
|
@@ -284641,7 +284687,7 @@ function createWebhookProvider(provider) {
|
|
|
284641
284687
|
}
|
|
284642
284688
|
function createAgUiProviderInstance(provider, instance4) {
|
|
284643
284689
|
if (!provider.apiKey) {
|
|
284644
|
-
|
|
284690
|
+
log93.warn("AG-UI provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
284645
284691
|
return null;
|
|
284646
284692
|
}
|
|
284647
284693
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
@@ -284660,7 +284706,7 @@ function createAgUiProviderInstance(provider, instance4) {
|
|
|
284660
284706
|
}
|
|
284661
284707
|
function createA2AProviderInstance(provider, instance4) {
|
|
284662
284708
|
if (!provider.apiKey) {
|
|
284663
|
-
|
|
284709
|
+
log93.warn("A2A provider has no API key, falling back to legacy path", { providerId: provider.id });
|
|
284664
284710
|
return null;
|
|
284665
284711
|
}
|
|
284666
284712
|
const schemaConfig = provider.schemaConfig ?? {};
|
|
@@ -284681,7 +284727,7 @@ function createNatsGenieProviderInstance(provider, instance4) {
|
|
|
284681
284727
|
const schemaConfig = typeof provider.schemaConfig === "object" && provider.schemaConfig !== null ? provider.schemaConfig : {};
|
|
284682
284728
|
const agentName = typeof schemaConfig.agentName === "string" ? schemaConfig.agentName : "";
|
|
284683
284729
|
if (!agentName) {
|
|
284684
|
-
|
|
284730
|
+
log93.error("NATS Genie provider missing agentName in schemaConfig", { providerId: provider.id });
|
|
284685
284731
|
return null;
|
|
284686
284732
|
}
|
|
284687
284733
|
const natsUrl = typeof schemaConfig.natsUrl === "string" ? schemaConfig.natsUrl : "localhost:4222";
|
|
@@ -284698,7 +284744,7 @@ function createNatsGenieProviderInstance(provider, instance4) {
|
|
|
284698
284744
|
try {
|
|
284699
284745
|
await sendTextMessage5(channel4, instance4.id, chatId, content);
|
|
284700
284746
|
} catch (error2) {
|
|
284701
|
-
|
|
284747
|
+
log93.error("Failed to deliver agent reply", {
|
|
284702
284748
|
chatId,
|
|
284703
284749
|
instanceId: instance4.id,
|
|
284704
284750
|
providerId: provider.id,
|
|
@@ -284711,11 +284757,11 @@ function createNatsGenieProviderInstance(provider, instance4) {
|
|
|
284711
284757
|
const startWithRetry = async (attempt = 1) => {
|
|
284712
284758
|
try {
|
|
284713
284759
|
await natsProvider.startReplySubscription();
|
|
284714
|
-
|
|
284760
|
+
log93.info("NATS reply subscription started", { instanceId: instance4.id, attempt });
|
|
284715
284761
|
} catch (err) {
|
|
284716
284762
|
const delay2 = Math.min(2000 * 2 ** (attempt - 1), 60000);
|
|
284717
284763
|
if (attempt < 10) {
|
|
284718
|
-
|
|
284764
|
+
log93.warn("NATS reply subscription failed, retrying", {
|
|
284719
284765
|
instanceId: instance4.id,
|
|
284720
284766
|
providerId: provider.id,
|
|
284721
284767
|
attempt,
|
|
@@ -284724,7 +284770,7 @@ function createNatsGenieProviderInstance(provider, instance4) {
|
|
|
284724
284770
|
});
|
|
284725
284771
|
setTimeout(() => startWithRetry(attempt + 1), delay2);
|
|
284726
284772
|
} else {
|
|
284727
|
-
|
|
284773
|
+
log93.error("NATS reply subscription permanently failed", {
|
|
284728
284774
|
instanceId: instance4.id,
|
|
284729
284775
|
providerId: provider.id,
|
|
284730
284776
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -284764,7 +284810,7 @@ function resolveProvider(provider, instance4, db2) {
|
|
|
284764
284810
|
agentProvider = createNatsGenieProviderInstance(provider, instance4);
|
|
284765
284811
|
break;
|
|
284766
284812
|
default:
|
|
284767
|
-
|
|
284813
|
+
log93.debug("Provider schema not supported for IAgentProvider dispatch", {
|
|
284768
284814
|
schema: provider.schema,
|
|
284769
284815
|
providerId: provider.id
|
|
284770
284816
|
});
|
|
@@ -284785,7 +284831,7 @@ function invalidateProviderCache(providerId) {
|
|
|
284785
284831
|
removed++;
|
|
284786
284832
|
if (provider.dispose) {
|
|
284787
284833
|
provider.dispose().catch((err) => {
|
|
284788
|
-
|
|
284834
|
+
log93.warn("Error disposing provider on cache invalidation", { key, error: String(err) });
|
|
284789
284835
|
});
|
|
284790
284836
|
}
|
|
284791
284837
|
}
|
|
@@ -284794,14 +284840,14 @@ function invalidateProviderCache(providerId) {
|
|
|
284794
284840
|
try {
|
|
284795
284841
|
openclawClient.stop();
|
|
284796
284842
|
} catch (err) {
|
|
284797
|
-
|
|
284843
|
+
log93.warn("Error stopping OpenClaw client on cache invalidation", {
|
|
284798
284844
|
providerId,
|
|
284799
284845
|
error: String(err)
|
|
284800
284846
|
});
|
|
284801
284847
|
}
|
|
284802
284848
|
openclawClientPool.delete(providerId);
|
|
284803
284849
|
}
|
|
284804
|
-
|
|
284850
|
+
log93.debug("Provider cache invalidated", { providerId, removed });
|
|
284805
284851
|
}
|
|
284806
284852
|
async function getAgentProvider(services, instance4, db2) {
|
|
284807
284853
|
if (!instance4.agentProviderId)
|
|
@@ -284812,7 +284858,7 @@ async function getAgentProvider(services, instance4, db2) {
|
|
|
284812
284858
|
return null;
|
|
284813
284859
|
return resolveProvider(provider, instance4, db2);
|
|
284814
284860
|
} catch (error2) {
|
|
284815
|
-
|
|
284861
|
+
log93.warn("Failed to resolve agent provider, falling back to legacy", {
|
|
284816
284862
|
instanceId: instance4.id,
|
|
284817
284863
|
providerId: instance4.agentProviderId,
|
|
284818
284864
|
error: String(error2)
|
|
@@ -284876,7 +284922,7 @@ async function applyInstanceFkAndReturn(db2, instance4) {
|
|
|
284876
284922
|
}
|
|
284877
284923
|
async function resolveEffectiveInstance(services, db2, instance4, chatId, personId) {
|
|
284878
284924
|
if (!chatId) {
|
|
284879
|
-
|
|
284925
|
+
log93.debug("No internal chatId \u2014 using instance default agent", { instanceId: instance4.id, personId });
|
|
284880
284926
|
return applyInstanceFkAndReturn(db2, instance4);
|
|
284881
284927
|
}
|
|
284882
284928
|
const route = await services.routeResolver.resolve(instance4.id, chatId, personId);
|
|
@@ -284888,7 +284934,7 @@ async function resolveEffectiveInstance(services, db2, instance4, chatId, person
|
|
|
284888
284934
|
if (effectiveAgentFkId) {
|
|
284889
284935
|
await applyAgentFkOverrides(db2, effectiveAgentFkId, effectiveInstance);
|
|
284890
284936
|
}
|
|
284891
|
-
|
|
284937
|
+
log93.debug("Route resolved and merged", {
|
|
284892
284938
|
instanceId: instance4.id,
|
|
284893
284939
|
chatId,
|
|
284894
284940
|
personId,
|
|
@@ -284909,7 +284955,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
284909
284955
|
const internalChatId = chat2?.id;
|
|
284910
284956
|
const reactionPersonId = await resolvePersonId(services, channel4, baseInstance.id, payload.from, metadata.personId);
|
|
284911
284957
|
const { instance: instance4, routeId: _routeId } = await resolveEffectiveInstance(services, db2, baseInstance, internalChatId, reactionPersonId);
|
|
284912
|
-
|
|
284958
|
+
log93.info("Dispatching reaction trigger", {
|
|
284913
284959
|
instanceId: instance4.id,
|
|
284914
284960
|
chatId: externalChatId,
|
|
284915
284961
|
routeChatId: internalChatId ?? "none",
|
|
@@ -284950,7 +284996,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
284950
284996
|
const _fmtMode = instance4.messageFormatMode ?? "convert";
|
|
284951
284997
|
await sendResponseParts(channel4, instance4.id, externalChatId, result2.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
|
|
284952
284998
|
}
|
|
284953
|
-
|
|
284999
|
+
log93.info("Reaction trigger response via provider", {
|
|
284954
285000
|
instanceId: instance4.id,
|
|
284955
285001
|
chatId: externalChatId,
|
|
284956
285002
|
routeChatId: internalChatId,
|
|
@@ -284962,7 +285008,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
284962
285008
|
});
|
|
284963
285009
|
return;
|
|
284964
285010
|
}
|
|
284965
|
-
|
|
285011
|
+
log93.debug("No IAgentProvider resolved, using legacy agentRunner path", {
|
|
284966
285012
|
instanceId: instance4.id
|
|
284967
285013
|
});
|
|
284968
285014
|
const personId = await resolvePersonId(services, channel4, instance4.id, payload.from, metadata.personId);
|
|
@@ -284988,7 +285034,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
284988
285034
|
const _fmtMode = instance4.messageFormatMode ?? "convert";
|
|
284989
285035
|
await sendResponseParts(channel4, instance4.id, externalChatId, result.parts, getSplitDelayConfig(instance4), _fmtMode, payload.messageId);
|
|
284990
285036
|
}
|
|
284991
|
-
|
|
285037
|
+
log93.info("Reaction trigger response via legacy runner", {
|
|
284992
285038
|
instanceId: instance4.id,
|
|
284993
285039
|
chatId: externalChatId,
|
|
284994
285040
|
routeChatId: internalChatId,
|
|
@@ -284997,7 +285043,7 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
|
|
|
284997
285043
|
traceId: metadata.traceId
|
|
284998
285044
|
});
|
|
284999
285045
|
} catch (error2) {
|
|
285000
|
-
|
|
285046
|
+
log93.error("Failed to process reaction trigger", {
|
|
285001
285047
|
instanceId: instance4.id,
|
|
285002
285048
|
chatId: externalChatId,
|
|
285003
285049
|
routeChatId: internalChatId,
|
|
@@ -285032,7 +285078,7 @@ function isTrashEmojiOnly(text3) {
|
|
|
285032
285078
|
}
|
|
285033
285079
|
async function isLidMatchingOwner(chatsService, instanceId, ownerIdentifier, ownerPhone, ownerIsLid, lidJid) {
|
|
285034
285080
|
if (ownerIsLid && extractPhoneFromJid(lidJid) === ownerPhone) {
|
|
285035
|
-
|
|
285081
|
+
log93.debug("LID mention matches owner LID directly", { lidJid, ownerIdentifier });
|
|
285036
285082
|
return true;
|
|
285037
285083
|
}
|
|
285038
285084
|
try {
|
|
@@ -285041,13 +285087,13 @@ async function isLidMatchingOwner(chatsService, instanceId, ownerIdentifier, own
|
|
|
285041
285087
|
return false;
|
|
285042
285088
|
const resolvedPhone = extractPhoneFromJid(mapping);
|
|
285043
285089
|
if (resolvedPhone === ownerPhone) {
|
|
285044
|
-
|
|
285090
|
+
log93.debug("LID resolved to instance owner via DB", { lidJid, resolvedPhone, ownerPhone });
|
|
285045
285091
|
return true;
|
|
285046
285092
|
}
|
|
285047
285093
|
if (ownerIsLid) {
|
|
285048
285094
|
const ownerMapping = await chatsService.findLidMapping(instanceId, ownerIdentifier);
|
|
285049
285095
|
if (ownerMapping && extractPhoneFromJid(ownerMapping) === resolvedPhone) {
|
|
285050
|
-
|
|
285096
|
+
log93.debug("LID resolved to owner via reverse mapping", { lidJid, resolvedPhone, ownerIdentifier });
|
|
285051
285097
|
return true;
|
|
285052
285098
|
}
|
|
285053
285099
|
}
|
|
@@ -285102,15 +285148,15 @@ function isInboundTooStale(rawPayload, maxAgeMinutes, now = Date.now()) {
|
|
|
285102
285148
|
}
|
|
285103
285149
|
async function shouldProcessMessage3(agentRunner, accessService, chatsService, messagesService, routeResolver, payload, metadata) {
|
|
285104
285150
|
if (!metadata.instanceId) {
|
|
285105
|
-
|
|
285151
|
+
log93.debug("No instanceId in metadata", { from: payload.from, chatId: payload.chatId });
|
|
285106
285152
|
return null;
|
|
285107
285153
|
}
|
|
285108
285154
|
if (payload.from === metadata.platformIdentityId) {
|
|
285109
|
-
|
|
285155
|
+
log93.debug("Message from self, skipping", { instanceId: metadata.instanceId, from: payload.from });
|
|
285110
285156
|
return null;
|
|
285111
285157
|
}
|
|
285112
285158
|
if (isTrashEmojiOnly(payload.content?.text)) {
|
|
285113
|
-
|
|
285159
|
+
log93.debug("Skipping trash emoji message (session-cleaner handles this)", {
|
|
285114
285160
|
instanceId: metadata.instanceId,
|
|
285115
285161
|
chatId: payload.chatId
|
|
285116
285162
|
});
|
|
@@ -285118,17 +285164,17 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
285118
285164
|
}
|
|
285119
285165
|
const chatId = payload.chatId ?? "";
|
|
285120
285166
|
if (isBroadcastOrNewsletter(chatId)) {
|
|
285121
|
-
|
|
285167
|
+
log93.debug("Skipping newsletter/broadcast message", { instanceId: metadata.instanceId, chatId });
|
|
285122
285168
|
return null;
|
|
285123
285169
|
}
|
|
285124
285170
|
const instance4 = await agentRunner.getInstanceWithProvider(metadata.instanceId);
|
|
285125
285171
|
if (!instance4?.agentId) {
|
|
285126
|
-
|
|
285172
|
+
log93.debug("Instance has no agentId", { instanceId: metadata.instanceId });
|
|
285127
285173
|
return null;
|
|
285128
285174
|
}
|
|
285129
285175
|
const staleness = isInboundTooStale(payload.rawPayload, instance4.inboundMaxAgeMinutes);
|
|
285130
285176
|
if (staleness.stale) {
|
|
285131
|
-
|
|
285177
|
+
log93.warn("Dropping stale inbound message", {
|
|
285132
285178
|
instanceId: instance4.id,
|
|
285133
285179
|
chatId: payload.chatId,
|
|
285134
285180
|
externalId: payload.externalId,
|
|
@@ -285139,7 +285185,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
285139
285185
|
return null;
|
|
285140
285186
|
}
|
|
285141
285187
|
if (!instanceTriggersOnEvent(instance4, "message.received")) {
|
|
285142
|
-
|
|
285188
|
+
log93.debug("Instance does not trigger on message.received", { instanceId: instance4.id });
|
|
285143
285189
|
return null;
|
|
285144
285190
|
}
|
|
285145
285191
|
const messageContext = buildMessageContext(payload, instance4);
|
|
@@ -285149,7 +285195,7 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
285149
285195
|
await resolveLidMentionBot(chatsService, metadata.instanceId, instance4.ownerIdentifier, mentionedJids, messageContext);
|
|
285150
285196
|
}
|
|
285151
285197
|
await resolveSlackThreadReply(chatsService, messagesService, instance4, payload, messageContext);
|
|
285152
|
-
|
|
285198
|
+
log93.debug("Message context built", {
|
|
285153
285199
|
instanceId: instance4.id,
|
|
285154
285200
|
chatId: payload.chatId,
|
|
285155
285201
|
isDirectMessage: messageContext.isDirectMessage,
|
|
@@ -285160,12 +285206,12 @@ async function shouldProcessMessage3(agentRunner, accessService, chatsService, m
|
|
|
285160
285206
|
const effectiveReplyFilter = await resolveEffectiveReplyFilter(chatsService, routeResolver, instance4.id, payload.chatId, instance4.agentReplyFilter);
|
|
285161
285207
|
if (!effectiveReplyFilter && !nullFilterWarnedInstances.has(instance4.id)) {
|
|
285162
285208
|
nullFilterWarnedInstances.add(instance4.id);
|
|
285163
|
-
|
|
285209
|
+
log93.warn("instance has no agent_reply_filter configured \u2014 allowing all inbound messages", {
|
|
285164
285210
|
instanceId: instance4.id
|
|
285165
285211
|
});
|
|
285166
285212
|
}
|
|
285167
285213
|
if (!shouldAgentReply(effectiveReplyFilter, messageContext)) {
|
|
285168
|
-
|
|
285214
|
+
log93.info("Message did not pass reply filter", {
|
|
285169
285215
|
instanceId: instance4.id,
|
|
285170
285216
|
chatId: payload.chatId,
|
|
285171
285217
|
messageContext,
|
|
@@ -285189,7 +285235,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
285189
285235
|
const primaryId = payload.from ?? "";
|
|
285190
285236
|
let accessResult = await accessService.checkAccess(instance4, primaryId, channel4);
|
|
285191
285237
|
if (!accessResult.allowed && participantAlt && participantAlt !== primaryId) {
|
|
285192
|
-
|
|
285238
|
+
log93.warn("Access fallback to participantAlt", {
|
|
285193
285239
|
instanceId: instance4.id,
|
|
285194
285240
|
primaryId,
|
|
285195
285241
|
participantAlt,
|
|
@@ -285198,7 +285244,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
285198
285244
|
accessResult = await accessService.checkAccess(instance4, participantAlt, channel4);
|
|
285199
285245
|
}
|
|
285200
285246
|
if (!accessResult.allowed && resolvedSenderPhone && resolvedSenderPhone !== primaryId && resolvedSenderPhone !== participantAlt) {
|
|
285201
|
-
|
|
285247
|
+
log93.debug("Access fallback to resolvedSenderPhone (LID\u2192phone)", {
|
|
285202
285248
|
instanceId: instance4.id,
|
|
285203
285249
|
primaryId,
|
|
285204
285250
|
resolvedSenderPhone,
|
|
@@ -285208,7 +285254,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
285208
285254
|
}
|
|
285209
285255
|
if (accessResult.allowed)
|
|
285210
285256
|
return false;
|
|
285211
|
-
|
|
285257
|
+
log93.info("Access denied", {
|
|
285212
285258
|
instanceId: instance4.id,
|
|
285213
285259
|
chatId: payload.chatId,
|
|
285214
285260
|
from: payload.from,
|
|
@@ -285217,7 +285263,7 @@ async function checkAccessWithFallback(accessService, instance4, payload, channe
|
|
|
285217
285263
|
});
|
|
285218
285264
|
if (accessResult.mode === "allowlist" && !accessResult.rule && primaryId) {
|
|
285219
285265
|
accessService.requestPairing(instance4.id, primaryId, { channelType: instance4.channel }).catch((err) => {
|
|
285220
|
-
|
|
285266
|
+
log93.warn("Failed to create pairing request", { instanceId: instance4.id, from: primaryId, error: String(err) });
|
|
285221
285267
|
});
|
|
285222
285268
|
}
|
|
285223
285269
|
if (accessResult.rule?.action !== "silent_block" && accessResult.rule?.blockMessage) {
|
|
@@ -285234,7 +285280,7 @@ async function shouldProcessReaction(agentRunner, accessService, reactionDedup,
|
|
|
285234
285280
|
if (!instanceTriggersOnEvent(instance4, eventType))
|
|
285235
285281
|
return null;
|
|
285236
285282
|
if (!isReactionTrigger(instance4, payload.emoji)) {
|
|
285237
|
-
|
|
285283
|
+
log93.debug("Reaction emoji not in trigger list", { instanceId: instance4.id, emoji: payload.emoji });
|
|
285238
285284
|
return null;
|
|
285239
285285
|
}
|
|
285240
285286
|
const channel4 = metadata.channelType ?? instance4.channel;
|
|
@@ -285242,7 +285288,7 @@ async function shouldProcessReaction(agentRunner, accessService, reactionDedup,
|
|
|
285242
285288
|
if (accessDenied)
|
|
285243
285289
|
return null;
|
|
285244
285290
|
if (reactionDedup.isDuplicate(payload.messageId, payload.emoji, payload.from)) {
|
|
285245
|
-
|
|
285291
|
+
log93.debug("Duplicate reaction, skipping", {
|
|
285246
285292
|
instanceId: instance4.id,
|
|
285247
285293
|
messageId: payload.messageId,
|
|
285248
285294
|
emoji: payload.emoji
|
|
@@ -285275,7 +285321,7 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
285275
285321
|
try {
|
|
285276
285322
|
const apiKey = await settings.getSecret("gemini.api_key", "GEMINI_API_KEY");
|
|
285277
285323
|
if (!apiKey) {
|
|
285278
|
-
|
|
285324
|
+
log93.warn("Gate: no Gemini API key, fail-open", { traceId });
|
|
285279
285325
|
return true;
|
|
285280
285326
|
}
|
|
285281
285327
|
const controller = new AbortController;
|
|
@@ -285293,13 +285339,13 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
285293
285339
|
});
|
|
285294
285340
|
clearTimeout(timeout);
|
|
285295
285341
|
if (!res.ok) {
|
|
285296
|
-
|
|
285342
|
+
log93.warn("Gate: API error, fail-open", { traceId, status: res.status, durationMs: Date.now() - startMs });
|
|
285297
285343
|
return true;
|
|
285298
285344
|
}
|
|
285299
285345
|
const data = await res.json();
|
|
285300
285346
|
const answer = data.candidates?.[0]?.content?.parts?.[0]?.text?.trim().toLowerCase() ?? "";
|
|
285301
285347
|
const shouldRespond = !answer.startsWith("skip");
|
|
285302
|
-
|
|
285348
|
+
log93.info("Gate decision", {
|
|
285303
285349
|
traceId,
|
|
285304
285350
|
decision: shouldRespond ? "respond" : "skip",
|
|
285305
285351
|
rawAnswer: answer,
|
|
@@ -285313,14 +285359,14 @@ async function shouldRespondViaGate(instance4, messages4, chatType, settings) {
|
|
|
285313
285359
|
clearTimeout(timeout);
|
|
285314
285360
|
const errName = fetchError.name;
|
|
285315
285361
|
if (errName === "AbortError") {
|
|
285316
|
-
|
|
285362
|
+
log93.warn("Gate: timeout, fail-open", { traceId, durationMs: Date.now() - startMs });
|
|
285317
285363
|
} else {
|
|
285318
|
-
|
|
285364
|
+
log93.warn("Gate: fetch error, fail-open", { traceId, error: String(fetchError) });
|
|
285319
285365
|
}
|
|
285320
285366
|
return true;
|
|
285321
285367
|
}
|
|
285322
285368
|
} catch (error2) {
|
|
285323
|
-
|
|
285369
|
+
log93.warn("Gate: unexpected error, fail-open", { traceId, error: String(error2) });
|
|
285324
285370
|
return true;
|
|
285325
285371
|
}
|
|
285326
285372
|
}
|
|
@@ -285330,7 +285376,7 @@ async function shouldSkipViaGate(triggerType, firstMsg, instance4, messages4, se
|
|
|
285330
285376
|
const chatType = determineChatType(firstMsg.payload.chatId, firstMsg.metadata.channelType ?? instance4.channel, firstMsg.payload.rawPayload ?? {});
|
|
285331
285377
|
const shouldRespond = await shouldRespondViaGate(instance4, messages4, chatType, services.settings);
|
|
285332
285378
|
if (!shouldRespond) {
|
|
285333
|
-
|
|
285379
|
+
log93.info("Gate skipped response", {
|
|
285334
285380
|
instanceId: instance4.id,
|
|
285335
285381
|
chatId: firstMsg.payload.chatId,
|
|
285336
285382
|
triggerType,
|
|
@@ -285349,7 +285395,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285349
285395
|
const leakThreshold = 10 * 60000;
|
|
285350
285396
|
for (const [mediaId, pending] of mediaCompletions.entries()) {
|
|
285351
285397
|
if (now - pending.createdAt > leakThreshold) {
|
|
285352
|
-
|
|
285398
|
+
log93.warn("media_promise_leaked", { mediaId, ageMs: now - pending.createdAt });
|
|
285353
285399
|
pending.reject(new Error("media processing promise leaked (10min circuit breaker)"));
|
|
285354
285400
|
mediaCompletions.delete(mediaId);
|
|
285355
285401
|
}
|
|
@@ -285366,7 +285412,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285366
285412
|
} else {
|
|
285367
285413
|
const baseInstance = await agentRunner.getInstanceWithProvider(instanceId);
|
|
285368
285414
|
if (!baseInstance) {
|
|
285369
|
-
|
|
285415
|
+
log93.warn("Instance not found for debounced messages", { instanceId });
|
|
285370
285416
|
return;
|
|
285371
285417
|
}
|
|
285372
285418
|
const externalChatId = firstMsg.payload.chatId;
|
|
@@ -285421,7 +285467,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285421
285467
|
timestamp: event.timestamp
|
|
285422
285468
|
}, effectiveDebounceConfig);
|
|
285423
285469
|
} catch (error2) {
|
|
285424
|
-
|
|
285470
|
+
log93.error("Error processing message for dispatch", {
|
|
285425
285471
|
instanceId: metadata.instanceId,
|
|
285426
285472
|
error: String(error2)
|
|
285427
285473
|
});
|
|
@@ -285452,7 +285498,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285452
285498
|
traceId
|
|
285453
285499
|
}, event, db2);
|
|
285454
285500
|
} catch (error2) {
|
|
285455
|
-
|
|
285501
|
+
log93.error("Error processing reaction for dispatch", {
|
|
285456
285502
|
instanceId: metadata.instanceId,
|
|
285457
285503
|
error: String(error2)
|
|
285458
285504
|
});
|
|
@@ -285483,7 +285529,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285483
285529
|
traceId
|
|
285484
285530
|
}, event, db2);
|
|
285485
285531
|
} catch (error2) {
|
|
285486
|
-
|
|
285532
|
+
log93.error("Error processing reaction removal for dispatch", {
|
|
285487
285533
|
instanceId: metadata.instanceId,
|
|
285488
285534
|
error: String(error2)
|
|
285489
285535
|
});
|
|
@@ -285515,7 +285561,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285515
285561
|
debouncer.onUserTyping(metadata.instanceId, payload.chatId, debounceConfig);
|
|
285516
285562
|
}
|
|
285517
285563
|
} catch (error2) {
|
|
285518
|
-
|
|
285564
|
+
log93.debug("Error handling typing event", { error: String(error2) });
|
|
285519
285565
|
}
|
|
285520
285566
|
});
|
|
285521
285567
|
}, {
|
|
@@ -285543,15 +285589,15 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285543
285589
|
queue: "agent-dispatcher-media",
|
|
285544
285590
|
startFrom: "new"
|
|
285545
285591
|
});
|
|
285546
|
-
|
|
285592
|
+
log93.info("Agent dispatcher initialized (message + reaction + reaction-removed + media triggers)");
|
|
285547
285593
|
} catch (error2) {
|
|
285548
|
-
|
|
285594
|
+
log93.error("Failed to set up agent dispatcher", { error: String(error2) });
|
|
285549
285595
|
clearInterval(mediaCleanupInterval);
|
|
285550
285596
|
debouncer.clear();
|
|
285551
285597
|
throw error2;
|
|
285552
285598
|
}
|
|
285553
285599
|
return async () => {
|
|
285554
|
-
|
|
285600
|
+
log93.info("Shutting down agent dispatcher");
|
|
285555
285601
|
clearInterval(mediaCleanupInterval);
|
|
285556
285602
|
debouncer.clear();
|
|
285557
285603
|
for (const [mediaId, pending] of mediaCompletions.entries()) {
|
|
@@ -285563,7 +285609,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285563
285609
|
for (const [key, provider] of providerCache.entries()) {
|
|
285564
285610
|
if (provider.dispose) {
|
|
285565
285611
|
disposePromises.push(provider.dispose().catch((err) => {
|
|
285566
|
-
|
|
285612
|
+
log93.warn("Error disposing provider", { key, error: String(err) });
|
|
285567
285613
|
}));
|
|
285568
285614
|
}
|
|
285569
285615
|
}
|
|
@@ -285573,7 +285619,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285573
285619
|
try {
|
|
285574
285620
|
client.stop();
|
|
285575
285621
|
} catch (err) {
|
|
285576
|
-
|
|
285622
|
+
log93.warn("Error stopping OpenClaw client", { providerId: id, error: String(err) });
|
|
285577
285623
|
}
|
|
285578
285624
|
}));
|
|
285579
285625
|
}
|
|
@@ -285581,7 +285627,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285581
285627
|
let timeoutId;
|
|
285582
285628
|
const timeoutGuard = new Promise((resolve4) => {
|
|
285583
285629
|
timeoutId = setTimeout(() => {
|
|
285584
|
-
|
|
285630
|
+
log93.warn("Dispatcher shutdown timed out after 5s, proceeding");
|
|
285585
285631
|
resolve4([]);
|
|
285586
285632
|
}, 5000);
|
|
285587
285633
|
});
|
|
@@ -285594,10 +285640,10 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
285594
285640
|
}
|
|
285595
285641
|
providerCache.clear();
|
|
285596
285642
|
openclawClientPool.clear();
|
|
285597
|
-
|
|
285643
|
+
log93.info("Agent dispatcher shutdown complete");
|
|
285598
285644
|
};
|
|
285599
285645
|
}
|
|
285600
|
-
var
|
|
285646
|
+
var log93, _natsGenieProviderCtor, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, TRANSIENT_DISPATCH_ERROR_PATTERNS, TRANSIENT_DISPATCH_RETRY_DELAYS_MS, CHANNEL_MESSAGE_LIMITS, DEFAULT_MESSAGE_LIMIT = 4000, MEDIA_BASE_PATH3, MEDIA_ICONS, MEDIA_WAIT_NULL, mediaCompletions, mediaResultCache, DEFAULT_SEND_MEDIA_PATH_TYPES, BOT_PREFIX = "\uD83E\uDD16 ", activeStreams, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", providerCache, openclawClientPool, nullFilterWarnedInstances, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
|
|
285601
285647
|
var init_agent_dispatcher = __esm(() => {
|
|
285602
285648
|
init_src2();
|
|
285603
285649
|
init_src();
|
|
@@ -285614,7 +285660,7 @@ var init_agent_dispatcher = __esm(() => {
|
|
|
285614
285660
|
init_message_persistence();
|
|
285615
285661
|
init_session_storage();
|
|
285616
285662
|
init_src7();
|
|
285617
|
-
|
|
285663
|
+
log93 = createLogger("agent-dispatcher");
|
|
285618
285664
|
_natsGenieProviderCtor = NatsGenieProvider;
|
|
285619
285665
|
TRANSIENT_DISPATCH_ERROR_PATTERNS = [
|
|
285620
285666
|
/ECONNREFUSED/i,
|
|
@@ -285775,7 +285821,7 @@ class RouteResolver {
|
|
|
285775
285821
|
}
|
|
285776
285822
|
async resolve(instanceId, chatId, personId) {
|
|
285777
285823
|
if (!UUID_RE2.test(chatId)) {
|
|
285778
|
-
|
|
285824
|
+
log94.debug("Skipping chat route resolution \u2014 chatId is not a valid UUID", {
|
|
285779
285825
|
instanceId,
|
|
285780
285826
|
chatId,
|
|
285781
285827
|
personId
|
|
@@ -285787,7 +285833,7 @@ class RouteResolver {
|
|
|
285787
285833
|
if (cached !== undefined) {
|
|
285788
285834
|
this.metrics.hits++;
|
|
285789
285835
|
const result = cached === NO_ROUTE ? null : cached;
|
|
285790
|
-
|
|
285836
|
+
log94.debug("Route cache hit", { instanceId, chatId, personId, hit: true, hasRoute: result !== null });
|
|
285791
285837
|
return result;
|
|
285792
285838
|
}
|
|
285793
285839
|
this.metrics.misses++;
|
|
@@ -285801,7 +285847,7 @@ class RouteResolver {
|
|
|
285801
285847
|
if (!dbRoute) {
|
|
285802
285848
|
this.metrics.sets++;
|
|
285803
285849
|
this.cache.set(cacheKey, NO_ROUTE);
|
|
285804
|
-
|
|
285850
|
+
log94.debug("No route found (using instance default, cached negative result)", {
|
|
285805
285851
|
instanceId,
|
|
285806
285852
|
chatId,
|
|
285807
285853
|
personId,
|
|
@@ -285815,7 +285861,7 @@ class RouteResolver {
|
|
|
285815
285861
|
};
|
|
285816
285862
|
this.metrics.sets++;
|
|
285817
285863
|
this.cache.set(cacheKey, route);
|
|
285818
|
-
|
|
285864
|
+
log94.debug("Route resolved from DB", {
|
|
285819
285865
|
instanceId,
|
|
285820
285866
|
chatId,
|
|
285821
285867
|
personId,
|
|
@@ -285828,12 +285874,12 @@ class RouteResolver {
|
|
|
285828
285874
|
invalidateRoute(routeId) {
|
|
285829
285875
|
this.cache.clear();
|
|
285830
285876
|
this.metrics.invalidations++;
|
|
285831
|
-
|
|
285877
|
+
log94.debug("Route cache invalidated", { routeId });
|
|
285832
285878
|
}
|
|
285833
285879
|
invalidateInstance(instanceId) {
|
|
285834
285880
|
this.cache.clear();
|
|
285835
285881
|
this.metrics.invalidations++;
|
|
285836
|
-
|
|
285882
|
+
log94.debug("Instance cache invalidated", { instanceId });
|
|
285837
285883
|
}
|
|
285838
285884
|
getMetrics() {
|
|
285839
285885
|
const total = this.metrics.hits + this.metrics.misses;
|
|
@@ -285848,13 +285894,13 @@ class RouteResolver {
|
|
|
285848
285894
|
return `${instanceId}:${chatId ?? "null"}:${personId ?? "null"}`;
|
|
285849
285895
|
}
|
|
285850
285896
|
}
|
|
285851
|
-
var
|
|
285897
|
+
var log94, UUID_RE2, NO_ROUTE;
|
|
285852
285898
|
var init_route_resolver = __esm(() => {
|
|
285853
285899
|
init_src();
|
|
285854
285900
|
init_src5();
|
|
285855
285901
|
init_drizzle_orm();
|
|
285856
285902
|
init_index_min();
|
|
285857
|
-
|
|
285903
|
+
log94 = createLogger("route-resolver");
|
|
285858
285904
|
UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
285859
285905
|
NO_ROUTE = Symbol("NO_ROUTE");
|
|
285860
285906
|
});
|
|
@@ -286089,7 +286135,7 @@ class SettingsService {
|
|
|
286089
286135
|
}
|
|
286090
286136
|
}
|
|
286091
286137
|
if (seeded > 0) {
|
|
286092
|
-
|
|
286138
|
+
log95.info("Seeded default settings", { count: seeded });
|
|
286093
286139
|
}
|
|
286094
286140
|
return seeded;
|
|
286095
286141
|
}
|
|
@@ -286150,12 +286196,12 @@ class SettingsService {
|
|
|
286150
286196
|
return "string";
|
|
286151
286197
|
}
|
|
286152
286198
|
}
|
|
286153
|
-
var
|
|
286199
|
+
var log95, DEFAULT_SETTINGS;
|
|
286154
286200
|
var init_settings = __esm(() => {
|
|
286155
286201
|
init_src();
|
|
286156
286202
|
init_src5();
|
|
286157
286203
|
init_drizzle_orm();
|
|
286158
|
-
|
|
286204
|
+
log95 = createLogger("settings");
|
|
286159
286205
|
DEFAULT_SETTINGS = [
|
|
286160
286206
|
{
|
|
286161
286207
|
key: "elevenlabs.api_key",
|
|
@@ -286678,7 +286724,7 @@ class TurnService {
|
|
|
286678
286724
|
if (!turn) {
|
|
286679
286725
|
throw new Error("Failed to create turn");
|
|
286680
286726
|
}
|
|
286681
|
-
|
|
286727
|
+
log96.info("Turn opened", {
|
|
286682
286728
|
turnId: turn.id,
|
|
286683
286729
|
instanceId: options.instanceId,
|
|
286684
286730
|
chatId: options.chatId,
|
|
@@ -286699,7 +286745,7 @@ class TurnService {
|
|
|
286699
286745
|
}).where(and2(eq(turns.id, turnId), eq(turns.status, "open"))).returning();
|
|
286700
286746
|
if (closed) {
|
|
286701
286747
|
const durationMs = now.getTime() - closed.startedAt.getTime();
|
|
286702
|
-
|
|
286748
|
+
log96.info("Turn closed", {
|
|
286703
286749
|
turnId,
|
|
286704
286750
|
action: options.action,
|
|
286705
286751
|
durationMs,
|
|
@@ -286773,7 +286819,7 @@ class TurnService {
|
|
|
286773
286819
|
closedReason: reason ?? "admin force-close"
|
|
286774
286820
|
}).where(and2(eq(turns.id, turnId), eq(turns.status, "open"))).returning();
|
|
286775
286821
|
if (closed) {
|
|
286776
|
-
|
|
286822
|
+
log96.info("Turn force-closed by admin", { turnId });
|
|
286777
286823
|
}
|
|
286778
286824
|
return closed ?? null;
|
|
286779
286825
|
}
|
|
@@ -286785,16 +286831,16 @@ class TurnService {
|
|
|
286785
286831
|
closedAt: now,
|
|
286786
286832
|
closedReason: reason ?? "admin bulk close"
|
|
286787
286833
|
}).where(eq(turns.status, "open")).returning({ id: turns.id });
|
|
286788
|
-
|
|
286834
|
+
log96.info("Bulk close completed", { closedCount: closed.length });
|
|
286789
286835
|
return closed.length;
|
|
286790
286836
|
}
|
|
286791
286837
|
}
|
|
286792
|
-
var
|
|
286838
|
+
var log96;
|
|
286793
286839
|
var init_turns = __esm(() => {
|
|
286794
286840
|
init_src();
|
|
286795
286841
|
init_src5();
|
|
286796
286842
|
init_drizzle_orm();
|
|
286797
|
-
|
|
286843
|
+
log96 = createLogger("turns");
|
|
286798
286844
|
});
|
|
286799
286845
|
|
|
286800
286846
|
// ../api/src/services/webhooks.ts
|
|
@@ -286953,7 +286999,8 @@ function createServices(db2, eventBus) {
|
|
|
286953
286999
|
turns: new TurnService(db2),
|
|
286954
287000
|
consumerOffsets: new ConsumerOffsetService(db2),
|
|
286955
287001
|
followUpLifecycle: new FollowUpLifecycleService(db2, eventBus),
|
|
286956
|
-
followUpSweeper: new FollowUpSweeperService(db2, eventBus)
|
|
287002
|
+
followUpSweeper: new FollowUpSweeperService(db2, eventBus),
|
|
287003
|
+
genieHosts: new GenieHostsService(db2)
|
|
286957
287004
|
};
|
|
286958
287005
|
}
|
|
286959
287006
|
var init_services = __esm(() => {
|
|
@@ -286982,6 +287029,7 @@ var init_services = __esm(() => {
|
|
|
286982
287029
|
init_events2();
|
|
286983
287030
|
init_follow_up_lifecycle();
|
|
286984
287031
|
init_follow_up_sweeper();
|
|
287032
|
+
init_genie_hosts();
|
|
286985
287033
|
init_instances();
|
|
286986
287034
|
init_messages3();
|
|
286987
287035
|
init_payload_store2();
|
|
@@ -287214,15 +287262,15 @@ function isClientError(error2) {
|
|
|
287214
287262
|
}
|
|
287215
287263
|
return false;
|
|
287216
287264
|
}
|
|
287217
|
-
var
|
|
287265
|
+
var log97, SENSITIVE_KEYS, ERROR_STATUS_MAP, CHANNEL_ERROR_MAP, PG_CLIENT_ERROR_CODES, errorHandler2 = (error2, c) => {
|
|
287218
287266
|
const requestId = c.get("requestId") ?? "unknown";
|
|
287219
287267
|
if (isClientError(error2)) {
|
|
287220
|
-
|
|
287268
|
+
log97.debug("Client error", {
|
|
287221
287269
|
requestId,
|
|
287222
287270
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
287223
287271
|
});
|
|
287224
287272
|
} else {
|
|
287225
|
-
|
|
287273
|
+
log97.error("Server error", {
|
|
287226
287274
|
requestId,
|
|
287227
287275
|
error: error2 instanceof Error ? error2.message : String(error2),
|
|
287228
287276
|
stack: error2 instanceof Error ? error2.stack : undefined
|
|
@@ -287250,7 +287298,7 @@ var init_error3 = __esm(() => {
|
|
|
287250
287298
|
init_esm5();
|
|
287251
287299
|
init_http_exception();
|
|
287252
287300
|
init_zod();
|
|
287253
|
-
|
|
287301
|
+
log97 = createLogger("api:error");
|
|
287254
287302
|
SENSITIVE_KEYS = new Set([
|
|
287255
287303
|
"password",
|
|
287256
287304
|
"token",
|
|
@@ -287496,22 +287544,22 @@ function createWebhookAuthMiddleware(config4) {
|
|
|
287496
287544
|
const token = c.req.header("x-telegram-bot-api-secret-token");
|
|
287497
287545
|
if (!token) {
|
|
287498
287546
|
const ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "unknown";
|
|
287499
|
-
|
|
287547
|
+
log98.warn("Webhook request missing secret token", { ip });
|
|
287500
287548
|
return c.json({ error: { code: "UNAUTHORIZED", message: "Missing webhook secret token" } }, 401);
|
|
287501
287549
|
}
|
|
287502
287550
|
if (token !== webhookSecret) {
|
|
287503
287551
|
const ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "unknown";
|
|
287504
|
-
|
|
287552
|
+
log98.warn("Webhook request with invalid secret token", { ip });
|
|
287505
287553
|
return c.json({ error: { code: "UNAUTHORIZED", message: "Invalid webhook secret token" } }, 401);
|
|
287506
287554
|
}
|
|
287507
287555
|
return next();
|
|
287508
287556
|
});
|
|
287509
287557
|
}
|
|
287510
|
-
var
|
|
287558
|
+
var log98;
|
|
287511
287559
|
var init_webhook_auth = __esm(() => {
|
|
287512
287560
|
init_src();
|
|
287513
287561
|
init_factory2();
|
|
287514
|
-
|
|
287562
|
+
log98 = createLogger("api:webhook-auth");
|
|
287515
287563
|
});
|
|
287516
287564
|
|
|
287517
287565
|
// ../api/src/plugin-state.ts
|
|
@@ -294335,7 +294383,7 @@ async function handleTrashEmojiMessage(services, db2, event) {
|
|
|
294335
294383
|
await runTrashEmojiCleanup(services, db2, instanceId, chatId, from);
|
|
294336
294384
|
});
|
|
294337
294385
|
if (!result.executed) {
|
|
294338
|
-
|
|
294386
|
+
log99.debug("Trash emoji event already processed (NATS redelivery skipped)", {
|
|
294339
294387
|
eventId: event.id,
|
|
294340
294388
|
instanceId,
|
|
294341
294389
|
chatId
|
|
@@ -294343,10 +294391,10 @@ async function handleTrashEmojiMessage(services, db2, event) {
|
|
|
294343
294391
|
}
|
|
294344
294392
|
}
|
|
294345
294393
|
async function runTrashEmojiCleanup(services, db2, instanceId, chatId, from) {
|
|
294346
|
-
|
|
294394
|
+
log99.info("Trash emoji detected, clearing session", { instanceId, chatId, from });
|
|
294347
294395
|
try {
|
|
294348
294396
|
const { sessionId, sessionStrategy } = await clearAgentSession(services, db2, instanceId, from, chatId);
|
|
294349
|
-
|
|
294397
|
+
log99.info("Session cleared successfully", { instanceId, sessionId, sessionStrategy });
|
|
294350
294398
|
try {
|
|
294351
294399
|
const dbChat = await services.chats.findByExternalIdSmart(instanceId, chatId);
|
|
294352
294400
|
if (dbChat?.id) {
|
|
@@ -294360,11 +294408,11 @@ async function runTrashEmojiCleanup(services, db2, instanceId, chatId, from) {
|
|
|
294360
294408
|
await services.chats.update(dbChat.id, {
|
|
294361
294409
|
settings: { agentPaused: false, agentResumedAt: new Date().toISOString() }
|
|
294362
294410
|
});
|
|
294363
|
-
|
|
294411
|
+
log99.info("Agent resumed after session clear (was paused by handoff)", { instanceId, chatId });
|
|
294364
294412
|
}
|
|
294365
294413
|
}
|
|
294366
294414
|
} catch (disarmError) {
|
|
294367
|
-
|
|
294415
|
+
log99.warn("Failed to disarm follow-up after session clear", {
|
|
294368
294416
|
instanceId,
|
|
294369
294417
|
chatId,
|
|
294370
294418
|
error: String(disarmError)
|
|
@@ -294372,9 +294420,9 @@ async function runTrashEmojiCleanup(services, db2, instanceId, chatId, from) {
|
|
|
294372
294420
|
}
|
|
294373
294421
|
try {
|
|
294374
294422
|
await sendMessage(services, instanceId, chatId, "\u2705 Conversa limpa! Sua sess\xE3o com o assistente foi resetada.");
|
|
294375
|
-
|
|
294423
|
+
log99.info("Sent session cleared confirmation", { instanceId, chatId });
|
|
294376
294424
|
} catch (sendError) {
|
|
294377
|
-
|
|
294425
|
+
log99.error("Failed to send confirmation message", { instanceId, chatId, error: String(sendError) });
|
|
294378
294426
|
}
|
|
294379
294427
|
} catch (error2) {
|
|
294380
294428
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -294385,14 +294433,14 @@ async function runTrashEmojiCleanup(services, db2, instanceId, chatId, from) {
|
|
|
294385
294433
|
"Session clearing not supported for"
|
|
294386
294434
|
];
|
|
294387
294435
|
if (skippableErrors.some((e) => errorMessage.includes(e))) {
|
|
294388
|
-
|
|
294436
|
+
log99.debug("Session clearing skipped", { instanceId, reason: errorMessage });
|
|
294389
294437
|
return;
|
|
294390
294438
|
}
|
|
294391
|
-
|
|
294439
|
+
log99.error("Failed to clear session", { instanceId, chatId, error: errorMessage });
|
|
294392
294440
|
try {
|
|
294393
294441
|
await sendMessage(services, instanceId, chatId, "\u274C Erro ao limpar sess\xE3o. Tente novamente.");
|
|
294394
294442
|
} catch (sendError) {
|
|
294395
|
-
|
|
294443
|
+
log99.error("Failed to send error message", { instanceId, chatId, error: String(sendError) });
|
|
294396
294444
|
}
|
|
294397
294445
|
}
|
|
294398
294446
|
}
|
|
@@ -294406,13 +294454,13 @@ async function setupSessionCleaner(eventBus, services, db2) {
|
|
|
294406
294454
|
startFrom: "new",
|
|
294407
294455
|
concurrency: 5
|
|
294408
294456
|
});
|
|
294409
|
-
|
|
294457
|
+
log99.info("Session cleaner initialized");
|
|
294410
294458
|
} catch (error2) {
|
|
294411
|
-
|
|
294459
|
+
log99.error("Failed to set up session cleaner", { error: String(error2) });
|
|
294412
294460
|
throw error2;
|
|
294413
294461
|
}
|
|
294414
294462
|
}
|
|
294415
|
-
var
|
|
294463
|
+
var log99;
|
|
294416
294464
|
var init_session_cleaner = __esm(() => {
|
|
294417
294465
|
init_src();
|
|
294418
294466
|
init_src5();
|
|
@@ -294421,7 +294469,7 @@ var init_session_cleaner = __esm(() => {
|
|
|
294421
294469
|
init_agent_runner();
|
|
294422
294470
|
init_agent_dispatcher();
|
|
294423
294471
|
init_loader2();
|
|
294424
|
-
|
|
294472
|
+
log99 = createLogger("session-cleaner");
|
|
294425
294473
|
});
|
|
294426
294474
|
|
|
294427
294475
|
// ../api/src/routes/v2/chats.ts
|
|
@@ -296665,12 +296713,12 @@ async function printQrCodeToTerminal(qrCode, instanceId) {
|
|
|
296665
296713
|
try {
|
|
296666
296714
|
const qrTerminalModule = await Promise.resolve().then(() => __toESM(require_main(), 1));
|
|
296667
296715
|
const qrTerminal = qrTerminalModule.default || qrTerminalModule;
|
|
296668
|
-
|
|
296716
|
+
log100.info("QR Code generated for WhatsApp", { instanceId });
|
|
296669
296717
|
qrTerminal.generate(qrCode, { small: true });
|
|
296670
296718
|
} catch (error2) {
|
|
296671
|
-
|
|
296719
|
+
log100.info("QR Code generated", { instanceId, qrCode: `${qrCode.substring(0, 50)}...` });
|
|
296672
296720
|
if (error2 instanceof Error && process.env.DEBUG) {
|
|
296673
|
-
|
|
296721
|
+
log100.debug("QR Terminal unavailable", { error: error2.message });
|
|
296674
296722
|
}
|
|
296675
296723
|
}
|
|
296676
296724
|
}
|
|
@@ -296682,13 +296730,13 @@ async function setupQrCodeListener(eventBus) {
|
|
|
296682
296730
|
await printQrCodeToTerminal(qrCode, instanceId);
|
|
296683
296731
|
});
|
|
296684
296732
|
} catch (error2) {
|
|
296685
|
-
|
|
296733
|
+
log100.warn("Failed to set up QR code listener", { error: String(error2) });
|
|
296686
296734
|
}
|
|
296687
296735
|
}
|
|
296688
|
-
var
|
|
296736
|
+
var log100, qrCodes;
|
|
296689
296737
|
var init_qr_store = __esm(() => {
|
|
296690
296738
|
init_src();
|
|
296691
|
-
|
|
296739
|
+
log100 = createLogger("api:qr-store");
|
|
296692
296740
|
qrCodes = new Map;
|
|
296693
296741
|
});
|
|
296694
296742
|
|
|
@@ -296709,29 +296757,29 @@ class AgentReplayService {
|
|
|
296709
296757
|
agentId: instances.agentId
|
|
296710
296758
|
}).from(instances).where(eq(instances.id, instanceId)).limit(1);
|
|
296711
296759
|
if (!instance4) {
|
|
296712
|
-
|
|
296760
|
+
log101.warn("Instance not found for replay", { instanceId });
|
|
296713
296761
|
return;
|
|
296714
296762
|
}
|
|
296715
296763
|
if (!instance4.agentId) {
|
|
296716
|
-
|
|
296764
|
+
log101.debug("Instance has no agent, skipping replay", { instanceId });
|
|
296717
296765
|
await this.updateLastSeenAt(instanceId);
|
|
296718
296766
|
return;
|
|
296719
296767
|
}
|
|
296720
296768
|
if (!instance4.replayEnabled) {
|
|
296721
|
-
|
|
296769
|
+
log101.debug("Replay disabled for instance", { instanceId });
|
|
296722
296770
|
await this.updateLastSeenAt(instanceId);
|
|
296723
296771
|
return;
|
|
296724
296772
|
}
|
|
296725
296773
|
const since = instance4.lastSeenAt ?? null;
|
|
296726
296774
|
if (!since) {
|
|
296727
|
-
|
|
296775
|
+
log101.debug("No lastSeenAt recorded, skipping replay (first connect)", { instanceId });
|
|
296728
296776
|
await this.updateLastSeenAt(instanceId);
|
|
296729
296777
|
return;
|
|
296730
296778
|
}
|
|
296731
|
-
|
|
296779
|
+
log101.info("Starting replay on reconnect", { instanceId, since: since.toISOString() });
|
|
296732
296780
|
try {
|
|
296733
296781
|
const result = await this.replayMissedMessages({ instanceId, since });
|
|
296734
|
-
|
|
296782
|
+
log101.info("Replay complete", {
|
|
296735
296783
|
instanceId,
|
|
296736
296784
|
replayed: result.replayed,
|
|
296737
296785
|
skipped: result.skipped,
|
|
@@ -296739,7 +296787,7 @@ class AgentReplayService {
|
|
|
296739
296787
|
});
|
|
296740
296788
|
await this.updateLastSeenAt(instanceId, result.until);
|
|
296741
296789
|
} catch (error2) {
|
|
296742
|
-
|
|
296790
|
+
log101.error("Replay failed", { instanceId, error: String(error2) });
|
|
296743
296791
|
}
|
|
296744
296792
|
}
|
|
296745
296793
|
async replayMissedMessages(options) {
|
|
@@ -296747,7 +296795,7 @@ class AgentReplayService {
|
|
|
296747
296795
|
const now = new Date;
|
|
296748
296796
|
const cutoff = new Date(now.getTime() - MAX_REPLAY_WINDOW_MS);
|
|
296749
296797
|
const since = options.since && options.since > cutoff ? options.since : cutoff;
|
|
296750
|
-
|
|
296798
|
+
log101.debug("Fetching missed messages", { instanceId, since: since.toISOString(), until: now.toISOString() });
|
|
296751
296799
|
let cursorTimestamp = since;
|
|
296752
296800
|
let cursorId = null;
|
|
296753
296801
|
let totalReplayed = 0;
|
|
@@ -296781,7 +296829,7 @@ class AgentReplayService {
|
|
|
296781
296829
|
if (rows.length === 0)
|
|
296782
296830
|
break;
|
|
296783
296831
|
if (rows.length === PAGE_SIZE) {
|
|
296784
|
-
|
|
296832
|
+
log101.warn("Replay page cap hit, fetching next page", {
|
|
296785
296833
|
instanceId,
|
|
296786
296834
|
limit: PAGE_SIZE,
|
|
296787
296835
|
cursor: cursorTimestamp.toISOString()
|
|
@@ -296809,7 +296857,7 @@ class AgentReplayService {
|
|
|
296809
296857
|
await this.redispatchMessage(instanceId, row);
|
|
296810
296858
|
replayed++;
|
|
296811
296859
|
} catch (error2) {
|
|
296812
|
-
|
|
296860
|
+
log101.warn("Failed to redispatch message during replay", {
|
|
296813
296861
|
instanceId,
|
|
296814
296862
|
messageId: row.id,
|
|
296815
296863
|
error: String(error2)
|
|
@@ -296866,12 +296914,12 @@ function mapMessageTypeToContentType(messageType) {
|
|
|
296866
296914
|
return "text";
|
|
296867
296915
|
}
|
|
296868
296916
|
}
|
|
296869
|
-
var
|
|
296917
|
+
var log101, MAX_REPLAY_WINDOW_MS;
|
|
296870
296918
|
var init_agent_replay = __esm(() => {
|
|
296871
296919
|
init_src();
|
|
296872
296920
|
init_src5();
|
|
296873
296921
|
init_drizzle_orm();
|
|
296874
|
-
|
|
296922
|
+
log101 = createLogger("agent-replay");
|
|
296875
296923
|
MAX_REPLAY_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
296876
296924
|
});
|
|
296877
296925
|
|
|
@@ -297041,15 +297089,15 @@ async function connectInstanceWithPlugin(plugin7, instanceId, options) {
|
|
|
297041
297089
|
async function triggerCreateConnection(channelRegistry2, channel4, instanceId, options) {
|
|
297042
297090
|
const plugin7 = getPluginFromRegistry(channelRegistry2, channel4);
|
|
297043
297091
|
if (!plugin7) {
|
|
297044
|
-
|
|
297092
|
+
log102.warn("No plugin found for channel", { channel: channel4 });
|
|
297045
297093
|
return;
|
|
297046
297094
|
}
|
|
297047
297095
|
const errorMessage = await connectInstanceWithPlugin(plugin7, instanceId, options);
|
|
297048
297096
|
if (errorMessage) {
|
|
297049
|
-
|
|
297097
|
+
log102.error("Failed to connect instance", { instanceId, error: errorMessage });
|
|
297050
297098
|
return;
|
|
297051
297099
|
}
|
|
297052
|
-
|
|
297100
|
+
log102.info("Triggered connection", { instanceId, channel: channel4 });
|
|
297053
297101
|
}
|
|
297054
297102
|
function buildTokenPersistUpdates(channel4, body) {
|
|
297055
297103
|
const updates = {};
|
|
@@ -297083,10 +297131,10 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
297083
297131
|
await services.apiKeys.update(existingKey.id, {
|
|
297084
297132
|
instanceIds: updated.length > 0 ? updated : null
|
|
297085
297133
|
});
|
|
297086
|
-
|
|
297134
|
+
log102.info("Removed instance from agent key", { keyName, instanceId });
|
|
297087
297135
|
}
|
|
297088
297136
|
} catch (err) {
|
|
297089
|
-
|
|
297137
|
+
log102.error("Failed to remove instance from old agent key", { oldAgentId, instanceId, error: String(err) });
|
|
297090
297138
|
}
|
|
297091
297139
|
}
|
|
297092
297140
|
if (newAgentId) {
|
|
@@ -297100,7 +297148,7 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
297100
297148
|
await services.apiKeys.update(existingKey.id, {
|
|
297101
297149
|
instanceIds: [...currentIds, instanceId]
|
|
297102
297150
|
});
|
|
297103
|
-
|
|
297151
|
+
log102.info("Added instance to existing agent key", { keyName, instanceId });
|
|
297104
297152
|
}
|
|
297105
297153
|
} else {
|
|
297106
297154
|
const agentScopes = Array.isArray(agent3.metadata?.omniScopes) ? agent3.metadata.omniScopes : [...DEFAULT_TURN_SCOPES];
|
|
@@ -297111,10 +297159,10 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
297111
297159
|
instanceIds: [instanceId],
|
|
297112
297160
|
createdBy: "system:auto-provision"
|
|
297113
297161
|
});
|
|
297114
|
-
|
|
297162
|
+
log102.info("Created scoped agent key", { keyName, instanceId, keyId: result.key.id });
|
|
297115
297163
|
}
|
|
297116
297164
|
} catch (err) {
|
|
297117
|
-
|
|
297165
|
+
log102.error("Failed to provision agent key", { newAgentId, instanceId, error: String(err) });
|
|
297118
297166
|
}
|
|
297119
297167
|
}
|
|
297120
297168
|
}
|
|
@@ -297247,7 +297295,7 @@ function getCacheKey(instanceId, guildId) {
|
|
|
297247
297295
|
function invalidateGuildCache(instanceId, guildId) {
|
|
297248
297296
|
guildConfigCache.delete(getCacheKey(instanceId, guildId));
|
|
297249
297297
|
}
|
|
297250
|
-
var
|
|
297298
|
+
var log102, instancesRoutes, instanceAccess2, listQuerySchema11, agentReplyFilterSchema, createInstanceSchema, updateInstanceSchema, DEFAULT_AGENT_REPLY_FILTER, SENSITIVE_INSTANCE_FIELDS, pairingCodeSchema, connectInstanceSchema, syncRequestSchema, listContactsQuerySchema, listGroupsQuerySchema, checkNumberSchema, updateBioSchema, blockContactSchema, resyncSchema, replaySchema, pairingActionSchema, guildConfigOverrideSchema, guildConfigCache, GUILD_CONFIG_TTL, presenceSchema;
|
|
297251
297299
|
var init_instances3 = __esm(() => {
|
|
297252
297300
|
init_dist6();
|
|
297253
297301
|
init_src();
|
|
@@ -297259,7 +297307,7 @@ var init_instances3 = __esm(() => {
|
|
|
297259
297307
|
init_qr_store();
|
|
297260
297308
|
init_access();
|
|
297261
297309
|
init_agent_replay();
|
|
297262
|
-
|
|
297310
|
+
log102 = createLogger("api:instances");
|
|
297263
297311
|
instancesRoutes = new Hono2;
|
|
297264
297312
|
instanceAccess2 = requireInstanceAccess((c) => c.req.param("id"));
|
|
297265
297313
|
listQuerySchema11 = exports_external.object({
|
|
@@ -297445,7 +297493,7 @@ var init_instances3 = __esm(() => {
|
|
|
297445
297493
|
agentIdTouched: data.agentId !== undefined
|
|
297446
297494
|
})) {
|
|
297447
297495
|
data.agentReplyFilter = DEFAULT_AGENT_REPLY_FILTER;
|
|
297448
|
-
|
|
297496
|
+
log102.info("Agent assigned without reply filter \u2014 defaulting to mode:all onDm:true (omni#443)", {
|
|
297449
297497
|
agentId: data.agentId,
|
|
297450
297498
|
defaultFilter: DEFAULT_AGENT_REPLY_FILTER
|
|
297451
297499
|
});
|
|
@@ -297499,7 +297547,7 @@ var init_instances3 = __esm(() => {
|
|
|
297499
297547
|
agentIdTouched: data.agentId !== undefined
|
|
297500
297548
|
})) {
|
|
297501
297549
|
data.agentReplyFilter = DEFAULT_AGENT_REPLY_FILTER;
|
|
297502
|
-
|
|
297550
|
+
log102.info("Agent assigned without reply filter \u2014 defaulting to mode:all onDm:true (omni#443)", {
|
|
297503
297551
|
instanceId: id,
|
|
297504
297552
|
agentId: data.agentId,
|
|
297505
297553
|
defaultFilter: DEFAULT_AGENT_REPLY_FILTER
|
|
@@ -297524,7 +297572,7 @@ var init_instances3 = __esm(() => {
|
|
|
297524
297572
|
try {
|
|
297525
297573
|
await plugin7.disconnect(id);
|
|
297526
297574
|
} catch (error2) {
|
|
297527
|
-
|
|
297575
|
+
log102.error("Failed to disconnect instance before delete", { instanceId: id, error: String(error2) });
|
|
297528
297576
|
}
|
|
297529
297577
|
}
|
|
297530
297578
|
await services.instances.delete(id);
|
|
@@ -297532,7 +297580,7 @@ var init_instances3 = __esm(() => {
|
|
|
297532
297580
|
try {
|
|
297533
297581
|
await plugin7.logout(id);
|
|
297534
297582
|
} catch (error2) {
|
|
297535
|
-
|
|
297583
|
+
log102.error("Failed to clear channel auth after delete", { instanceId: id, error: String(error2) });
|
|
297536
297584
|
}
|
|
297537
297585
|
}
|
|
297538
297586
|
return c.json({ success: true });
|
|
@@ -297696,7 +297744,7 @@ var init_instances3 = __esm(() => {
|
|
|
297696
297744
|
try {
|
|
297697
297745
|
await plugin7.disconnect(id);
|
|
297698
297746
|
} catch (error2) {
|
|
297699
|
-
|
|
297747
|
+
log102.error("Failed to disconnect instance", { instanceId: id, error: String(error2) });
|
|
297700
297748
|
}
|
|
297701
297749
|
}
|
|
297702
297750
|
}
|
|
@@ -297776,13 +297824,13 @@ var init_instances3 = __esm(() => {
|
|
|
297776
297824
|
try {
|
|
297777
297825
|
await plugin7.logout(id);
|
|
297778
297826
|
} catch (error2) {
|
|
297779
|
-
|
|
297827
|
+
log102.error("Failed to logout instance", { instanceId: id, error: String(error2) });
|
|
297780
297828
|
}
|
|
297781
297829
|
} else if (plugin7) {
|
|
297782
297830
|
try {
|
|
297783
297831
|
await plugin7.disconnect(id);
|
|
297784
297832
|
} catch (error2) {
|
|
297785
|
-
|
|
297833
|
+
log102.error("Failed to disconnect instance during logout", { instanceId: id, error: String(error2) });
|
|
297786
297834
|
}
|
|
297787
297835
|
}
|
|
297788
297836
|
}
|
|
@@ -298572,7 +298620,7 @@ var init_instances3 = __esm(() => {
|
|
|
298572
298620
|
...chatJids?.length ? { chatJids } : {}
|
|
298573
298621
|
}
|
|
298574
298622
|
});
|
|
298575
|
-
|
|
298623
|
+
log102.info("Resync triggered", {
|
|
298576
298624
|
instanceId: id,
|
|
298577
298625
|
jobId: job.id,
|
|
298578
298626
|
since: sinceDate.toISOString(),
|
|
@@ -298590,7 +298638,7 @@ var init_instances3 = __esm(() => {
|
|
|
298590
298638
|
});
|
|
298591
298639
|
} catch (error2) {
|
|
298592
298640
|
const message2 = error2 instanceof Error ? error2.message : "Unknown error";
|
|
298593
|
-
|
|
298641
|
+
log102.error("Failed to trigger resync", { instanceId: id, error: message2 });
|
|
298594
298642
|
return c.json({ error: { code: "RESYNC_FAILED", message: message2 } }, 500);
|
|
298595
298643
|
}
|
|
298596
298644
|
});
|
|
@@ -298619,7 +298667,7 @@ var init_instances3 = __esm(() => {
|
|
|
298619
298667
|
const sinceDate = since ? new Date(since) : undefined;
|
|
298620
298668
|
try {
|
|
298621
298669
|
const result = await replayService.replayMissedMessages({ instanceId: instance4.id, since: sinceDate });
|
|
298622
|
-
|
|
298670
|
+
log102.info("Manual replay triggered", {
|
|
298623
298671
|
instanceId: instance4.id,
|
|
298624
298672
|
replayed: result.replayed,
|
|
298625
298673
|
since: result.since.toISOString()
|
|
@@ -298635,7 +298683,7 @@ var init_instances3 = __esm(() => {
|
|
|
298635
298683
|
});
|
|
298636
298684
|
} catch (error2) {
|
|
298637
298685
|
const message2 = error2 instanceof Error ? error2.message : "Unknown error";
|
|
298638
|
-
|
|
298686
|
+
log102.error("Manual replay failed", { instanceId: id, error: message2 });
|
|
298639
298687
|
return c.json({ error: { code: "REPLAY_FAILED", message: message2 } }, 500);
|
|
298640
298688
|
}
|
|
298641
298689
|
});
|
|
@@ -298768,7 +298816,7 @@ var init_instances3 = __esm(() => {
|
|
|
298768
298816
|
plugin7.setGuildConfig(id, guildId, newConfig);
|
|
298769
298817
|
}
|
|
298770
298818
|
}
|
|
298771
|
-
|
|
298819
|
+
log102.info("Guild config updated", {
|
|
298772
298820
|
instanceId: id,
|
|
298773
298821
|
guildId,
|
|
298774
298822
|
apiKeyId: apiKey?.id,
|
|
@@ -298797,7 +298845,7 @@ var init_instances3 = __esm(() => {
|
|
|
298797
298845
|
plugin7.removeGuildConfig(id, guildId);
|
|
298798
298846
|
}
|
|
298799
298847
|
}
|
|
298800
|
-
|
|
298848
|
+
log102.info("Guild config deleted", {
|
|
298801
298849
|
instanceId: id,
|
|
298802
298850
|
guildId,
|
|
298803
298851
|
apiKeyId: apiKey?.id,
|
|
@@ -299433,7 +299481,7 @@ function isValidPathComponent(component) {
|
|
|
299433
299481
|
function isValidUUID(str2) {
|
|
299434
299482
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str2);
|
|
299435
299483
|
}
|
|
299436
|
-
var
|
|
299484
|
+
var log103, mediaRoutes, mediaStorage = null, ttsAudioFormatSchema, ttsRequestSchema, sttRequestSchema, imagineAspectRatioSchema, imagineRequestSchema, visionRequestSchema, filmAspectRatioSchema, filmRequestSchema, FILM_TIMEOUT_MS, FILM_POLL_INTERVAL_MS = 5000;
|
|
299437
299485
|
var init_media = __esm(() => {
|
|
299438
299486
|
init_dist6();
|
|
299439
299487
|
init_src();
|
|
@@ -299441,7 +299489,7 @@ var init_media = __esm(() => {
|
|
|
299441
299489
|
init_zod();
|
|
299442
299490
|
init_registry3();
|
|
299443
299491
|
init_media_storage();
|
|
299444
|
-
|
|
299492
|
+
log103 = createLogger("routes:media");
|
|
299445
299493
|
mediaRoutes = new Hono2;
|
|
299446
299494
|
ttsAudioFormatSchema = exports_external.enum(["mp3", "ogg", "opus", "wav", "pcm", "flac", "aac"]);
|
|
299447
299495
|
ttsRequestSchema = exports_external.object({
|
|
@@ -299460,7 +299508,7 @@ var init_media = __esm(() => {
|
|
|
299460
299508
|
provider = await providerRegistry.resolve("tts", body.provider);
|
|
299461
299509
|
} catch (err) {
|
|
299462
299510
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299463
|
-
|
|
299511
|
+
log103.warn("TTS provider resolution failed", { provider: body.provider, error: message2 });
|
|
299464
299512
|
return c.json({
|
|
299465
299513
|
error: {
|
|
299466
299514
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -299488,7 +299536,7 @@ var init_media = __esm(() => {
|
|
|
299488
299536
|
});
|
|
299489
299537
|
} catch (err) {
|
|
299490
299538
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299491
|
-
|
|
299539
|
+
log103.error("TTS synthesis failed", { provider: provider.name, error: message2 });
|
|
299492
299540
|
return c.json({
|
|
299493
299541
|
error: {
|
|
299494
299542
|
code: "TTS_SYNTHESIS_FAILED",
|
|
@@ -299513,7 +299561,7 @@ var init_media = __esm(() => {
|
|
|
299513
299561
|
provider = await providerRegistry.resolve("stt", body.provider);
|
|
299514
299562
|
} catch (err) {
|
|
299515
299563
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299516
|
-
|
|
299564
|
+
log103.warn("STT provider resolution failed", { provider: body.provider, error: message2 });
|
|
299517
299565
|
return c.json({
|
|
299518
299566
|
error: {
|
|
299519
299567
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -299554,7 +299602,7 @@ var init_media = __esm(() => {
|
|
|
299554
299602
|
});
|
|
299555
299603
|
} catch (err) {
|
|
299556
299604
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299557
|
-
|
|
299605
|
+
log103.error("STT transcription failed", { provider: provider.name, error: message2 });
|
|
299558
299606
|
return c.json({
|
|
299559
299607
|
error: {
|
|
299560
299608
|
code: "STT_TRANSCRIPTION_FAILED",
|
|
@@ -299582,7 +299630,7 @@ var init_media = __esm(() => {
|
|
|
299582
299630
|
provider = await providerRegistry.resolve("imagegen", body.provider);
|
|
299583
299631
|
} catch (err) {
|
|
299584
299632
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299585
|
-
|
|
299633
|
+
log103.warn("Imagegen provider resolution failed", { provider: body.provider, error: message2 });
|
|
299586
299634
|
return c.json({
|
|
299587
299635
|
error: {
|
|
299588
299636
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -299616,7 +299664,7 @@ var init_media = __esm(() => {
|
|
|
299616
299664
|
});
|
|
299617
299665
|
} catch (err) {
|
|
299618
299666
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299619
|
-
|
|
299667
|
+
log103.error("Image generation failed", { provider: provider.name, error: message2 });
|
|
299620
299668
|
return c.json({
|
|
299621
299669
|
error: {
|
|
299622
299670
|
code: "IMAGE_GEN_FAILED",
|
|
@@ -299641,7 +299689,7 @@ var init_media = __esm(() => {
|
|
|
299641
299689
|
provider = await providerRegistry.resolve("vision", body.provider);
|
|
299642
299690
|
} catch (err) {
|
|
299643
299691
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299644
|
-
|
|
299692
|
+
log103.warn("Vision provider resolution failed", { provider: body.provider, error: message2 });
|
|
299645
299693
|
return c.json({
|
|
299646
299694
|
error: {
|
|
299647
299695
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -299680,7 +299728,7 @@ var init_media = __esm(() => {
|
|
|
299680
299728
|
});
|
|
299681
299729
|
} catch (err) {
|
|
299682
299730
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299683
|
-
|
|
299731
|
+
log103.error("Vision description failed", { provider: provider.name, error: message2 });
|
|
299684
299732
|
return c.json({
|
|
299685
299733
|
error: {
|
|
299686
299734
|
code: "VISION_DESCRIBE_FAILED",
|
|
@@ -299708,7 +299756,7 @@ var init_media = __esm(() => {
|
|
|
299708
299756
|
provider = await providerRegistry.resolve("videogen", body.provider);
|
|
299709
299757
|
} catch (err) {
|
|
299710
299758
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299711
|
-
|
|
299759
|
+
log103.warn("Videogen provider resolution failed", { provider: body.provider, error: message2 });
|
|
299712
299760
|
return c.json({
|
|
299713
299761
|
error: {
|
|
299714
299762
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -299742,7 +299790,7 @@ var init_media = __esm(() => {
|
|
|
299742
299790
|
}
|
|
299743
299791
|
if (operation.state === "failed" || !operation.video) {
|
|
299744
299792
|
const message2 = operation.error ?? "Video generation failed without error";
|
|
299745
|
-
|
|
299793
|
+
log103.error("Videogen operation failed", { provider: provider.name, error: message2 });
|
|
299746
299794
|
return c.json({
|
|
299747
299795
|
error: {
|
|
299748
299796
|
code: "VIDEO_GEN_FAILED",
|
|
@@ -299753,7 +299801,7 @@ var init_media = __esm(() => {
|
|
|
299753
299801
|
}, 500);
|
|
299754
299802
|
}
|
|
299755
299803
|
const video = operation.video;
|
|
299756
|
-
|
|
299804
|
+
log103.info("Videogen operation complete", {
|
|
299757
299805
|
provider: provider.name,
|
|
299758
299806
|
operationId: operation.operationId,
|
|
299759
299807
|
sizeBytes: video.data.length,
|
|
@@ -299772,7 +299820,7 @@ var init_media = __esm(() => {
|
|
|
299772
299820
|
});
|
|
299773
299821
|
} catch (err) {
|
|
299774
299822
|
const message2 = err instanceof Error ? err.message : "Unknown error";
|
|
299775
|
-
|
|
299823
|
+
log103.error("Videogen request failed", { provider: provider.name, error: message2 });
|
|
299776
299824
|
return c.json({
|
|
299777
299825
|
error: {
|
|
299778
299826
|
code: "VIDEO_GEN_FAILED",
|
|
@@ -299979,7 +300027,7 @@ async function verifyMessageInstanceOwnership(services, message2, instanceId) {
|
|
|
299979
300027
|
});
|
|
299980
300028
|
}
|
|
299981
300029
|
}
|
|
299982
|
-
var
|
|
300030
|
+
var log104, mediaDownloadLog, messagesRoutes, UUID_REGEX, MessageSourceSchema, MessageTypeSchema, MessageStatusSchema, DeliveryStatusSchema, listQuerySchema13, createMessageSchema, updateMessageSchema, recordEditSchema, addReactionSchema, removeReactionSchema, updateDeliveryStatusSchema, MentionSchema, sendTextSchema, sendMediaSchema, sendReactionSchema, sendStickerSchema, sendContactSchema, sendLocationSchema, sendHandoffSchema, messageRefSchema, _mediaStorageForDownload = null, sendTtsSchema, forwardMessageSchema, sendPresenceSchema, markMessageReadSchema, markBatchReadSchema, sendPollSchema, sendEmbedSchema, editMessageChannelSchema, deleteMessageChannelSchema, starMessageSchema;
|
|
299983
300031
|
var init_messages5 = __esm(() => {
|
|
299984
300032
|
init_dist6();
|
|
299985
300033
|
init_src2();
|
|
@@ -299992,7 +300040,7 @@ var init_messages5 = __esm(() => {
|
|
|
299992
300040
|
init_date_query();
|
|
299993
300041
|
init_api_keys();
|
|
299994
300042
|
init_media_storage();
|
|
299995
|
-
|
|
300043
|
+
log104 = createLogger("routes:messages");
|
|
299996
300044
|
mediaDownloadLog = createLogger("routes:messages:media-download");
|
|
299997
300045
|
messagesRoutes = new Hono2;
|
|
299998
300046
|
UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -300554,7 +300602,7 @@ var init_messages5 = __esm(() => {
|
|
|
300554
300602
|
reactionMetadata.targetParticipant = participant;
|
|
300555
300603
|
}
|
|
300556
300604
|
} else {
|
|
300557
|
-
|
|
300605
|
+
log104.warn("Reaction target message not found in DB; deferring fromMe to channel plugin fallback (#386)", {
|
|
300558
300606
|
instanceId,
|
|
300559
300607
|
chatId: chat2.id,
|
|
300560
300608
|
messageId,
|
|
@@ -300562,7 +300610,7 @@ var init_messages5 = __esm(() => {
|
|
|
300562
300610
|
});
|
|
300563
300611
|
}
|
|
300564
300612
|
} else {
|
|
300565
|
-
|
|
300613
|
+
log104.warn("Reaction target chat not found in DB; deferring fromMe to channel plugin fallback (#386)", {
|
|
300566
300614
|
instanceId,
|
|
300567
300615
|
resolvedTo,
|
|
300568
300616
|
messageId,
|
|
@@ -300862,7 +300910,7 @@ var init_messages5 = __esm(() => {
|
|
|
300862
300910
|
channelHandoffSupported: hasNativeHandoff,
|
|
300863
300911
|
...data.motivoHandoff ? { motivoHandoff: data.motivoHandoff } : {}
|
|
300864
300912
|
}
|
|
300865
|
-
}).catch((err) =>
|
|
300913
|
+
}).catch((err) => log104.warn("Failed to persist handoff log", { error: String(err) }));
|
|
300866
300914
|
return c.json({
|
|
300867
300915
|
data: {
|
|
300868
300916
|
messageId: channelSendResult?.messageId ?? null,
|
|
@@ -301378,7 +301426,7 @@ var init_messages5 = __esm(() => {
|
|
|
301378
301426
|
const message2 = await services.messages.getById(messageId);
|
|
301379
301427
|
await verifyMessageInstanceOwnership(services, message2, instanceId);
|
|
301380
301428
|
resolvedMessageId = message2.externalId;
|
|
301381
|
-
|
|
301429
|
+
log104.debug("Resolved internal UUID to external ID", { messageId, externalId: resolvedMessageId });
|
|
301382
301430
|
}
|
|
301383
301431
|
try {
|
|
301384
301432
|
await plugin7.editMessage(instanceId, channelId, resolvedMessageId, text3);
|
|
@@ -302078,6 +302126,36 @@ var init_settings3 = __esm(() => {
|
|
|
302078
302126
|
});
|
|
302079
302127
|
});
|
|
302080
302128
|
|
|
302129
|
+
// ../api/src/routes/v2/trust.ts
|
|
302130
|
+
var trustRoutes, PUBKEY_PATTERN, handshakeSchema;
|
|
302131
|
+
var init_trust = __esm(() => {
|
|
302132
|
+
init_dist6();
|
|
302133
|
+
init_dist2();
|
|
302134
|
+
init_zod();
|
|
302135
|
+
trustRoutes = new Hono2;
|
|
302136
|
+
PUBKEY_PATTERN = /^[A-Za-z0-9_-]{43}=?$/;
|
|
302137
|
+
handshakeSchema = exports_external.object({
|
|
302138
|
+
pubkey: exports_external.string().regex(PUBKEY_PATTERN, "pubkey must be base64url-encoded 32 bytes (ed25519 public key)"),
|
|
302139
|
+
hostname: exports_external.string().min(1).max(255),
|
|
302140
|
+
capabilities: exports_external.record(exports_external.unknown()).optional()
|
|
302141
|
+
});
|
|
302142
|
+
trustRoutes.post("/handshake", zValidator("json", handshakeSchema), async (c) => {
|
|
302143
|
+
const input = c.req.valid("json");
|
|
302144
|
+
const services = c.get("services");
|
|
302145
|
+
const existing = await services.genieHosts.findByPubkey(input.pubkey);
|
|
302146
|
+
if (existing) {
|
|
302147
|
+
return c.json({ data: existing }, 200);
|
|
302148
|
+
}
|
|
302149
|
+
const host = await services.genieHosts.register(input);
|
|
302150
|
+
return c.json({ data: host }, 201);
|
|
302151
|
+
});
|
|
302152
|
+
trustRoutes.get("/hosts", async (c) => {
|
|
302153
|
+
const services = c.get("services");
|
|
302154
|
+
const items = await services.genieHosts.listActive();
|
|
302155
|
+
return c.json({ items });
|
|
302156
|
+
});
|
|
302157
|
+
});
|
|
302158
|
+
|
|
302081
302159
|
// ../api/src/routes/v2/turns.ts
|
|
302082
302160
|
function requireAdmin(c) {
|
|
302083
302161
|
const keyData = c.get("apiKey");
|
|
@@ -302540,6 +302618,7 @@ var init_v2 = __esm(() => {
|
|
|
302540
302618
|
init_processed_events();
|
|
302541
302619
|
init_providers4();
|
|
302542
302620
|
init_settings3();
|
|
302621
|
+
init_trust();
|
|
302543
302622
|
init_turns2();
|
|
302544
302623
|
init_voice2();
|
|
302545
302624
|
init_webhooks3();
|
|
@@ -302568,6 +302647,7 @@ var init_v2 = __esm(() => {
|
|
|
302568
302647
|
v2Routes.route("/keys", keysRoutes);
|
|
302569
302648
|
v2Routes.route("/context", contextRoutes);
|
|
302570
302649
|
v2Routes.route("/turns", turnsRoutes);
|
|
302650
|
+
v2Routes.route("/trust", trustRoutes);
|
|
302571
302651
|
v2Routes.route("/", payloadsRoutes);
|
|
302572
302652
|
v2Routes.route("/", webhooksRoutes);
|
|
302573
302653
|
v2Routes.route("/automations", automationsRoutes);
|
|
@@ -303039,12 +303119,12 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
303039
303119
|
const tracker = getJourneyTracker();
|
|
303040
303120
|
tracker.recordCheckpoint(metadata.correlationId, "T4", JOURNEY_STAGES.T4);
|
|
303041
303121
|
}
|
|
303042
|
-
|
|
303122
|
+
log105.debug("Persisted message.received", {
|
|
303043
303123
|
externalId: payload.externalId,
|
|
303044
303124
|
instanceId: metadata.instanceId
|
|
303045
303125
|
});
|
|
303046
303126
|
} catch (error2) {
|
|
303047
|
-
|
|
303127
|
+
log105.error("Failed to persist message.received", {
|
|
303048
303128
|
externalId: payload.externalId,
|
|
303049
303129
|
error: String(error2)
|
|
303050
303130
|
});
|
|
@@ -303081,12 +303161,12 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
303081
303161
|
chatUuid
|
|
303082
303162
|
};
|
|
303083
303163
|
await db2.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
303084
|
-
|
|
303164
|
+
log105.debug("Persisted message.sent", {
|
|
303085
303165
|
externalId: payload.externalId,
|
|
303086
303166
|
instanceId: metadata.instanceId
|
|
303087
303167
|
});
|
|
303088
303168
|
} catch (error2) {
|
|
303089
|
-
|
|
303169
|
+
log105.error("Failed to persist message.sent", {
|
|
303090
303170
|
externalId: payload.externalId,
|
|
303091
303171
|
error: String(error2)
|
|
303092
303172
|
});
|
|
@@ -303119,11 +303199,11 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
303119
303199
|
};
|
|
303120
303200
|
await db2.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
303121
303201
|
}
|
|
303122
|
-
|
|
303202
|
+
log105.debug("Persisted message.delivered", {
|
|
303123
303203
|
externalId: payload.externalId
|
|
303124
303204
|
});
|
|
303125
303205
|
} catch (error2) {
|
|
303126
|
-
|
|
303206
|
+
log105.error("Failed to persist message.delivered", {
|
|
303127
303207
|
externalId: payload.externalId,
|
|
303128
303208
|
error: String(error2)
|
|
303129
303209
|
});
|
|
@@ -303155,11 +303235,11 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
303155
303235
|
};
|
|
303156
303236
|
await db2.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
303157
303237
|
}
|
|
303158
|
-
|
|
303238
|
+
log105.debug("Persisted message.read", {
|
|
303159
303239
|
externalId: payload.externalId
|
|
303160
303240
|
});
|
|
303161
303241
|
} catch (error2) {
|
|
303162
|
-
|
|
303242
|
+
log105.error("Failed to persist message.read", {
|
|
303163
303243
|
externalId: payload.externalId,
|
|
303164
303244
|
error: String(error2)
|
|
303165
303245
|
});
|
|
@@ -303192,29 +303272,29 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
303192
303272
|
chatUuid
|
|
303193
303273
|
};
|
|
303194
303274
|
await db2.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
303195
|
-
|
|
303275
|
+
log105.debug("Persisted message.failed", {
|
|
303196
303276
|
chatId: payload.chatId,
|
|
303197
303277
|
error: payload.error
|
|
303198
303278
|
});
|
|
303199
303279
|
} catch (error2) {
|
|
303200
|
-
|
|
303280
|
+
log105.error("Failed to persist message.failed", {
|
|
303201
303281
|
chatId: payload.chatId,
|
|
303202
303282
|
error: String(error2)
|
|
303203
303283
|
});
|
|
303204
303284
|
}
|
|
303205
303285
|
}, { ...CONSUMER_OPTIONS, durable: "event-persistence-failed" });
|
|
303206
|
-
|
|
303286
|
+
log105.info("Event persistence initialized - listening for message events");
|
|
303207
303287
|
} catch (error2) {
|
|
303208
|
-
|
|
303288
|
+
log105.error("Failed to set up event persistence", { error: String(error2) });
|
|
303209
303289
|
throw error2;
|
|
303210
303290
|
}
|
|
303211
303291
|
}
|
|
303212
|
-
var
|
|
303292
|
+
var log105, CONSUMER_OPTIONS;
|
|
303213
303293
|
var init_event_persistence = __esm(() => {
|
|
303214
303294
|
init_src();
|
|
303215
303295
|
init_src5();
|
|
303216
303296
|
init_drizzle_orm();
|
|
303217
|
-
|
|
303297
|
+
log105 = createLogger("event-persistence");
|
|
303218
303298
|
CONSUMER_OPTIONS = {
|
|
303219
303299
|
queue: "event-persistence",
|
|
303220
303300
|
maxRetries: 3,
|
|
@@ -303292,10 +303372,10 @@ async function downloadMediaFromUrl(ctx, instanceId, messageId, mediaUrl, mimeTy
|
|
|
303292
303372
|
try {
|
|
303293
303373
|
const result = await ctx.mediaStorage.storeFromUrl(instanceId, messageId, mediaUrl, mimeType, platformTimestamp, fetchOptions);
|
|
303294
303374
|
await ctx.mediaStorage.updateMessageLocalPath(messageId, result.localPath);
|
|
303295
|
-
|
|
303375
|
+
log106.debug("Downloaded media from URL", { messageId, filePath: result.localPath });
|
|
303296
303376
|
return result.localPath;
|
|
303297
303377
|
} catch (error2) {
|
|
303298
|
-
|
|
303378
|
+
log106.error("Failed to download media", { error: String(error2), mediaUrl });
|
|
303299
303379
|
return null;
|
|
303300
303380
|
}
|
|
303301
303381
|
}
|
|
@@ -303309,7 +303389,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
303309
303389
|
chat2 = await ctx.services.chats.findByExternalIdSmart(instanceId, chatId);
|
|
303310
303390
|
}
|
|
303311
303391
|
if (!chat2) {
|
|
303312
|
-
|
|
303392
|
+
log106.debug("Chat not found, cannot process media", { chatId, externalId });
|
|
303313
303393
|
return null;
|
|
303314
303394
|
}
|
|
303315
303395
|
let message2 = await ctx.services.messages.getByExternalId(chat2.id, externalId);
|
|
@@ -303318,7 +303398,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
303318
303398
|
message2 = await ctx.services.messages.getByExternalId(chat2.id, externalId);
|
|
303319
303399
|
}
|
|
303320
303400
|
if (!message2) {
|
|
303321
|
-
|
|
303401
|
+
log106.debug("Message not found after waiting, cannot process media", { externalId });
|
|
303322
303402
|
return null;
|
|
303323
303403
|
}
|
|
303324
303404
|
let filePath = message2.mediaLocalPath;
|
|
@@ -303328,7 +303408,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
303328
303408
|
return null;
|
|
303329
303409
|
}
|
|
303330
303410
|
if (!filePath) {
|
|
303331
|
-
|
|
303411
|
+
log106.debug("No media file path available", { externalId });
|
|
303332
303412
|
return null;
|
|
303333
303413
|
}
|
|
303334
303414
|
return {
|
|
@@ -303349,11 +303429,11 @@ async function resolveSafeMediaContentEventId(ctx, eventId) {
|
|
|
303349
303429
|
if (event)
|
|
303350
303430
|
return event.id;
|
|
303351
303431
|
} catch (error2) {
|
|
303352
|
-
|
|
303432
|
+
log106.debug("Failed to validate media_content event FK", { eventId, error: String(error2) });
|
|
303353
303433
|
return null;
|
|
303354
303434
|
}
|
|
303355
303435
|
if (Date.now() >= deadline) {
|
|
303356
|
-
|
|
303436
|
+
log106.debug("Skipping media_content event FK; omni_event not found", { eventId });
|
|
303357
303437
|
return null;
|
|
303358
303438
|
}
|
|
303359
303439
|
await new Promise((resolve4) => setTimeout(resolve4, pollMs));
|
|
@@ -303382,7 +303462,7 @@ async function persistProcessingResult(ctx, messageId, eventId, result, contentT
|
|
|
303382
303462
|
processingTimeMs: result.processingTimeMs
|
|
303383
303463
|
});
|
|
303384
303464
|
} catch (error2) {
|
|
303385
|
-
|
|
303465
|
+
log106.warn("Failed to insert media_content record (non-critical)", {
|
|
303386
303466
|
messageId,
|
|
303387
303467
|
error: String(error2)
|
|
303388
303468
|
});
|
|
@@ -303402,13 +303482,13 @@ async function processMessageMedia(ctx, payload, metadata) {
|
|
|
303402
303482
|
const { content, externalId } = payload;
|
|
303403
303483
|
const mimeType = getMimeType2(content);
|
|
303404
303484
|
if (!mimeType || !ctx.mediaService.canProcess(mimeType)) {
|
|
303405
|
-
|
|
303485
|
+
log106.debug("MIME type not processable or missing", { mimeType, externalId });
|
|
303406
303486
|
return;
|
|
303407
303487
|
}
|
|
303408
303488
|
const media = await resolveMediaPath2(ctx, instanceId, payload.chatId, externalId, content, mimeType, metadata.channelType);
|
|
303409
303489
|
if (!media)
|
|
303410
303490
|
return;
|
|
303411
|
-
|
|
303491
|
+
log106.info("Processing media", { messageId: media.messageId, mimeType, filePath: media.fullPath });
|
|
303412
303492
|
const result = await ctx.mediaService.process(media.fullPath, mimeType, {
|
|
303413
303493
|
language: "pt",
|
|
303414
303494
|
caption: content.text,
|
|
@@ -303416,7 +303496,7 @@ async function processMessageMedia(ctx, payload, metadata) {
|
|
|
303416
303496
|
});
|
|
303417
303497
|
if (!result.success) {
|
|
303418
303498
|
const reason = result.errorMessage ?? "unknown";
|
|
303419
|
-
|
|
303499
|
+
log106.warn("Media processing failed", { messageId: media.messageId, error: reason });
|
|
303420
303500
|
const processingType = result.processingType ?? inferProcessingType(content.type);
|
|
303421
303501
|
const errorColumn = getContentFieldForType(processingType, content.type);
|
|
303422
303502
|
if (errorColumn) {
|
|
@@ -303441,7 +303521,7 @@ async function processMessageMedia(ctx, payload, metadata) {
|
|
|
303441
303521
|
return;
|
|
303442
303522
|
}
|
|
303443
303523
|
await persistProcessingResult(ctx, media.messageId, eventId, result, content.type);
|
|
303444
|
-
|
|
303524
|
+
log106.info("Media processing complete", {
|
|
303445
303525
|
messageId: media.messageId,
|
|
303446
303526
|
processingType: result.processingType,
|
|
303447
303527
|
provider: result.provider,
|
|
@@ -303481,7 +303561,7 @@ async function publishMediaCrashEvents(ctx, eventId, payload, metadata, error2)
|
|
|
303481
303561
|
error: reason
|
|
303482
303562
|
}, meta);
|
|
303483
303563
|
} catch (publishError) {
|
|
303484
|
-
|
|
303564
|
+
log106.error("Failed to publish media failure event", { error: String(publishError) });
|
|
303485
303565
|
}
|
|
303486
303566
|
}
|
|
303487
303567
|
async function resolveMediaIdForCrash(ctx, instanceId, payload) {
|
|
@@ -303493,7 +303573,7 @@ async function resolveMediaIdForCrash(ctx, instanceId, payload) {
|
|
|
303493
303573
|
return msg.id;
|
|
303494
303574
|
}
|
|
303495
303575
|
} catch (lookupError) {
|
|
303496
|
-
|
|
303576
|
+
log106.debug("Failed to resolve DB message UUID for crash handler, falling back to externalId", {
|
|
303497
303577
|
error: String(lookupError),
|
|
303498
303578
|
instanceId,
|
|
303499
303579
|
chatId: payload.chatId
|
|
@@ -303544,7 +303624,7 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
303544
303624
|
channelType: metadata.channelType
|
|
303545
303625
|
});
|
|
303546
303626
|
} catch (error2) {
|
|
303547
|
-
|
|
303627
|
+
log106.error("Failed to process media", {
|
|
303548
303628
|
externalId: payload.externalId,
|
|
303549
303629
|
error: String(error2)
|
|
303550
303630
|
});
|
|
@@ -303559,14 +303639,14 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
303559
303639
|
concurrency: 5
|
|
303560
303640
|
});
|
|
303561
303641
|
setGlobalCircuitBreakerStateChangeCallback((name, from, to) => {
|
|
303562
|
-
|
|
303642
|
+
log106.warn("Circuit breaker state change", { provider: name, from, to });
|
|
303563
303643
|
});
|
|
303564
303644
|
await eventBus.subscribePattern("media.health.request", async (event) => {
|
|
303565
303645
|
const tracker = getMediaHealthTracker();
|
|
303566
303646
|
const report = tracker.getReport();
|
|
303567
303647
|
const correlationId = event.metadata?.correlationId ?? event.id;
|
|
303568
303648
|
await eventBus.publishGeneric("system.media.health.response", { correlationId, report }, { source: "media-processor" });
|
|
303569
|
-
|
|
303649
|
+
log106.debug("Published media health report", {
|
|
303570
303650
|
correlationId,
|
|
303571
303651
|
totalRequests: report.overall.totalRequests,
|
|
303572
303652
|
successRate: report.overall.successRate
|
|
@@ -303575,16 +303655,16 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
303575
303655
|
durable: "media-health-responder",
|
|
303576
303656
|
queue: "media-health-responder"
|
|
303577
303657
|
});
|
|
303578
|
-
|
|
303658
|
+
log106.info("Media processor initialized");
|
|
303579
303659
|
}
|
|
303580
|
-
var
|
|
303660
|
+
var log106, PROCESSABLE_MEDIA_TYPES;
|
|
303581
303661
|
var init_media_processor = __esm(() => {
|
|
303582
303662
|
init_src();
|
|
303583
303663
|
init_src5();
|
|
303584
303664
|
init_src7();
|
|
303585
303665
|
init_drizzle_orm();
|
|
303586
303666
|
init_media_storage();
|
|
303587
|
-
|
|
303667
|
+
log106 = createLogger("media-processor");
|
|
303588
303668
|
PROCESSABLE_MEDIA_TYPES = new Set(["audio", "image", "document", "video"]);
|
|
303589
303669
|
});
|
|
303590
303670
|
|
|
@@ -303656,7 +303736,7 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
303656
303736
|
await eventBus.subscribe("sync.started", async (event) => {
|
|
303657
303737
|
const payload = event.payload;
|
|
303658
303738
|
const { jobId, instanceId, type, config: config4 } = payload;
|
|
303659
|
-
|
|
303739
|
+
log107.info("Processing sync job", { jobId, instanceId, type });
|
|
303660
303740
|
try {
|
|
303661
303741
|
await services.syncJobs.start(jobId);
|
|
303662
303742
|
const instance4 = await services.instances.getById(instanceId);
|
|
@@ -303683,12 +303763,12 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
303683
303763
|
case "history-push":
|
|
303684
303764
|
break;
|
|
303685
303765
|
default:
|
|
303686
|
-
|
|
303766
|
+
log107.warn("Unknown sync type", { jobId, type });
|
|
303687
303767
|
await services.syncJobs.fail(jobId, `Unknown sync type: ${type}`);
|
|
303688
303768
|
}
|
|
303689
303769
|
} catch (error2) {
|
|
303690
303770
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
303691
|
-
|
|
303771
|
+
log107.error("Sync job failed", { jobId, error: errorMessage });
|
|
303692
303772
|
await services.syncJobs.fail(jobId, errorMessage);
|
|
303693
303773
|
}
|
|
303694
303774
|
}, {
|
|
@@ -303696,15 +303776,15 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
303696
303776
|
queue: "sync-workers",
|
|
303697
303777
|
startFrom: "new"
|
|
303698
303778
|
});
|
|
303699
|
-
|
|
303779
|
+
log107.info("Sync worker initialized - listening for sync.started events");
|
|
303700
303780
|
} catch (error2) {
|
|
303701
|
-
|
|
303781
|
+
log107.error("Failed to set up sync worker", { error: String(error2) });
|
|
303702
303782
|
throw error2;
|
|
303703
303783
|
}
|
|
303704
303784
|
}
|
|
303705
303785
|
async function buildWhatsAppAnchors(instanceId, _services) {
|
|
303706
303786
|
if (!db2) {
|
|
303707
|
-
|
|
303787
|
+
log107.warn("Database not available for building anchors");
|
|
303708
303788
|
return [];
|
|
303709
303789
|
}
|
|
303710
303790
|
const result = await db2.execute(sql`
|
|
@@ -303740,20 +303820,20 @@ async function buildWhatsAppAnchors(instanceId, _services) {
|
|
|
303740
303820
|
});
|
|
303741
303821
|
}
|
|
303742
303822
|
}
|
|
303743
|
-
|
|
303823
|
+
log107.info("Built WhatsApp anchors", { instanceId, anchorCount: anchors.length });
|
|
303744
303824
|
return anchors;
|
|
303745
303825
|
}
|
|
303746
303826
|
function buildAnchorsForExplicitChatJids(jobId, chatJids, dbAnchors) {
|
|
303747
|
-
|
|
303827
|
+
log107.info("Using explicit chatJids for sync", { jobId, chatJids });
|
|
303748
303828
|
const anchors = [];
|
|
303749
303829
|
for (const jid of chatJids) {
|
|
303750
303830
|
const dbAnchor = dbAnchors.find((a3) => a3.chatJid === jid);
|
|
303751
303831
|
if (dbAnchor) {
|
|
303752
|
-
|
|
303832
|
+
log107.debug("Found DB anchor for chatJid", { jobId, chatJid: jid, anchorId: dbAnchor.messageKey.id });
|
|
303753
303833
|
anchors.push(dbAnchor);
|
|
303754
303834
|
continue;
|
|
303755
303835
|
}
|
|
303756
|
-
|
|
303836
|
+
log107.debug("No DB anchor for chatJid, will fetch recent", { jobId, chatJid: jid });
|
|
303757
303837
|
anchors.push({
|
|
303758
303838
|
chatJid: jid,
|
|
303759
303839
|
messageKey: { remoteJid: jid, id: "", fromMe: false },
|
|
@@ -303779,7 +303859,7 @@ async function discoverAnchorsFromPlugin(jobId, instanceId, plugin7, dbAnchors,
|
|
|
303779
303859
|
discovered.push({ chatJid: jid, messageKey: { remoteJid: jid, id: "", fromMe: false }, timestamp: Date.now() });
|
|
303780
303860
|
}
|
|
303781
303861
|
if (discovered.length > 0) {
|
|
303782
|
-
|
|
303862
|
+
log107.info("Discovered chats from DB + Baileys not in anchors", {
|
|
303783
303863
|
jobId,
|
|
303784
303864
|
discoveredCount: discovered.length,
|
|
303785
303865
|
fromDb: dbExternalIds.length,
|
|
@@ -303800,7 +303880,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303800
303880
|
throw new Error(`No plugin found for channel type: ${channelType}`);
|
|
303801
303881
|
}
|
|
303802
303882
|
if (!("fetchHistory" in plugin7) || typeof plugin7.fetchHistory !== "function") {
|
|
303803
|
-
|
|
303883
|
+
log107.warn("Plugin does not support fetchHistory", { channelType });
|
|
303804
303884
|
await services.syncJobs.complete(jobId);
|
|
303805
303885
|
return;
|
|
303806
303886
|
}
|
|
@@ -303809,7 +303889,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303809
303889
|
let fetched = 0;
|
|
303810
303890
|
let stored = 0;
|
|
303811
303891
|
let duplicates = 0;
|
|
303812
|
-
|
|
303892
|
+
log107.info("Starting message sync", {
|
|
303813
303893
|
jobId,
|
|
303814
303894
|
instanceId,
|
|
303815
303895
|
channelType,
|
|
@@ -303819,13 +303899,13 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303819
303899
|
if (channelType === "whatsapp-baileys" && config4.chatJids?.length) {
|
|
303820
303900
|
const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
|
|
303821
303901
|
anchors = await resolveWhatsAppAnchors(jobId, instanceId, config4, plugin7, dbAnchors, services);
|
|
303822
|
-
|
|
303902
|
+
log107.info("WhatsApp per-chat active sync", { jobId, anchorCount: anchors.length, chatJids: config4.chatJids });
|
|
303823
303903
|
} else if (channelType === "whatsapp-baileys") {
|
|
303824
303904
|
const dbAnchors = await buildWhatsAppAnchors(instanceId, services);
|
|
303825
303905
|
const discoveredAnchors = await discoverAnchorsFromPlugin(jobId, instanceId, plugin7, dbAnchors, services);
|
|
303826
303906
|
anchors = [...dbAnchors, ...discoveredAnchors];
|
|
303827
303907
|
if (anchors.length > 0) {
|
|
303828
|
-
|
|
303908
|
+
log107.info("WhatsApp default sync with DB+cache discovery", {
|
|
303829
303909
|
jobId,
|
|
303830
303910
|
instanceId,
|
|
303831
303911
|
dbAnchorCount: dbAnchors.length,
|
|
@@ -303833,7 +303913,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303833
303913
|
totalAnchors: anchors.length
|
|
303834
303914
|
});
|
|
303835
303915
|
} else {
|
|
303836
|
-
|
|
303916
|
+
log107.info("WhatsApp passive sync (no prior data)", { jobId, instanceId });
|
|
303837
303917
|
}
|
|
303838
303918
|
}
|
|
303839
303919
|
const fetchOptions = {
|
|
@@ -303875,7 +303955,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303875
303955
|
});
|
|
303876
303956
|
stored++;
|
|
303877
303957
|
} catch (error2) {
|
|
303878
|
-
|
|
303958
|
+
log107.warn("Failed to store synced message", {
|
|
303879
303959
|
externalId: msg.externalId,
|
|
303880
303960
|
error: String(error2)
|
|
303881
303961
|
});
|
|
@@ -303892,7 +303972,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
303892
303972
|
duplicates
|
|
303893
303973
|
});
|
|
303894
303974
|
await services.syncJobs.complete(jobId);
|
|
303895
|
-
|
|
303975
|
+
log107.info("Message sync completed", {
|
|
303896
303976
|
jobId,
|
|
303897
303977
|
fetched,
|
|
303898
303978
|
stored,
|
|
@@ -303939,14 +304019,14 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
303939
304019
|
throw new Error(`No plugin found for channel type: ${channelType}`);
|
|
303940
304020
|
}
|
|
303941
304021
|
if (!("fetchContacts" in plugin7) || typeof plugin7.fetchContacts !== "function") {
|
|
303942
|
-
|
|
304022
|
+
log107.warn("Plugin does not support fetchContacts", { channelType });
|
|
303943
304023
|
await services.syncJobs.complete(jobId);
|
|
303944
304024
|
return;
|
|
303945
304025
|
}
|
|
303946
304026
|
let fetched = 0;
|
|
303947
304027
|
let stored = 0;
|
|
303948
304028
|
let linked = 0;
|
|
303949
|
-
|
|
304029
|
+
log107.info("Starting contacts sync", {
|
|
303950
304030
|
jobId,
|
|
303951
304031
|
instanceId,
|
|
303952
304032
|
channelType
|
|
@@ -303985,7 +304065,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
303985
304065
|
await updateDmChatName(services, instanceId, c.platformUserId, c.name);
|
|
303986
304066
|
}
|
|
303987
304067
|
} catch (error2) {
|
|
303988
|
-
|
|
304068
|
+
log107.warn("Failed to store synced contact", {
|
|
303989
304069
|
platformUserId: c.platformUserId,
|
|
303990
304070
|
error: String(error2)
|
|
303991
304071
|
});
|
|
@@ -304002,7 +304082,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
304002
304082
|
duplicates: 0
|
|
304003
304083
|
});
|
|
304004
304084
|
await services.syncJobs.complete(jobId);
|
|
304005
|
-
|
|
304085
|
+
log107.info("Contacts sync completed", {
|
|
304006
304086
|
jobId,
|
|
304007
304087
|
fetched,
|
|
304008
304088
|
stored,
|
|
@@ -304016,7 +304096,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
304016
304096
|
}
|
|
304017
304097
|
const fetchMethod = channelType === "discord" ? "fetchGuilds" : "fetchGroups";
|
|
304018
304098
|
if (!(fetchMethod in plugin7) || typeof plugin7[fetchMethod] !== "function") {
|
|
304019
|
-
|
|
304099
|
+
log107.warn(`Plugin does not support ${fetchMethod}`, { channelType });
|
|
304020
304100
|
await services.syncJobs.complete(jobId);
|
|
304021
304101
|
return;
|
|
304022
304102
|
}
|
|
@@ -304027,7 +304107,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
304027
304107
|
let fetched = 0;
|
|
304028
304108
|
let stored = 0;
|
|
304029
304109
|
let updated = 0;
|
|
304030
|
-
|
|
304110
|
+
log107.info("Starting groups sync", {
|
|
304031
304111
|
jobId,
|
|
304032
304112
|
instanceId,
|
|
304033
304113
|
channelType
|
|
@@ -304077,7 +304157,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
304077
304157
|
stored++;
|
|
304078
304158
|
}
|
|
304079
304159
|
} catch (error2) {
|
|
304080
|
-
|
|
304160
|
+
log107.warn("Failed to store synced group", {
|
|
304081
304161
|
externalId: g2.externalId,
|
|
304082
304162
|
error: String(error2)
|
|
304083
304163
|
});
|
|
@@ -304118,7 +304198,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
304118
304198
|
stored++;
|
|
304119
304199
|
}
|
|
304120
304200
|
} catch (error2) {
|
|
304121
|
-
|
|
304201
|
+
log107.warn("Failed to store synced guild", {
|
|
304122
304202
|
externalId: g2.externalId,
|
|
304123
304203
|
error: String(error2)
|
|
304124
304204
|
});
|
|
@@ -304133,7 +304213,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
304133
304213
|
duplicates: updated
|
|
304134
304214
|
});
|
|
304135
304215
|
await services.syncJobs.complete(jobId);
|
|
304136
|
-
|
|
304216
|
+
log107.info("Groups sync completed", {
|
|
304137
304217
|
jobId,
|
|
304138
304218
|
fetched,
|
|
304139
304219
|
stored,
|
|
@@ -304250,12 +304330,12 @@ async function setupHistoryPushTracker(eventBus, services) {
|
|
|
304250
304330
|
throw error2;
|
|
304251
304331
|
}
|
|
304252
304332
|
}
|
|
304253
|
-
var
|
|
304333
|
+
var log107, RATE_LIMITS2, db2 = null, historyPushLog;
|
|
304254
304334
|
var init_sync_worker = __esm(() => {
|
|
304255
304335
|
init_src();
|
|
304256
304336
|
init_src5();
|
|
304257
304337
|
init_drizzle_orm();
|
|
304258
|
-
|
|
304338
|
+
log107 = createLogger("sync-worker");
|
|
304259
304339
|
RATE_LIMITS2 = {
|
|
304260
304340
|
"whatsapp-baileys": 30,
|
|
304261
304341
|
discord: 50,
|
|
@@ -304270,7 +304350,7 @@ async function resolveChatId2(services, instanceId, externalId) {
|
|
|
304270
304350
|
const chat2 = await services.chats.findByExternalIdSmart(instanceId, externalId);
|
|
304271
304351
|
return chat2?.id ?? null;
|
|
304272
304352
|
} catch (err) {
|
|
304273
|
-
|
|
304353
|
+
log108.warn("follow-up-hooks: failed to resolve chatId", { instanceId, externalId, error: String(err) });
|
|
304274
304354
|
return null;
|
|
304275
304355
|
}
|
|
304276
304356
|
}
|
|
@@ -304359,15 +304439,15 @@ async function setupFollowUpHooks(eventBus, services) {
|
|
|
304359
304439
|
retryDelayMs: 500,
|
|
304360
304440
|
startFrom: "new"
|
|
304361
304441
|
});
|
|
304362
|
-
|
|
304442
|
+
log108.info("Follow-up hooks active (message.sent/received, chat.handoff_activated, chat.archived)");
|
|
304363
304443
|
} catch (error2) {
|
|
304364
|
-
|
|
304444
|
+
log108.error("Failed to set up follow-up hooks", { error: String(error2) });
|
|
304365
304445
|
}
|
|
304366
304446
|
}
|
|
304367
|
-
var
|
|
304447
|
+
var log108;
|
|
304368
304448
|
var init_follow_up_hooks = __esm(() => {
|
|
304369
304449
|
init_src();
|
|
304370
|
-
|
|
304450
|
+
log108 = createLogger("follow-up-hooks");
|
|
304371
304451
|
});
|
|
304372
304452
|
|
|
304373
304453
|
// ../api/src/plugins/instance-monitor.ts
|
|
@@ -304807,7 +304887,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304807
304887
|
recordScheduledJob("dead-letter-auto-retry", "success", durationSec);
|
|
304808
304888
|
const pendingCount = await services.deadLetters.getPendingCount();
|
|
304809
304889
|
deadLettersPending.set(pendingCount);
|
|
304810
|
-
|
|
304890
|
+
log109.info("Dead letter auto-retry completed", result);
|
|
304811
304891
|
} catch (err) {
|
|
304812
304892
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304813
304893
|
recordScheduledJob("dead-letter-auto-retry", "failure", durationSec);
|
|
@@ -304829,7 +304909,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304829
304909
|
recordScheduledJob("payload-cleanup", "success", durationSec);
|
|
304830
304910
|
const stats = await services.payloadStore.getStats();
|
|
304831
304911
|
payloadStorageSize.set(stats.totalSizeCompressed);
|
|
304832
|
-
|
|
304912
|
+
log109.info("Payload cleanup completed", { deleted });
|
|
304833
304913
|
} catch (err) {
|
|
304834
304914
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304835
304915
|
recordScheduledJob("payload-cleanup", "failure", durationSec);
|
|
@@ -304849,7 +304929,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304849
304929
|
const deleted = await services.deadLetters.cleanupExpired();
|
|
304850
304930
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304851
304931
|
recordScheduledJob("dead-letter-cleanup", "success", durationSec);
|
|
304852
|
-
|
|
304932
|
+
log109.info("Dead letter cleanup completed", { deleted });
|
|
304853
304933
|
} catch (err) {
|
|
304854
304934
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304855
304935
|
recordScheduledJob("dead-letter-cleanup", "failure", durationSec);
|
|
@@ -304878,7 +304958,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304878
304958
|
});
|
|
304879
304959
|
jobsCreated++;
|
|
304880
304960
|
} catch (err) {
|
|
304881
|
-
|
|
304961
|
+
log109.warn("Failed to create contacts sync job for instance", {
|
|
304882
304962
|
instanceId: instance4.id,
|
|
304883
304963
|
error: String(err)
|
|
304884
304964
|
});
|
|
@@ -304886,7 +304966,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304886
304966
|
}
|
|
304887
304967
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304888
304968
|
recordScheduledJob("contacts-sync-daily", "success", durationSec);
|
|
304889
|
-
|
|
304969
|
+
log109.info("Daily contacts sync jobs created", { jobsCreated, instanceCount: instances2.length });
|
|
304890
304970
|
} catch (err) {
|
|
304891
304971
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304892
304972
|
recordScheduledJob("contacts-sync-daily", "failure", durationSec);
|
|
@@ -304915,7 +304995,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304915
304995
|
});
|
|
304916
304996
|
jobsCreated++;
|
|
304917
304997
|
} catch (err) {
|
|
304918
|
-
|
|
304998
|
+
log109.warn("Failed to create groups sync job for instance", {
|
|
304919
304999
|
instanceId: instance4.id,
|
|
304920
305000
|
error: String(err)
|
|
304921
305001
|
});
|
|
@@ -304923,7 +305003,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304923
305003
|
}
|
|
304924
305004
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304925
305005
|
recordScheduledJob("groups-sync-daily", "success", durationSec);
|
|
304926
|
-
|
|
305006
|
+
log109.info("Daily groups sync jobs created", { jobsCreated, instanceCount: instances2.length });
|
|
304927
305007
|
} catch (err) {
|
|
304928
305008
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304929
305009
|
recordScheduledJob("groups-sync-daily", "failure", durationSec);
|
|
@@ -304944,7 +305024,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304944
305024
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304945
305025
|
recordScheduledJob("follow-up-sweeper", "success", durationSec);
|
|
304946
305026
|
if (stats.scanned > 0) {
|
|
304947
|
-
|
|
305027
|
+
log109.debug("Follow-up sweep tick", stats);
|
|
304948
305028
|
}
|
|
304949
305029
|
} catch (err) {
|
|
304950
305030
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
@@ -304974,7 +305054,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304974
305054
|
}
|
|
304975
305055
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304976
305056
|
recordScheduledJob("unread-count-refresh", "success", durationSec);
|
|
304977
|
-
|
|
305057
|
+
log109.debug("Refreshed unread counts", { instanceCount: waInstances.length });
|
|
304978
305058
|
} catch (err) {
|
|
304979
305059
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
304980
305060
|
recordScheduledJob("unread-count-refresh", "failure", durationSec);
|
|
@@ -304985,7 +305065,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
304985
305065
|
});
|
|
304986
305066
|
updateSchedulerMetrics();
|
|
304987
305067
|
scheduler.start();
|
|
304988
|
-
|
|
305068
|
+
log109.info("Scheduler started", {
|
|
304989
305069
|
jobs: scheduler.listJobs().map((j) => ({
|
|
304990
305070
|
name: j.name,
|
|
304991
305071
|
cron: j.cron,
|
|
@@ -305005,14 +305085,14 @@ function updateSchedulerMetrics() {
|
|
|
305005
305085
|
function stopScheduler() {
|
|
305006
305086
|
const scheduler = getScheduler();
|
|
305007
305087
|
scheduler.stop();
|
|
305008
|
-
|
|
305088
|
+
log109.info("Scheduler stopped");
|
|
305009
305089
|
}
|
|
305010
|
-
var
|
|
305090
|
+
var log109;
|
|
305011
305091
|
var init_scheduler2 = __esm(() => {
|
|
305012
305092
|
init_src();
|
|
305013
305093
|
init_esm5();
|
|
305014
305094
|
init_sentry_scrub();
|
|
305015
|
-
|
|
305095
|
+
log109 = createLogger("scheduler:setup");
|
|
305016
305096
|
});
|
|
305017
305097
|
|
|
305018
305098
|
// ../api/src/services/turn-monitor.ts
|
|
@@ -305026,7 +305106,7 @@ class TurnMonitor {
|
|
|
305026
305106
|
start() {
|
|
305027
305107
|
if (this.intervalId)
|
|
305028
305108
|
return;
|
|
305029
|
-
|
|
305109
|
+
log110.info("Turn monitor started", {
|
|
305030
305110
|
pollIntervalMs: POLL_INTERVAL_MS2,
|
|
305031
305111
|
nudgeMs: NUDGE_THRESHOLD_MS,
|
|
305032
305112
|
defaultStalledMs: DEFAULT_STALLED_THRESHOLD_MS,
|
|
@@ -305038,7 +305118,7 @@ class TurnMonitor {
|
|
|
305038
305118
|
if (this.intervalId) {
|
|
305039
305119
|
clearInterval(this.intervalId);
|
|
305040
305120
|
this.intervalId = null;
|
|
305041
|
-
|
|
305121
|
+
log110.info("Turn monitor stopped");
|
|
305042
305122
|
}
|
|
305043
305123
|
}
|
|
305044
305124
|
async tick() {
|
|
@@ -305066,7 +305146,7 @@ class TurnMonitor {
|
|
|
305066
305146
|
}
|
|
305067
305147
|
}
|
|
305068
305148
|
} catch (error2) {
|
|
305069
|
-
|
|
305149
|
+
log110.error("Turn monitor tick failed", { error: String(error2) });
|
|
305070
305150
|
} finally {
|
|
305071
305151
|
this.running = false;
|
|
305072
305152
|
}
|
|
@@ -305079,13 +305159,13 @@ class TurnMonitor {
|
|
|
305079
305159
|
idleSec,
|
|
305080
305160
|
message: `Turn idle for ${idleSec}s. Are you still working?`
|
|
305081
305161
|
});
|
|
305082
|
-
|
|
305162
|
+
log110.info("Turn nudge emitted", { turnId, nudgeCount, idleSec });
|
|
305083
305163
|
}
|
|
305084
305164
|
async handleStalled(turnId, instanceId, chatId, stalledAtMs, threshold) {
|
|
305085
305165
|
await this.deps.turnService.incrementNudge(turnId);
|
|
305086
305166
|
const payload = { turnId, instanceId, chatId, stalledAtMs, threshold };
|
|
305087
305167
|
publishTurnStalled(instanceId, chatId, payload);
|
|
305088
|
-
|
|
305168
|
+
log110.warn("Turn stalled \u2014 internal event emitted (no channel message sent)", payload);
|
|
305089
305169
|
}
|
|
305090
305170
|
async handleTimeout(turnId, instanceId, chatId, idleSec, nudgeCount) {
|
|
305091
305171
|
const closed = await this.deps.turnService.close(turnId, {
|
|
@@ -305108,14 +305188,14 @@ class TurnMonitor {
|
|
|
305108
305188
|
nudgeCount,
|
|
305109
305189
|
messagesSent: closed.messagesSent
|
|
305110
305190
|
});
|
|
305111
|
-
|
|
305191
|
+
log110.info("Turn force-closed (timeout)", { turnId, duration, nudgeCount });
|
|
305112
305192
|
}
|
|
305113
305193
|
}
|
|
305114
|
-
var
|
|
305194
|
+
var log110, NUDGE_THRESHOLD_MS = 120000, DEFAULT_STALLED_THRESHOLD_MS = 600000, TIMEOUT_THRESHOLD_MS = 1800000, POLL_INTERVAL_MS2 = 1e4;
|
|
305115
305195
|
var init_turn_monitor = __esm(() => {
|
|
305116
305196
|
init_src();
|
|
305117
305197
|
init_turn_events();
|
|
305118
|
-
|
|
305198
|
+
log110 = createLogger("turn-monitor");
|
|
305119
305199
|
});
|
|
305120
305200
|
|
|
305121
305201
|
// ../api/src/utils/startup-banner.ts
|
|
@@ -305189,12 +305269,12 @@ function printStartupBanner(options) {
|
|
|
305189
305269
|
process.stdout.write(`${line3}
|
|
305190
305270
|
`);
|
|
305191
305271
|
}
|
|
305192
|
-
|
|
305272
|
+
log111.info("Server ready", { host, port, version: version4 });
|
|
305193
305273
|
}
|
|
305194
|
-
var
|
|
305274
|
+
var log111, COLORS3, BOX, ANSI_ESCAPE_PATTERN;
|
|
305195
305275
|
var init_startup_banner = __esm(() => {
|
|
305196
305276
|
init_src();
|
|
305197
|
-
|
|
305277
|
+
log111 = createLogger("api:startup");
|
|
305198
305278
|
COLORS3 = {
|
|
305199
305279
|
reset: "\x1B[0m",
|
|
305200
305280
|
dim: "\x1B[2m",
|
|
@@ -305252,7 +305332,7 @@ class VoiceStreamRegistry {
|
|
|
305252
305332
|
clients = new Map;
|
|
305253
305333
|
add(ws, client) {
|
|
305254
305334
|
this.clients.set(ws, client);
|
|
305255
|
-
|
|
305335
|
+
log112.info("Voice WS client connected", {
|
|
305256
305336
|
sessionId: client.params.sessionId,
|
|
305257
305337
|
format: client.params.format,
|
|
305258
305338
|
filterUser: client.params.filterUserId ?? "all"
|
|
@@ -305317,11 +305397,11 @@ function parseVoiceStreamParams(url) {
|
|
|
305317
305397
|
return null;
|
|
305318
305398
|
return { sessionId, apiKey, format: format === "pcm" ? "pcm" : "opus", filterUserId };
|
|
305319
305399
|
}
|
|
305320
|
-
var
|
|
305400
|
+
var log112, opusCodec = null;
|
|
305321
305401
|
var init_voice3 = __esm(() => {
|
|
305322
305402
|
init_src();
|
|
305323
305403
|
init_src3();
|
|
305324
|
-
|
|
305404
|
+
log112 = createLogger("ws:voice");
|
|
305325
305405
|
});
|
|
305326
305406
|
|
|
305327
305407
|
// ../api/src/index.ts
|
|
@@ -305555,7 +305635,7 @@ async function resolveCallAgentChatIds(services, ctx) {
|
|
|
305555
305635
|
senderId: ctx.senderId === ctx.chatId ? chat2.externalId : ctx.senderId
|
|
305556
305636
|
};
|
|
305557
305637
|
} catch {
|
|
305558
|
-
|
|
305638
|
+
log113.warn("call_agent: chat UUID not resolvable, using raw value (session may diverge)", {
|
|
305559
305639
|
chatId: ctx.chatId,
|
|
305560
305640
|
instanceId: ctx.instanceId
|
|
305561
305641
|
});
|
|
@@ -305564,23 +305644,23 @@ async function resolveCallAgentChatIds(services, ctx) {
|
|
|
305564
305644
|
}
|
|
305565
305645
|
async function setupEventBusServices(eventBus, services, db3) {
|
|
305566
305646
|
if (!eventBus) {
|
|
305567
|
-
|
|
305647
|
+
log113.warn("Skipping event bus services (no event bus)");
|
|
305568
305648
|
return;
|
|
305569
305649
|
}
|
|
305570
305650
|
try {
|
|
305571
305651
|
await setupMessagePersistence(eventBus, services);
|
|
305572
305652
|
} catch (error2) {
|
|
305573
|
-
|
|
305653
|
+
log113.error("Failed to set up message persistence", { error: String(error2) });
|
|
305574
305654
|
}
|
|
305575
305655
|
try {
|
|
305576
305656
|
await setupMediaProcessor(eventBus, db3, services);
|
|
305577
305657
|
} catch (error2) {
|
|
305578
|
-
|
|
305658
|
+
log113.error("Failed to set up media processor", { error: String(error2) });
|
|
305579
305659
|
}
|
|
305580
305660
|
try {
|
|
305581
305661
|
globalDispatcherCleanup = await setupAgentResponder(eventBus, services, db3);
|
|
305582
305662
|
} catch (error2) {
|
|
305583
|
-
|
|
305663
|
+
log113.error("Failed to set up agent dispatcher", { error: String(error2) });
|
|
305584
305664
|
}
|
|
305585
305665
|
try {
|
|
305586
305666
|
await services.automations.startEngine({
|
|
@@ -305656,34 +305736,34 @@ async function setupEventBusServices(eventBus, services, db3) {
|
|
|
305656
305736
|
}
|
|
305657
305737
|
});
|
|
305658
305738
|
} catch (error2) {
|
|
305659
|
-
|
|
305739
|
+
log113.error("Failed to start automation engine", { error: String(error2) });
|
|
305660
305740
|
}
|
|
305661
305741
|
try {
|
|
305662
305742
|
await setupSessionCleaner(eventBus, services, db3);
|
|
305663
305743
|
} catch (error2) {
|
|
305664
|
-
|
|
305744
|
+
log113.error("Failed to set up session cleaner", { error: String(error2) });
|
|
305665
305745
|
}
|
|
305666
305746
|
try {
|
|
305667
305747
|
await setupFollowUpHooks(eventBus, services);
|
|
305668
305748
|
} catch (error2) {
|
|
305669
|
-
|
|
305749
|
+
log113.error("Failed to set up follow-up hooks", { error: String(error2) });
|
|
305670
305750
|
}
|
|
305671
305751
|
if (globalChannelRegistry) {
|
|
305672
305752
|
try {
|
|
305673
305753
|
await setupSyncWorker(eventBus, services, globalChannelRegistry, db3);
|
|
305674
305754
|
} catch (error2) {
|
|
305675
|
-
|
|
305755
|
+
log113.error("Failed to set up sync worker", { error: String(error2) });
|
|
305676
305756
|
}
|
|
305677
305757
|
}
|
|
305678
305758
|
try {
|
|
305679
305759
|
await setupHistoryPushTracker(eventBus, services);
|
|
305680
305760
|
} catch (error2) {
|
|
305681
|
-
|
|
305761
|
+
log113.error("Failed to set up history-push tracker", { error: String(error2) });
|
|
305682
305762
|
}
|
|
305683
305763
|
try {
|
|
305684
305764
|
await initTurnEvents(NATS_URL);
|
|
305685
305765
|
} catch (error2) {
|
|
305686
|
-
|
|
305766
|
+
log113.error("Failed to initialize turn events", { error: String(error2) });
|
|
305687
305767
|
}
|
|
305688
305768
|
try {
|
|
305689
305769
|
globalTurnMonitor = new TurnMonitor({
|
|
@@ -305691,42 +305771,42 @@ async function setupEventBusServices(eventBus, services, db3) {
|
|
|
305691
305771
|
instanceService: services.instances
|
|
305692
305772
|
});
|
|
305693
305773
|
globalTurnMonitor.start();
|
|
305694
|
-
|
|
305774
|
+
log113.info("Turn monitor started");
|
|
305695
305775
|
} catch (error2) {
|
|
305696
|
-
|
|
305776
|
+
log113.error("Failed to start turn monitor", { error: String(error2) });
|
|
305697
305777
|
}
|
|
305698
305778
|
}
|
|
305699
305779
|
async function waitForDatabaseReady(db3, maxAttempts = 30) {
|
|
305700
|
-
|
|
305780
|
+
log113.info("Waiting for database readiness");
|
|
305701
305781
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
305702
305782
|
try {
|
|
305703
305783
|
await db3.execute(sql`SELECT 1`);
|
|
305704
|
-
|
|
305784
|
+
log113.info("Database ready", { attempt });
|
|
305705
305785
|
return;
|
|
305706
305786
|
} catch {
|
|
305707
305787
|
if (attempt === maxAttempts) {
|
|
305708
305788
|
throw new Error(`Database not ready after ${maxAttempts} attempts`);
|
|
305709
305789
|
}
|
|
305710
|
-
|
|
305790
|
+
log113.warn("Database not ready, retrying...", { attempt });
|
|
305711
305791
|
await new Promise((resolve4) => setTimeout(resolve4, 1000));
|
|
305712
305792
|
}
|
|
305713
305793
|
}
|
|
305714
305794
|
}
|
|
305715
305795
|
async function main() {
|
|
305716
|
-
|
|
305796
|
+
log113.info("Starting Omni API v2");
|
|
305717
305797
|
enableDefaultMetrics();
|
|
305718
305798
|
const pgserveConfig = resolvePgserveConfig();
|
|
305719
305799
|
const databaseUrl = await startEmbeddedPgserve(pgserveConfig);
|
|
305720
|
-
|
|
305800
|
+
log113.info("Connecting to database");
|
|
305721
305801
|
const db3 = createDb({ url: databaseUrl });
|
|
305722
305802
|
globalDbRef = db3;
|
|
305723
305803
|
const earlyShutdown = async () => {
|
|
305724
|
-
|
|
305804
|
+
log113.info("Shutdown during startup \u2014 cleaning up");
|
|
305725
305805
|
try {
|
|
305726
305806
|
await closeDb();
|
|
305727
305807
|
await stopEmbeddedPgserve();
|
|
305728
305808
|
} catch (err) {
|
|
305729
|
-
|
|
305809
|
+
log113.error("Cleanup failed during early shutdown", { error: String(err) });
|
|
305730
305810
|
} finally {
|
|
305731
305811
|
process.exit(1);
|
|
305732
305812
|
}
|
|
@@ -305740,7 +305820,7 @@ async function main() {
|
|
|
305740
305820
|
await stopEmbeddedPgserve();
|
|
305741
305821
|
throw error2;
|
|
305742
305822
|
}
|
|
305743
|
-
|
|
305823
|
+
log113.info("Running database migrations");
|
|
305744
305824
|
const migrationStart = Date.now();
|
|
305745
305825
|
const MIGRATION_TIMEOUT_MS = 60000;
|
|
305746
305826
|
try {
|
|
@@ -305753,17 +305833,17 @@ async function main() {
|
|
|
305753
305833
|
await stopEmbeddedPgserve();
|
|
305754
305834
|
throw error2;
|
|
305755
305835
|
}
|
|
305756
|
-
|
|
305836
|
+
log113.info("Database migrations complete", { durationMs: Date.now() - migrationStart });
|
|
305757
305837
|
try {
|
|
305758
305838
|
const driftReport = await verifyCriticalColumns(db3, API_CRITICAL_COLUMNS);
|
|
305759
305839
|
if (!driftReport.ok) {
|
|
305760
|
-
|
|
305840
|
+
log113.error(formatDriftReport(driftReport), { drift: driftReport.drift });
|
|
305761
305841
|
await closeDb();
|
|
305762
305842
|
await stopEmbeddedPgserve();
|
|
305763
305843
|
process.exit(1);
|
|
305764
305844
|
}
|
|
305765
305845
|
} catch (error2) {
|
|
305766
|
-
|
|
305846
|
+
log113.error("Schema drift check failed", { error: String(error2) });
|
|
305767
305847
|
await closeDb();
|
|
305768
305848
|
await stopEmbeddedPgserve();
|
|
305769
305849
|
process.exit(1);
|
|
@@ -305771,12 +305851,12 @@ async function main() {
|
|
|
305771
305851
|
try {
|
|
305772
305852
|
const [countRow] = await db3.select({ count: sql`count(*)::int` }).from(instances);
|
|
305773
305853
|
const rowCount = countRow?.count ?? 0;
|
|
305774
|
-
|
|
305854
|
+
log113.info("Post-migration content snapshot", { DB_ROW_COUNT_INSTANCES: rowCount });
|
|
305775
305855
|
if (rowCount === 0 && pgserveConfig.requireExisting) {
|
|
305776
|
-
|
|
305856
|
+
log113.error("PGSERVE_REQUIRE_EXISTING=true but instances table is empty after boot \u2014 verify PGSERVE_DATA points at the correct cluster (see #412).");
|
|
305777
305857
|
}
|
|
305778
305858
|
} catch (error2) {
|
|
305779
|
-
|
|
305859
|
+
log113.warn("Failed to read instances row count (non-fatal)", { error: String(error2) });
|
|
305780
305860
|
}
|
|
305781
305861
|
const eventBus = await connectToNats(db3);
|
|
305782
305862
|
if (eventBus) {
|
|
@@ -305794,9 +305874,9 @@ async function main() {
|
|
|
305794
305874
|
try {
|
|
305795
305875
|
await services.settings.seedDefaults();
|
|
305796
305876
|
} catch (error2) {
|
|
305797
|
-
|
|
305877
|
+
log113.error("Failed to seed default settings", { error: String(error2) });
|
|
305798
305878
|
}
|
|
305799
|
-
|
|
305879
|
+
log113.info("Initializing API key");
|
|
305800
305880
|
let apiKeyInfo;
|
|
305801
305881
|
try {
|
|
305802
305882
|
const keyResult = await services.apiKeys.initializePrimaryKey();
|
|
@@ -305806,17 +305886,17 @@ async function main() {
|
|
|
305806
305886
|
isFromEnv: keyResult.isFromEnv
|
|
305807
305887
|
};
|
|
305808
305888
|
if (keyResult.isNew) {
|
|
305809
|
-
|
|
305889
|
+
log113.info("Generated new primary API key");
|
|
305810
305890
|
} else if (keyResult.isFromEnv) {
|
|
305811
|
-
|
|
305891
|
+
log113.info("Using primary API key from environment");
|
|
305812
305892
|
} else {
|
|
305813
|
-
|
|
305893
|
+
log113.info("Using existing primary API key");
|
|
305814
305894
|
}
|
|
305815
305895
|
} catch (error2) {
|
|
305816
|
-
|
|
305896
|
+
log113.error("Failed to initialize primary API key", { error: String(error2) });
|
|
305817
305897
|
}
|
|
305818
305898
|
await setupEventBusServices(eventBus, services, db3);
|
|
305819
|
-
|
|
305899
|
+
log113.info("Starting scheduler");
|
|
305820
305900
|
setupScheduler(services, globalChannelRegistry);
|
|
305821
305901
|
const server = startBunServer(app);
|
|
305822
305902
|
printStartupBanner({
|
|
@@ -305830,7 +305910,7 @@ async function main() {
|
|
|
305830
305910
|
});
|
|
305831
305911
|
setupShutdownHandlers(server, earlyShutdown);
|
|
305832
305912
|
}
|
|
305833
|
-
var import__package3,
|
|
305913
|
+
var import__package3, log113, natsLog, pluginLog, shutdownLog, PORT, HOST, NATS_URL, voiceStreamRegistry, globalEventBus = null, globalChannelRegistry = null, globalInstanceMonitor = null, globalDispatcherCleanup = null, globalTurnMonitor = null, globalDbRef = null, UUID_RE3;
|
|
305834
305914
|
var init_src8 = __esm(() => {
|
|
305835
305915
|
init_instrument2();
|
|
305836
305916
|
init_src2();
|
|
@@ -305855,7 +305935,7 @@ var init_src8 = __esm(() => {
|
|
|
305855
305935
|
level: process.env.LOG_LEVEL ?? "info",
|
|
305856
305936
|
format: process.env.LOG_FORMAT ?? "auto"
|
|
305857
305937
|
});
|
|
305858
|
-
|
|
305938
|
+
log113 = createLogger("api:startup");
|
|
305859
305939
|
natsLog = createLogger("api:nats");
|
|
305860
305940
|
pluginLog = createLogger("api:plugins");
|
|
305861
305941
|
shutdownLog = createLogger("api:shutdown");
|
|
@@ -305865,7 +305945,7 @@ var init_src8 = __esm(() => {
|
|
|
305865
305945
|
voiceStreamRegistry = new VoiceStreamRegistry;
|
|
305866
305946
|
UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
305867
305947
|
main().catch((error2) => {
|
|
305868
|
-
|
|
305948
|
+
log113.error("Failed to start API server", { error: String(error2) });
|
|
305869
305949
|
process.exit(1);
|
|
305870
305950
|
});
|
|
305871
305951
|
});
|