@automagik/omni 2.260902.1 → 2.260902.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/send.d.ts +5 -0
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/webhooks.d.ts +8 -0
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/index.js +16 -6
- package/dist/sdk/types.generated.d.ts +44 -2
- package/dist/sdk/types.generated.d.ts.map +1 -1
- package/dist/server/index.js +299 -272
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -242901,7 +242901,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
242901
242901
|
var require_package7 = __commonJS((exports, module) => {
|
|
242902
242902
|
module.exports = {
|
|
242903
242903
|
name: "@omni/api",
|
|
242904
|
-
version: "2.260902.
|
|
242904
|
+
version: "2.260902.2",
|
|
242905
242905
|
type: "module",
|
|
242906
242906
|
exports: {
|
|
242907
242907
|
".": {
|
|
@@ -355872,7 +355872,8 @@ function resolveClientIp(trustedProxyHeaderValue, remoteAddr) {
|
|
|
355872
355872
|
if (!raw2)
|
|
355873
355873
|
return;
|
|
355874
355874
|
const hops = raw2.split(",").map((hop) => hop.trim()).filter(Boolean);
|
|
355875
|
-
|
|
355875
|
+
const parsed = clientIpSchema.safeParse(hops.at(-1));
|
|
355876
|
+
return parsed.success ? parsed.data : undefined;
|
|
355876
355877
|
}
|
|
355877
355878
|
function createRateLimiter2(config4 = RATE_LIMITS.general, keyPrefix = "ratelimit") {
|
|
355878
355879
|
return createMiddleware(async (c, next) => {
|
|
@@ -355882,6 +355883,12 @@ function createRateLimiter2(config4 = RATE_LIMITS.general, keyPrefix = "ratelimi
|
|
|
355882
355883
|
const server = c.env;
|
|
355883
355884
|
const remoteAddr = server?.remoteAddr ?? server?.requestIP?.(c.req.raw)?.address;
|
|
355884
355885
|
const normalizedIp = resolveClientIp(trustedProxyIp, remoteAddr);
|
|
355886
|
+
if (trustedProxyIp !== undefined && normalizedIp === undefined && !warnedUnparseableProxyHop) {
|
|
355887
|
+
warnedUnparseableProxyHop = true;
|
|
355888
|
+
log112.warn("TRUSTED_PROXY_HEADER hop is not a bare IP literal; requests share the anonymous rate-limit bucket", {
|
|
355889
|
+
header: trustedProxyHeader
|
|
355890
|
+
});
|
|
355891
|
+
}
|
|
355885
355892
|
const identifier = apiKey?.id ? `api:${apiKey.id}` : normalizedIp ? `ip:${normalizedIp}` : "anon";
|
|
355886
355893
|
const key = `${keyPrefix}:${identifier}`;
|
|
355887
355894
|
const now = Date.now();
|
|
@@ -355920,9 +355927,12 @@ function createRateLimiter2(config4 = RATE_LIMITS.general, keyPrefix = "ratelimi
|
|
|
355920
355927
|
setRateLimitHeaders();
|
|
355921
355928
|
});
|
|
355922
355929
|
}
|
|
355923
|
-
var rateLimitStore, cleanupTimer, RATE_LIMITS, rateLimitMiddleware, webhookIngressRateLimitMiddleware;
|
|
355930
|
+
var log112, warnedUnparseableProxyHop = false, rateLimitStore, cleanupTimer, RATE_LIMITS, clientIpSchema, rateLimitMiddleware, webhookIngressRateLimitMiddleware;
|
|
355924
355931
|
var init_rate_limit = __esm(() => {
|
|
355932
|
+
init_src();
|
|
355925
355933
|
init_factory2();
|
|
355934
|
+
init_zod();
|
|
355935
|
+
log112 = createLogger("api:rate-limit");
|
|
355926
355936
|
rateLimitStore = new Map;
|
|
355927
355937
|
cleanupTimer = setInterval(() => {
|
|
355928
355938
|
const now = Date.now();
|
|
@@ -355939,6 +355949,7 @@ var init_rate_limit = __esm(() => {
|
|
|
355939
355949
|
instances: { windowMs: 60 * 1000, maxRequests: 30 },
|
|
355940
355950
|
general: { windowMs: 60 * 1000, maxRequests: 1000 }
|
|
355941
355951
|
};
|
|
355952
|
+
clientIpSchema = exports_external.string().ip();
|
|
355942
355953
|
rateLimitMiddleware = createRateLimiter2(RATE_LIMITS.general);
|
|
355943
355954
|
webhookIngressRateLimitMiddleware = createRateLimiter2(RATE_LIMITS.events, "ratelimit:webhook-ingress");
|
|
355944
355955
|
});
|
|
@@ -356042,22 +356053,22 @@ function createWebhookAuthMiddleware(config4) {
|
|
|
356042
356053
|
const token = c.req.header("x-telegram-bot-api-secret-token");
|
|
356043
356054
|
if (!token) {
|
|
356044
356055
|
const ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "unknown";
|
|
356045
|
-
|
|
356056
|
+
log113.warn("Webhook request missing secret token", { ip });
|
|
356046
356057
|
return c.json({ error: { code: "UNAUTHORIZED", message: "Missing webhook secret token" } }, 401);
|
|
356047
356058
|
}
|
|
356048
356059
|
if (token !== webhookSecret) {
|
|
356049
356060
|
const ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "unknown";
|
|
356050
|
-
|
|
356061
|
+
log113.warn("Webhook request with invalid secret token", { ip });
|
|
356051
356062
|
return c.json({ error: { code: "UNAUTHORIZED", message: "Invalid webhook secret token" } }, 401);
|
|
356052
356063
|
}
|
|
356053
356064
|
return next();
|
|
356054
356065
|
});
|
|
356055
356066
|
}
|
|
356056
|
-
var
|
|
356067
|
+
var log113;
|
|
356057
356068
|
var init_webhook_auth = __esm(() => {
|
|
356058
356069
|
init_src();
|
|
356059
356070
|
init_factory2();
|
|
356060
|
-
|
|
356071
|
+
log113 = createLogger("api:webhook-auth");
|
|
356061
356072
|
});
|
|
356062
356073
|
|
|
356063
356074
|
// ../api/src/plugin-state.ts
|
|
@@ -361760,7 +361771,7 @@ function registerWebhookSchemas(registry4) {
|
|
|
361760
361771
|
operationId: "receiveWebhook",
|
|
361761
361772
|
tags: ["Webhooks"],
|
|
361762
361773
|
summary: "Receive webhook",
|
|
361763
|
-
description: "Receive webhook from external system. Creates a custom event.",
|
|
361774
|
+
description: "Receive webhook from external system. Creates a custom event. An empty body is accepted as an empty " + "payload; a non-empty body that is not a JSON object (malformed, array, scalar) is rejected.",
|
|
361764
361775
|
request: {
|
|
361765
361776
|
params: exports_external.object({ source: exports_external.string().openapi({ description: "Source name" }) }),
|
|
361766
361777
|
body: { content: { "application/json": { schema: exports_external.record(exports_external.string(), exports_external.unknown()) } } }
|
|
@@ -361769,7 +361780,8 @@ function registerWebhookSchemas(registry4) {
|
|
|
361769
361780
|
200: {
|
|
361770
361781
|
description: "Webhook received",
|
|
361771
361782
|
content: { "application/json": { schema: WebhookReceiveResponseSchema } }
|
|
361772
|
-
}
|
|
361783
|
+
},
|
|
361784
|
+
400: { description: "Body is not a JSON object", content: { "application/json": { schema: ErrorSchema } } }
|
|
361773
361785
|
}
|
|
361774
361786
|
});
|
|
361775
361787
|
registry4.registerPath({
|
|
@@ -361778,7 +361790,7 @@ function registerWebhookSchemas(registry4) {
|
|
|
361778
361790
|
operationId: "receiveWebhookIngress",
|
|
361779
361791
|
tags: ["Webhooks"],
|
|
361780
361792
|
summary: "Public webhook ingress",
|
|
361781
|
-
description: "Auth-exempt receiver for third-party webhook senders. Requires the source to have a signature " + "configuration; the request is verified against it (HMAC over the raw body, or token match) before any " + "event is published. Unknown, disabled, unconfigured, or badly signed requests all return the same 401.",
|
|
361793
|
+
description: "Auth-exempt receiver for third-party webhook senders. Requires the source to have a signature " + "configuration; the request is verified against it (HMAC over the raw body, or token match) before any " + "event is published. Unknown, disabled, unconfigured, or badly signed requests all return the same 401. " + "A non-empty body that is not a JSON object (malformed, array, scalar) is rejected with 400.",
|
|
361782
361794
|
security: [],
|
|
361783
361795
|
request: {
|
|
361784
361796
|
params: exports_external.object({ source: exports_external.string().openapi({ description: "Source name" }) }),
|
|
@@ -361789,6 +361801,7 @@ function registerWebhookSchemas(registry4) {
|
|
|
361789
361801
|
description: "Webhook received",
|
|
361790
361802
|
content: { "application/json": { schema: WebhookReceiveResponseSchema } }
|
|
361791
361803
|
},
|
|
361804
|
+
400: { description: "Body is not a JSON object", content: { "application/json": { schema: ErrorSchema } } },
|
|
361792
361805
|
401: { description: "Verification failed", content: { "application/json": { schema: ErrorSchema } } }
|
|
361793
361806
|
}
|
|
361794
361807
|
});
|
|
@@ -363823,7 +363836,7 @@ async function clearAgentSession(services, db2, instanceId, from, chatId, option
|
|
|
363823
363836
|
});
|
|
363824
363837
|
const primaryDelete = await client.deleteSession?.(sessionId);
|
|
363825
363838
|
const legacyDelete = legacySessionId !== sessionId ? await client.deleteSession?.(legacySessionId) : undefined;
|
|
363826
|
-
|
|
363839
|
+
log114.info("Agno session delete verified", {
|
|
363827
363840
|
instanceId,
|
|
363828
363841
|
sessionId,
|
|
363829
363842
|
legacySessionId,
|
|
@@ -363845,7 +363858,7 @@ async function handleTrashEmojiMessage(services, db2, event) {
|
|
|
363845
363858
|
await runTrashEmojiCleanup(services, db2, event);
|
|
363846
363859
|
});
|
|
363847
363860
|
if (!result.executed) {
|
|
363848
|
-
|
|
363861
|
+
log114.debug("Trash emoji event already processed (NATS redelivery skipped)", {
|
|
363849
363862
|
eventId: event.id,
|
|
363850
363863
|
instanceId,
|
|
363851
363864
|
chatId
|
|
@@ -363858,11 +363871,11 @@ async function runTrashEmojiCleanup(services, db2, event) {
|
|
|
363858
363871
|
if (!instanceId)
|
|
363859
363872
|
return;
|
|
363860
363873
|
const tenantId = trustedTenantOf(event);
|
|
363861
|
-
|
|
363874
|
+
log114.info("Trash emoji detected, clearing session", { instanceId, chatId, from, personId });
|
|
363862
363875
|
try {
|
|
363863
363876
|
const identity = await clearAgentSession(services, db2, instanceId, from, chatId, { personId, rawPayload }, tenantId);
|
|
363864
363877
|
const { sessionId, legacySessionId, sessionStrategy, source, canonicalSessionId, environment, channelSegment } = identity;
|
|
363865
|
-
|
|
363878
|
+
log114.info("Session cleared successfully", {
|
|
363866
363879
|
instanceId,
|
|
363867
363880
|
sessionId,
|
|
363868
363881
|
legacySessionId,
|
|
@@ -363887,11 +363900,11 @@ async function runTrashEmojiCleanup(services, db2, event) {
|
|
|
363887
363900
|
await runTenantWorkDb(db2, tenantId, () => services.chats.update(dbChat.id, {
|
|
363888
363901
|
settings: { agentPaused: false, agentResumedAt: new Date().toISOString() }
|
|
363889
363902
|
}));
|
|
363890
|
-
|
|
363903
|
+
log114.info("Agent resumed after session clear (was paused by handoff)", { instanceId, chatId });
|
|
363891
363904
|
}
|
|
363892
363905
|
}
|
|
363893
363906
|
} catch (disarmError) {
|
|
363894
|
-
|
|
363907
|
+
log114.warn("Failed to disarm follow-up after session clear", {
|
|
363895
363908
|
instanceId,
|
|
363896
363909
|
chatId,
|
|
363897
363910
|
error: String(disarmError)
|
|
@@ -363899,9 +363912,9 @@ async function runTrashEmojiCleanup(services, db2, event) {
|
|
|
363899
363912
|
}
|
|
363900
363913
|
try {
|
|
363901
363914
|
await sendMessage(services, db2, instanceId, chatId, "\u2705 Conversa limpa! Sua sess\xE3o com o assistente foi resetada.", tenantId);
|
|
363902
|
-
|
|
363915
|
+
log114.info("Sent session cleared confirmation", { instanceId, chatId });
|
|
363903
363916
|
} catch (sendError) {
|
|
363904
|
-
|
|
363917
|
+
log114.error("Failed to send confirmation message", { instanceId, chatId, error: String(sendError) });
|
|
363905
363918
|
}
|
|
363906
363919
|
} catch (error3) {
|
|
363907
363920
|
const errorMessage = error3 instanceof Error ? error3.message : String(error3);
|
|
@@ -363912,14 +363925,14 @@ async function runTrashEmojiCleanup(services, db2, event) {
|
|
|
363912
363925
|
"Session clearing not supported for"
|
|
363913
363926
|
];
|
|
363914
363927
|
if (skippableErrors.some((e) => errorMessage.includes(e))) {
|
|
363915
|
-
|
|
363928
|
+
log114.debug("Session clearing skipped", { instanceId, reason: errorMessage });
|
|
363916
363929
|
return;
|
|
363917
363930
|
}
|
|
363918
|
-
|
|
363931
|
+
log114.error("Failed to clear session", { instanceId, chatId, error: errorMessage });
|
|
363919
363932
|
try {
|
|
363920
363933
|
await sendMessage(services, db2, instanceId, chatId, "\u274C Erro ao limpar sess\xE3o. Tente novamente.", tenantId);
|
|
363921
363934
|
} catch (sendError) {
|
|
363922
|
-
|
|
363935
|
+
log114.error("Failed to send error message", { instanceId, chatId, error: String(sendError) });
|
|
363923
363936
|
}
|
|
363924
363937
|
}
|
|
363925
363938
|
}
|
|
@@ -363933,13 +363946,13 @@ async function setupSessionCleaner(eventBus, services, db2) {
|
|
|
363933
363946
|
startFrom: "new",
|
|
363934
363947
|
concurrency: 5
|
|
363935
363948
|
});
|
|
363936
|
-
|
|
363949
|
+
log114.info("Session cleaner initialized");
|
|
363937
363950
|
} catch (error3) {
|
|
363938
|
-
|
|
363951
|
+
log114.error("Failed to set up session cleaner", { error: String(error3) });
|
|
363939
363952
|
throw error3;
|
|
363940
363953
|
}
|
|
363941
363954
|
}
|
|
363942
|
-
var
|
|
363955
|
+
var log114;
|
|
363943
363956
|
var init_session_cleaner = __esm(() => {
|
|
363944
363957
|
init_src();
|
|
363945
363958
|
init_src5();
|
|
@@ -363949,7 +363962,7 @@ var init_session_cleaner = __esm(() => {
|
|
|
363949
363962
|
init_worker_tenant_context();
|
|
363950
363963
|
init_agent_dispatcher();
|
|
363951
363964
|
init_loader2();
|
|
363952
|
-
|
|
363965
|
+
log114 = createLogger("session-cleaner");
|
|
363953
363966
|
});
|
|
363954
363967
|
|
|
363955
363968
|
// ../api/src/routes/v2/chats.ts
|
|
@@ -365324,6 +365337,12 @@ var init_handoffs = __esm(() => {
|
|
|
365324
365337
|
});
|
|
365325
365338
|
|
|
365326
365339
|
// ../api/src/lib/whatsapp-business-connection.ts
|
|
365340
|
+
function resolveMetaApiVersion(persisted) {
|
|
365341
|
+
const fromEnv = metaGraphApiVersionSchema.safeParse(process.env.META_GRAPH_API_VERSION);
|
|
365342
|
+
if (fromEnv.success)
|
|
365343
|
+
return fromEnv.data;
|
|
365344
|
+
return persisted ?? undefined;
|
|
365345
|
+
}
|
|
365327
365346
|
function applyWhatsAppBusinessConnectionOptions(options, input) {
|
|
365328
365347
|
if (input.metaAccessToken)
|
|
365329
365348
|
options.metaAccessToken = input.metaAccessToken;
|
|
@@ -365335,7 +365354,7 @@ function applyWhatsAppBusinessConnectionOptions(options, input) {
|
|
|
365335
365354
|
options.metaAppId = input.metaAppId;
|
|
365336
365355
|
if (input.metaBusinessId)
|
|
365337
365356
|
options.metaBusinessId = input.metaBusinessId;
|
|
365338
|
-
const apiVersion =
|
|
365357
|
+
const apiVersion = resolveMetaApiVersion(input.metaApiVersion);
|
|
365339
365358
|
if (apiVersion)
|
|
365340
365359
|
options.metaApiVersion = apiVersion;
|
|
365341
365360
|
if (input.metaDisplayPhoneNumber)
|
|
@@ -365343,6 +365362,11 @@ function applyWhatsAppBusinessConnectionOptions(options, input) {
|
|
|
365343
365362
|
if (input.metaConnectionMethod)
|
|
365344
365363
|
options.metaConnectionMethod = input.metaConnectionMethod;
|
|
365345
365364
|
}
|
|
365365
|
+
var metaGraphApiVersionSchema;
|
|
365366
|
+
var init_whatsapp_business_connection = __esm(() => {
|
|
365367
|
+
init_zod();
|
|
365368
|
+
metaGraphApiVersionSchema = exports_external.string().regex(/^v\d+\.\d+$/);
|
|
365369
|
+
});
|
|
365346
365370
|
|
|
365347
365371
|
// ../../node_modules/.bun/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
|
|
365348
365372
|
var require_QRMode = __commonJS((exports, module) => {
|
|
@@ -366388,12 +366412,12 @@ async function printQrCodeToTerminal(qrCode, instanceId) {
|
|
|
366388
366412
|
try {
|
|
366389
366413
|
const qrTerminalModule = await Promise.resolve().then(() => __toESM(require_main(), 1));
|
|
366390
366414
|
const qrTerminal = qrTerminalModule.default || qrTerminalModule;
|
|
366391
|
-
|
|
366415
|
+
log115.info("QR Code generated for WhatsApp", { instanceId });
|
|
366392
366416
|
qrTerminal.generate(qrCode, { small: true });
|
|
366393
366417
|
} catch (error3) {
|
|
366394
|
-
|
|
366418
|
+
log115.info("QR Code generated", { instanceId, qrCode: `${qrCode.substring(0, 50)}...` });
|
|
366395
366419
|
if (error3 instanceof Error && process.env.DEBUG) {
|
|
366396
|
-
|
|
366420
|
+
log115.debug("QR Terminal unavailable", { error: error3.message });
|
|
366397
366421
|
}
|
|
366398
366422
|
}
|
|
366399
366423
|
}
|
|
@@ -366405,13 +366429,13 @@ async function setupQrCodeListener(eventBus) {
|
|
|
366405
366429
|
await printQrCodeToTerminal(qrCode, instanceId);
|
|
366406
366430
|
});
|
|
366407
366431
|
} catch (error3) {
|
|
366408
|
-
|
|
366432
|
+
log115.warn("Failed to set up QR code listener", { error: String(error3) });
|
|
366409
366433
|
}
|
|
366410
366434
|
}
|
|
366411
|
-
var
|
|
366435
|
+
var log115, qrCodes;
|
|
366412
366436
|
var init_qr_store = __esm(() => {
|
|
366413
366437
|
init_src();
|
|
366414
|
-
|
|
366438
|
+
log115 = createLogger("api:qr-store");
|
|
366415
366439
|
qrCodes = new Map;
|
|
366416
366440
|
});
|
|
366417
366441
|
|
|
@@ -366435,29 +366459,29 @@ class AgentReplayService {
|
|
|
366435
366459
|
agentId: instances.agentId
|
|
366436
366460
|
}).from(instances).where(eq(instances.id, instanceId)).limit(1));
|
|
366437
366461
|
if (!instance4) {
|
|
366438
|
-
|
|
366462
|
+
log116.warn("Instance not found for replay", { instanceId });
|
|
366439
366463
|
return;
|
|
366440
366464
|
}
|
|
366441
366465
|
if (!instance4.agentId) {
|
|
366442
|
-
|
|
366466
|
+
log116.debug("Instance has no agent, skipping replay", { instanceId });
|
|
366443
366467
|
await this.updateLastSeenAt(instanceId, undefined, trustedTenantId);
|
|
366444
366468
|
return;
|
|
366445
366469
|
}
|
|
366446
366470
|
if (!instance4.replayEnabled) {
|
|
366447
|
-
|
|
366471
|
+
log116.debug("Replay disabled for instance", { instanceId });
|
|
366448
366472
|
await this.updateLastSeenAt(instanceId, undefined, trustedTenantId);
|
|
366449
366473
|
return;
|
|
366450
366474
|
}
|
|
366451
366475
|
const since = instance4.lastSeenAt ?? null;
|
|
366452
366476
|
if (!since) {
|
|
366453
|
-
|
|
366477
|
+
log116.debug("No lastSeenAt recorded, skipping replay (first connect)", { instanceId });
|
|
366454
366478
|
await this.updateLastSeenAt(instanceId, undefined, trustedTenantId);
|
|
366455
366479
|
return;
|
|
366456
366480
|
}
|
|
366457
|
-
|
|
366481
|
+
log116.info("Starting replay on reconnect", { instanceId, since: since.toISOString() });
|
|
366458
366482
|
try {
|
|
366459
366483
|
const result = await this.replayMissedMessages({ instanceId, since }, trustedTenantId);
|
|
366460
|
-
|
|
366484
|
+
log116.info("Replay complete", {
|
|
366461
366485
|
instanceId,
|
|
366462
366486
|
replayed: result.replayed,
|
|
366463
366487
|
skipped: result.skipped,
|
|
@@ -366465,7 +366489,7 @@ class AgentReplayService {
|
|
|
366465
366489
|
});
|
|
366466
366490
|
await this.updateLastSeenAt(instanceId, result.until, trustedTenantId);
|
|
366467
366491
|
} catch (error3) {
|
|
366468
|
-
|
|
366492
|
+
log116.error("Replay failed", { instanceId, error: String(error3) });
|
|
366469
366493
|
}
|
|
366470
366494
|
}
|
|
366471
366495
|
async replayMissedMessages(options, trustedTenantId) {
|
|
@@ -366473,7 +366497,7 @@ class AgentReplayService {
|
|
|
366473
366497
|
const now = new Date;
|
|
366474
366498
|
const cutoff = new Date(now.getTime() - MAX_REPLAY_WINDOW_MS);
|
|
366475
366499
|
const since = options.since && options.since > cutoff ? options.since : cutoff;
|
|
366476
|
-
|
|
366500
|
+
log116.debug("Fetching missed messages", { instanceId, since: since.toISOString(), until: now.toISOString() });
|
|
366477
366501
|
let cursorTimestamp = since;
|
|
366478
366502
|
let cursorId = null;
|
|
366479
366503
|
let totalReplayed = 0;
|
|
@@ -366508,7 +366532,7 @@ class AgentReplayService {
|
|
|
366508
366532
|
if (rows.length === 0)
|
|
366509
366533
|
break;
|
|
366510
366534
|
if (rows.length === PAGE_SIZE) {
|
|
366511
|
-
|
|
366535
|
+
log116.warn("Replay page cap hit, fetching next page", {
|
|
366512
366536
|
instanceId,
|
|
366513
366537
|
limit: PAGE_SIZE,
|
|
366514
366538
|
cursor: cursorTimestamp.toISOString()
|
|
@@ -366536,7 +366560,7 @@ class AgentReplayService {
|
|
|
366536
366560
|
await this.redispatchMessage(instanceId, row);
|
|
366537
366561
|
replayed++;
|
|
366538
366562
|
} catch (error3) {
|
|
366539
|
-
|
|
366563
|
+
log116.warn("Failed to redispatch message during replay", {
|
|
366540
366564
|
instanceId,
|
|
366541
366565
|
messageId: row.id,
|
|
366542
366566
|
error: String(error3)
|
|
@@ -366593,14 +366617,14 @@ function mapMessageTypeToContentType(messageType) {
|
|
|
366593
366617
|
return "text";
|
|
366594
366618
|
}
|
|
366595
366619
|
}
|
|
366596
|
-
var
|
|
366620
|
+
var log116, MAX_REPLAY_WINDOW_MS;
|
|
366597
366621
|
var init_agent_replay = __esm(() => {
|
|
366598
366622
|
init_src();
|
|
366599
366623
|
init_src5();
|
|
366600
366624
|
init_drizzle_orm();
|
|
366601
366625
|
init_tenant_scope();
|
|
366602
366626
|
init_worker_tenant_context();
|
|
366603
|
-
|
|
366627
|
+
log116 = createLogger("agent-replay");
|
|
366604
366628
|
MAX_REPLAY_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
366605
366629
|
});
|
|
366606
366630
|
|
|
@@ -366803,15 +366827,15 @@ async function connectInstanceWithPlugin(plugin10, instanceId, options) {
|
|
|
366803
366827
|
async function triggerCreateConnection(channelRegistry2, channel5, instanceId, options) {
|
|
366804
366828
|
const plugin10 = getPluginFromRegistry(channelRegistry2, channel5);
|
|
366805
366829
|
if (!plugin10) {
|
|
366806
|
-
|
|
366830
|
+
log117.warn("No plugin found for channel", { channel: channel5 });
|
|
366807
366831
|
return;
|
|
366808
366832
|
}
|
|
366809
366833
|
const errorMessage = await connectInstanceWithPlugin(plugin10, instanceId, options);
|
|
366810
366834
|
if (errorMessage) {
|
|
366811
|
-
|
|
366835
|
+
log117.error("Failed to connect instance", { instanceId, error: errorMessage });
|
|
366812
366836
|
return;
|
|
366813
366837
|
}
|
|
366814
|
-
|
|
366838
|
+
log117.info("Triggered connection", { instanceId, channel: channel5 });
|
|
366815
366839
|
}
|
|
366816
366840
|
function buildTokenPersistUpdates(channel5, body) {
|
|
366817
366841
|
const updates = {};
|
|
@@ -366849,10 +366873,10 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
366849
366873
|
await services.apiKeys.update(existingKey.id, {
|
|
366850
366874
|
instanceIds: updated.length > 0 ? updated : null
|
|
366851
366875
|
});
|
|
366852
|
-
|
|
366876
|
+
log117.info("Removed instance from agent key", { keyName, instanceId });
|
|
366853
366877
|
}
|
|
366854
366878
|
} catch (err2) {
|
|
366855
|
-
|
|
366879
|
+
log117.error("Failed to remove instance from old agent key", { oldAgentId, instanceId, error: String(err2) });
|
|
366856
366880
|
}
|
|
366857
366881
|
}
|
|
366858
366882
|
if (newAgentId) {
|
|
@@ -366866,7 +366890,7 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
366866
366890
|
await services.apiKeys.update(existingKey.id, {
|
|
366867
366891
|
instanceIds: [...currentIds, instanceId]
|
|
366868
366892
|
});
|
|
366869
|
-
|
|
366893
|
+
log117.info("Added instance to existing agent key", { keyName, instanceId });
|
|
366870
366894
|
}
|
|
366871
366895
|
} else {
|
|
366872
366896
|
const agentScopes = Array.isArray(agent3.metadata?.omniScopes) ? agent3.metadata.omniScopes : [...DEFAULT_TURN_SCOPES];
|
|
@@ -366877,10 +366901,10 @@ async function handleAgentKeyProvisioning(services, instanceId, newAgentId, oldA
|
|
|
366877
366901
|
instanceIds: [instanceId],
|
|
366878
366902
|
createdBy: "system:auto-provision"
|
|
366879
366903
|
});
|
|
366880
|
-
|
|
366904
|
+
log117.info("Created scoped agent key", { keyName, instanceId, keyId: result.key.id });
|
|
366881
366905
|
}
|
|
366882
366906
|
} catch (err2) {
|
|
366883
|
-
|
|
366907
|
+
log117.error("Failed to provision agent key", { newAgentId, instanceId, error: String(err2) });
|
|
366884
366908
|
}
|
|
366885
366909
|
}
|
|
366886
366910
|
}
|
|
@@ -367064,7 +367088,7 @@ function getCacheKey(instanceId, guildId) {
|
|
|
367064
367088
|
function invalidateGuildCache(instanceId, guildId) {
|
|
367065
367089
|
guildConfigCache.delete(getCacheKey(instanceId, guildId));
|
|
367066
367090
|
}
|
|
367067
|
-
var
|
|
367091
|
+
var log117, instancesRoutes, instanceAccess2, listQuerySchema12, agentReplyFilterSchema, createInstanceSchema, updateInstanceSchema, DEFAULT_AGENT_REPLY_FILTER, SENSITIVE_INSTANCE_FIELDS, pairingCodeSchema, passkeyBase64UrlSchema, passkeyCredentialSchema, connectInstanceSchema, syncRequestSchema, listContactsQuerySchema, listGroupsQuerySchema, checkNumberSchema, updateBioSchema, blockContactSchema, groupParticipantActionSchema, groupSettingSchema, groupParticipantsSchema, groupParticipantsPatchSchema, updateGroupSubjectSchema, updateGroupDescriptionSchema, updateGroupSettingsSchema, patchGroupSchema, resyncSchema, replaySchema, pairingActionSchema, guildConfigOverrideSchema, guildConfigCache, GUILD_CONFIG_TTL, presenceSchema;
|
|
367068
367092
|
var init_instances3 = __esm(() => {
|
|
367069
367093
|
init_dist6();
|
|
367070
367094
|
init_src();
|
|
@@ -367072,12 +367096,13 @@ var init_instances3 = __esm(() => {
|
|
|
367072
367096
|
init_zod();
|
|
367073
367097
|
init_cache_keys();
|
|
367074
367098
|
init_scopes();
|
|
367099
|
+
init_whatsapp_business_connection();
|
|
367075
367100
|
init_auth();
|
|
367076
367101
|
init_agent_dispatcher();
|
|
367077
367102
|
init_qr_store();
|
|
367078
367103
|
init_access();
|
|
367079
367104
|
init_agent_replay();
|
|
367080
|
-
|
|
367105
|
+
log117 = createLogger("api:instances");
|
|
367081
367106
|
instancesRoutes = new Hono2;
|
|
367082
367107
|
instanceAccess2 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
367083
367108
|
listQuerySchema12 = exports_external.object({
|
|
@@ -367289,7 +367314,7 @@ var init_instances3 = __esm(() => {
|
|
|
367289
367314
|
agentIdTouched: data.agentId !== undefined
|
|
367290
367315
|
})) {
|
|
367291
367316
|
data.agentReplyFilter = DEFAULT_AGENT_REPLY_FILTER;
|
|
367292
|
-
|
|
367317
|
+
log117.info("Agent assigned without reply filter \u2014 defaulting to mode:all onDm:true (omni#443)", {
|
|
367293
367318
|
agentId: data.agentId,
|
|
367294
367319
|
defaultFilter: DEFAULT_AGENT_REPLY_FILTER
|
|
367295
367320
|
});
|
|
@@ -367351,7 +367376,7 @@ var init_instances3 = __esm(() => {
|
|
|
367351
367376
|
agentIdTouched: data.agentId !== undefined
|
|
367352
367377
|
})) {
|
|
367353
367378
|
data.agentReplyFilter = DEFAULT_AGENT_REPLY_FILTER;
|
|
367354
|
-
|
|
367379
|
+
log117.info("Agent assigned without reply filter \u2014 defaulting to mode:all onDm:true (omni#443)", {
|
|
367355
367380
|
instanceId: id,
|
|
367356
367381
|
agentId: data.agentId,
|
|
367357
367382
|
defaultFilter: DEFAULT_AGENT_REPLY_FILTER
|
|
@@ -367377,7 +367402,7 @@ var init_instances3 = __esm(() => {
|
|
|
367377
367402
|
try {
|
|
367378
367403
|
await plugin10.disconnect(id);
|
|
367379
367404
|
} catch (error3) {
|
|
367380
|
-
|
|
367405
|
+
log117.error("Failed to disconnect instance before delete", { instanceId: id, error: String(error3) });
|
|
367381
367406
|
}
|
|
367382
367407
|
}
|
|
367383
367408
|
await services.instances.delete(id);
|
|
@@ -367385,7 +367410,7 @@ var init_instances3 = __esm(() => {
|
|
|
367385
367410
|
try {
|
|
367386
367411
|
await plugin10.logout(id);
|
|
367387
367412
|
} catch (error3) {
|
|
367388
|
-
|
|
367413
|
+
log117.error("Failed to clear channel auth after delete", { instanceId: id, error: String(error3) });
|
|
367389
367414
|
}
|
|
367390
367415
|
}
|
|
367391
367416
|
return c.json({ success: true });
|
|
@@ -367616,7 +367641,7 @@ var init_instances3 = __esm(() => {
|
|
|
367616
367641
|
try {
|
|
367617
367642
|
await plugin10.disconnect(id);
|
|
367618
367643
|
} catch (error3) {
|
|
367619
|
-
|
|
367644
|
+
log117.error("Failed to disconnect instance", { instanceId: id, error: String(error3) });
|
|
367620
367645
|
}
|
|
367621
367646
|
}
|
|
367622
367647
|
}
|
|
@@ -367698,13 +367723,13 @@ var init_instances3 = __esm(() => {
|
|
|
367698
367723
|
try {
|
|
367699
367724
|
await plugin10.logout(id);
|
|
367700
367725
|
} catch (error3) {
|
|
367701
|
-
|
|
367726
|
+
log117.error("Failed to logout instance", { instanceId: id, error: String(error3) });
|
|
367702
367727
|
}
|
|
367703
367728
|
} else if (plugin10) {
|
|
367704
367729
|
try {
|
|
367705
367730
|
await plugin10.disconnect(id);
|
|
367706
367731
|
} catch (error3) {
|
|
367707
|
-
|
|
367732
|
+
log117.error("Failed to disconnect instance during logout", { instanceId: id, error: String(error3) });
|
|
367708
367733
|
}
|
|
367709
367734
|
}
|
|
367710
367735
|
}
|
|
@@ -368730,7 +368755,7 @@ var init_instances3 = __esm(() => {
|
|
|
368730
368755
|
...chatJids?.length ? { chatJids } : {}
|
|
368731
368756
|
}
|
|
368732
368757
|
});
|
|
368733
|
-
|
|
368758
|
+
log117.info("Resync triggered", {
|
|
368734
368759
|
instanceId: id,
|
|
368735
368760
|
jobId: job.id,
|
|
368736
368761
|
since: sinceDate.toISOString(),
|
|
@@ -368748,7 +368773,7 @@ var init_instances3 = __esm(() => {
|
|
|
368748
368773
|
});
|
|
368749
368774
|
} catch (error3) {
|
|
368750
368775
|
const message2 = error3 instanceof Error ? error3.message : "Unknown error";
|
|
368751
|
-
|
|
368776
|
+
log117.error("Failed to trigger resync", { instanceId: id, error: message2 });
|
|
368752
368777
|
return c.json({ error: { code: "RESYNC_FAILED", message: message2 } }, 500);
|
|
368753
368778
|
}
|
|
368754
368779
|
});
|
|
@@ -368777,7 +368802,7 @@ var init_instances3 = __esm(() => {
|
|
|
368777
368802
|
const sinceDate = since ? new Date(since) : undefined;
|
|
368778
368803
|
try {
|
|
368779
368804
|
const result = await replayService.replayMissedMessages({ instanceId: instance4.id, since: sinceDate });
|
|
368780
|
-
|
|
368805
|
+
log117.info("Manual replay triggered", {
|
|
368781
368806
|
instanceId: instance4.id,
|
|
368782
368807
|
replayed: result.replayed,
|
|
368783
368808
|
since: result.since.toISOString()
|
|
@@ -368793,7 +368818,7 @@ var init_instances3 = __esm(() => {
|
|
|
368793
368818
|
});
|
|
368794
368819
|
} catch (error3) {
|
|
368795
368820
|
const message2 = error3 instanceof Error ? error3.message : "Unknown error";
|
|
368796
|
-
|
|
368821
|
+
log117.error("Manual replay failed", { instanceId: id, error: message2 });
|
|
368797
368822
|
return c.json({ error: { code: "REPLAY_FAILED", message: message2 } }, 500);
|
|
368798
368823
|
}
|
|
368799
368824
|
});
|
|
@@ -368926,7 +368951,7 @@ var init_instances3 = __esm(() => {
|
|
|
368926
368951
|
plugin10.setGuildConfig(id, guildId, newConfig);
|
|
368927
368952
|
}
|
|
368928
368953
|
}
|
|
368929
|
-
|
|
368954
|
+
log117.info("Guild config updated", {
|
|
368930
368955
|
instanceId: id,
|
|
368931
368956
|
guildId,
|
|
368932
368957
|
apiKeyId: apiKey?.id,
|
|
@@ -368955,7 +368980,7 @@ var init_instances3 = __esm(() => {
|
|
|
368955
368980
|
plugin10.removeGuildConfig(id, guildId);
|
|
368956
368981
|
}
|
|
368957
368982
|
}
|
|
368958
|
-
|
|
368983
|
+
log117.info("Guild config deleted", {
|
|
368959
368984
|
instanceId: id,
|
|
368960
368985
|
guildId,
|
|
368961
368986
|
apiKeyId: apiKey?.id,
|
|
@@ -369870,7 +369895,7 @@ function isValidPathComponent(component) {
|
|
|
369870
369895
|
function isValidUUID(str2) {
|
|
369871
369896
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str2);
|
|
369872
369897
|
}
|
|
369873
|
-
var
|
|
369898
|
+
var log118, mediaRoutes, mediaStorage = null, ttsAudioFormatSchema, ttsRequestSchema, sttRequestSchema, imagineAspectRatioSchema, imagineRequestSchema, visionRequestSchema, filmAspectRatioSchema, imageMimeTypeSchema, imageBase64Schema, filmRequestSchema, FILM_TIMEOUT_MS, FILM_POLL_INTERVAL_MS = 5000, musicRequestSchema;
|
|
369874
369899
|
var init_media2 = __esm(() => {
|
|
369875
369900
|
init_dist6();
|
|
369876
369901
|
init_src();
|
|
@@ -369878,7 +369903,7 @@ var init_media2 = __esm(() => {
|
|
|
369878
369903
|
init_zod();
|
|
369879
369904
|
init_registry3();
|
|
369880
369905
|
init_media_storage();
|
|
369881
|
-
|
|
369906
|
+
log118 = createLogger("routes:media");
|
|
369882
369907
|
mediaRoutes = new Hono2;
|
|
369883
369908
|
ttsAudioFormatSchema = exports_external.enum(["mp3", "ogg", "opus", "wav", "pcm", "flac", "aac"]);
|
|
369884
369909
|
ttsRequestSchema = exports_external.object({
|
|
@@ -369905,7 +369930,7 @@ var init_media2 = __esm(() => {
|
|
|
369905
369930
|
provider = await providerRegistry.resolve("tts", body.provider);
|
|
369906
369931
|
} catch (err2) {
|
|
369907
369932
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
369908
|
-
|
|
369933
|
+
log118.warn("TTS provider resolution failed", { provider: body.provider, error: message2 });
|
|
369909
369934
|
return c.json({
|
|
369910
369935
|
error: {
|
|
369911
369936
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -369941,7 +369966,7 @@ var init_media2 = __esm(() => {
|
|
|
369941
369966
|
});
|
|
369942
369967
|
} catch (err2) {
|
|
369943
369968
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
369944
|
-
|
|
369969
|
+
log118.error("TTS synthesis failed", { provider: provider.name, error: message2 });
|
|
369945
369970
|
return c.json({
|
|
369946
369971
|
error: {
|
|
369947
369972
|
code: "TTS_SYNTHESIS_FAILED",
|
|
@@ -369969,7 +369994,7 @@ var init_media2 = __esm(() => {
|
|
|
369969
369994
|
provider = await providerRegistry.resolve("stt", body.provider);
|
|
369970
369995
|
} catch (err2) {
|
|
369971
369996
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
369972
|
-
|
|
369997
|
+
log118.warn("STT provider resolution failed", { provider: body.provider, error: message2 });
|
|
369973
369998
|
return c.json({
|
|
369974
369999
|
error: {
|
|
369975
370000
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -370013,7 +370038,7 @@ var init_media2 = __esm(() => {
|
|
|
370013
370038
|
});
|
|
370014
370039
|
} catch (err2) {
|
|
370015
370040
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370016
|
-
|
|
370041
|
+
log118.error("STT transcription failed", { provider: provider.name, error: message2 });
|
|
370017
370042
|
return c.json({
|
|
370018
370043
|
error: {
|
|
370019
370044
|
code: "STT_TRANSCRIPTION_FAILED",
|
|
@@ -370045,7 +370070,7 @@ var init_media2 = __esm(() => {
|
|
|
370045
370070
|
provider = await providerRegistry.resolve("imagegen", body.provider);
|
|
370046
370071
|
} catch (err2) {
|
|
370047
370072
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370048
|
-
|
|
370073
|
+
log118.warn("Imagegen provider resolution failed", { provider: body.provider, error: message2 });
|
|
370049
370074
|
return c.json({
|
|
370050
370075
|
error: {
|
|
370051
370076
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -370083,7 +370108,7 @@ var init_media2 = __esm(() => {
|
|
|
370083
370108
|
});
|
|
370084
370109
|
} catch (err2) {
|
|
370085
370110
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370086
|
-
|
|
370111
|
+
log118.error("Image generation failed", { provider: provider.name, error: message2 });
|
|
370087
370112
|
return c.json({
|
|
370088
370113
|
error: {
|
|
370089
370114
|
code: "IMAGE_GEN_FAILED",
|
|
@@ -370108,7 +370133,7 @@ var init_media2 = __esm(() => {
|
|
|
370108
370133
|
provider = await providerRegistry.resolve("vision", body.provider);
|
|
370109
370134
|
} catch (err2) {
|
|
370110
370135
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370111
|
-
|
|
370136
|
+
log118.warn("Vision provider resolution failed", { provider: body.provider, error: message2 });
|
|
370112
370137
|
return c.json({
|
|
370113
370138
|
error: {
|
|
370114
370139
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -370147,7 +370172,7 @@ var init_media2 = __esm(() => {
|
|
|
370147
370172
|
});
|
|
370148
370173
|
} catch (err2) {
|
|
370149
370174
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370150
|
-
|
|
370175
|
+
log118.error("Vision description failed", { provider: provider.name, error: message2 });
|
|
370151
370176
|
return c.json({
|
|
370152
370177
|
error: {
|
|
370153
370178
|
code: "VISION_DESCRIBE_FAILED",
|
|
@@ -370185,7 +370210,7 @@ var init_media2 = __esm(() => {
|
|
|
370185
370210
|
provider = await providerRegistry.resolve("videogen", body.provider);
|
|
370186
370211
|
} catch (err2) {
|
|
370187
370212
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370188
|
-
|
|
370213
|
+
log118.warn("Videogen provider resolution failed", { provider: body.provider, error: message2 });
|
|
370189
370214
|
return c.json({
|
|
370190
370215
|
error: {
|
|
370191
370216
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -370228,7 +370253,7 @@ var init_media2 = __esm(() => {
|
|
|
370228
370253
|
}
|
|
370229
370254
|
if (operation.state === "failed" || !operation.video) {
|
|
370230
370255
|
const message2 = operation.error ?? "Video generation failed without error";
|
|
370231
|
-
|
|
370256
|
+
log118.error("Videogen operation failed", { provider: provider.name, error: message2 });
|
|
370232
370257
|
return c.json({
|
|
370233
370258
|
error: {
|
|
370234
370259
|
code: "VIDEO_GEN_FAILED",
|
|
@@ -370239,7 +370264,7 @@ var init_media2 = __esm(() => {
|
|
|
370239
370264
|
}, 500);
|
|
370240
370265
|
}
|
|
370241
370266
|
const video = operation.video;
|
|
370242
|
-
|
|
370267
|
+
log118.info("Videogen operation complete", {
|
|
370243
370268
|
provider: provider.name,
|
|
370244
370269
|
operationId: operation.operationId,
|
|
370245
370270
|
sizeBytes: video.data.length,
|
|
@@ -370258,7 +370283,7 @@ var init_media2 = __esm(() => {
|
|
|
370258
370283
|
});
|
|
370259
370284
|
} catch (err2) {
|
|
370260
370285
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370261
|
-
|
|
370286
|
+
log118.error("Videogen request failed", { provider: provider.name, error: message2 });
|
|
370262
370287
|
return c.json({
|
|
370263
370288
|
error: {
|
|
370264
370289
|
code: "VIDEO_GEN_FAILED",
|
|
@@ -370293,7 +370318,7 @@ var init_media2 = __esm(() => {
|
|
|
370293
370318
|
provider = await providerRegistry.resolve("musicgen", body.provider);
|
|
370294
370319
|
} catch (err2) {
|
|
370295
370320
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370296
|
-
|
|
370321
|
+
log118.warn("Musicgen provider resolution failed", { provider: body.provider, error: message2 });
|
|
370297
370322
|
return c.json({
|
|
370298
370323
|
error: {
|
|
370299
370324
|
code: "PROVIDER_NOT_AVAILABLE",
|
|
@@ -370332,7 +370357,7 @@ var init_media2 = __esm(() => {
|
|
|
370332
370357
|
});
|
|
370333
370358
|
} catch (err2) {
|
|
370334
370359
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
370335
|
-
|
|
370360
|
+
log118.error("Music generation failed", { provider: provider.name, error: message2 });
|
|
370336
370361
|
return c.json({
|
|
370337
370362
|
error: {
|
|
370338
370363
|
code: "MUSIC_GEN_FAILED",
|
|
@@ -370406,7 +370431,7 @@ var init_media2 = __esm(() => {
|
|
|
370406
370431
|
}
|
|
370407
370432
|
});
|
|
370408
370433
|
} catch (err2) {
|
|
370409
|
-
|
|
370434
|
+
log118.error("Media backend read failed", { relativePath, error: String(err2) });
|
|
370410
370435
|
return c.json({ error: { code: "MEDIA_BACKEND_UNAVAILABLE", message: "Media storage backend unavailable, retry later" } }, 503);
|
|
370411
370436
|
}
|
|
370412
370437
|
});
|
|
@@ -370475,7 +370500,7 @@ async function resolveReactionTarget(services, instanceId, resolvedTo, messageId
|
|
|
370475
370500
|
recoverable: false
|
|
370476
370501
|
});
|
|
370477
370502
|
}
|
|
370478
|
-
|
|
370503
|
+
log119.warn("Reaction target chat not found in DB; deferring fromMe to channel plugin fallback (#386)", {
|
|
370479
370504
|
instanceId,
|
|
370480
370505
|
resolvedTo,
|
|
370481
370506
|
messageId,
|
|
@@ -370485,7 +370510,7 @@ async function resolveReactionTarget(services, instanceId, resolvedTo, messageId
|
|
|
370485
370510
|
}
|
|
370486
370511
|
const target = isUUID(messageId) ? await getReactionTargetByOmniId(services, instanceId, chat2.id, messageId) : await services.messages.getByExternalId(chat2.id, messageId);
|
|
370487
370512
|
if (!target) {
|
|
370488
|
-
|
|
370513
|
+
log119.warn("Reaction target message not found in DB; deferring fromMe to channel plugin fallback (#386)", {
|
|
370489
370514
|
instanceId,
|
|
370490
370515
|
chatId: chat2.id,
|
|
370491
370516
|
messageId,
|
|
@@ -370636,7 +370661,7 @@ function resolveSentByAgentId(sentBy, instance4) {
|
|
|
370636
370661
|
if (sentBy !== "agent")
|
|
370637
370662
|
return;
|
|
370638
370663
|
if (!instance4.agentId) {
|
|
370639
|
-
|
|
370664
|
+
log119.warn("sentBy=agent could not be attributed: instance has no configured agent", { instanceId: instance4.id });
|
|
370640
370665
|
return;
|
|
370641
370666
|
}
|
|
370642
370667
|
return instance4.agentId;
|
|
@@ -370745,10 +370770,10 @@ async function resolveChannelMessageId(services, messageId, instanceId) {
|
|
|
370745
370770
|
return messageId;
|
|
370746
370771
|
const message2 = await services.messages.getById(messageId);
|
|
370747
370772
|
await verifyMessageInstanceOwnership(services, message2, instanceId);
|
|
370748
|
-
|
|
370773
|
+
log119.debug("Resolved internal UUID to external ID", { messageId, externalId: message2.externalId });
|
|
370749
370774
|
return message2.externalId;
|
|
370750
370775
|
}
|
|
370751
|
-
var
|
|
370776
|
+
var log119, mediaDownloadLog, messagesRoutes, MIME_BY_EXTENSION, DEFAULT_MIME_BY_MEDIA_TYPE, UUID_REGEX2, permalinkQuerySchema, MessageSourceSchema, MessageTypeSchema, MessageStatusSchema, DeliveryStatusSchema, listQuerySchema14, createMessageSchema, updateMessageSchema, recordEditSchema, addReactionSchema, removeReactionSchema, updateDeliveryStatusSchema, sentByField, MentionSchema, sendTextSchema, sendMediaSchema, sendReactionSchema, sendStickerSchema, sendContactSchema, sendLocationSchema, sendHandoffSchema, sendCloseContactSchema, messageRefSchema, _mediaStorageForDownload = null, sendTtsSchema, forwardMessageSchema, sendPresenceSchema, markMessageReadSchema, markBatchReadSchema, sendPollSchema, sendEmbedSchema, editMessageChannelSchema, deleteMessageChannelSchema, starMessageSchema;
|
|
370752
370777
|
var init_messages5 = __esm(() => {
|
|
370753
370778
|
init_dist6();
|
|
370754
370779
|
init_src2();
|
|
@@ -370764,7 +370789,7 @@ var init_messages5 = __esm(() => {
|
|
|
370764
370789
|
init_media_storage();
|
|
370765
370790
|
init_tenant_scope();
|
|
370766
370791
|
init__close_contact_config();
|
|
370767
|
-
|
|
370792
|
+
log119 = createLogger("routes:messages");
|
|
370768
370793
|
mediaDownloadLog = createLogger("routes:messages:media-download");
|
|
370769
370794
|
messagesRoutes = new Hono2;
|
|
370770
370795
|
MIME_BY_EXTENSION = {
|
|
@@ -371719,7 +371744,7 @@ var init_messages5 = __esm(() => {
|
|
|
371719
371744
|
channelHandoffSupported: hasNativeHandoff,
|
|
371720
371745
|
...data.motivoHandoff ? { motivoHandoff: data.motivoHandoff } : {}
|
|
371721
371746
|
}
|
|
371722
|
-
}).catch((err2) =>
|
|
371747
|
+
}).catch((err2) => log119.warn("Failed to persist handoff log", { error: String(err2) }));
|
|
371723
371748
|
return c.json({
|
|
371724
371749
|
data: {
|
|
371725
371750
|
messageId: channelSendResult?.messageId ?? null,
|
|
@@ -371820,7 +371845,7 @@ var init_messages5 = __esm(() => {
|
|
|
371820
371845
|
closedFields: data.closeFields ?? null,
|
|
371821
371846
|
closedAt: closedAt.toISOString()
|
|
371822
371847
|
};
|
|
371823
|
-
services.eventBus.publish("chat.closed", payload, { instanceId: data.instanceId }).catch((err2) =>
|
|
371848
|
+
services.eventBus.publish("chat.closed", payload, { instanceId: data.instanceId }).catch((err2) => log119.debug("Failed to publish chat.closed", { error: String(err2) }));
|
|
371824
371849
|
}
|
|
371825
371850
|
return c.json({
|
|
371826
371851
|
data: {
|
|
@@ -373550,7 +373575,7 @@ function makeClient(cfg) {
|
|
|
373550
373575
|
function variablesToBodyParameters(variables) {
|
|
373551
373576
|
return Object.entries(variables).map(([k2, v2]) => [Number.parseInt(k2, 10), v2]).filter(([n2]) => Number.isFinite(n2) && n2 >= 1).sort((a, b3) => a[0] - b3[0]).map(([, v2]) => v2);
|
|
373552
373577
|
}
|
|
373553
|
-
var
|
|
373578
|
+
var log120, templatesRoutes, instanceAccess3, idParamSchema6, templateIdParamSchema, templateNameParamSchema, listQuerySchema19, createBodySchema, sendTestBodySchema, sendByNameBodySchema;
|
|
373554
373579
|
var init_templates3 = __esm(() => {
|
|
373555
373580
|
init_dist6();
|
|
373556
373581
|
init_src6();
|
|
@@ -373561,7 +373586,7 @@ var init_templates3 = __esm(() => {
|
|
|
373561
373586
|
init_dist2();
|
|
373562
373587
|
init_zod();
|
|
373563
373588
|
init_auth();
|
|
373564
|
-
|
|
373589
|
+
log120 = createLogger("routes:whatsapp-templates");
|
|
373565
373590
|
templatesRoutes = new Hono2;
|
|
373566
373591
|
instanceAccess3 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
373567
373592
|
idParamSchema6 = exports_external.object({
|
|
@@ -373688,7 +373713,7 @@ var init_templates3 = __esm(() => {
|
|
|
373688
373713
|
});
|
|
373689
373714
|
return c.json({ data: persisted.row }, persisted.created ? 201 : 200);
|
|
373690
373715
|
} catch (dbErr) {
|
|
373691
|
-
|
|
373716
|
+
log120.error("[whatsapp-business] local template mirror failed after Meta create", {
|
|
373692
373717
|
instanceId,
|
|
373693
373718
|
metaTemplateId: result.id,
|
|
373694
373719
|
name: body.name,
|
|
@@ -374341,7 +374366,7 @@ function readMetaAppEnv() {
|
|
|
374341
374366
|
return {
|
|
374342
374367
|
appId: process.env.META_APP_ID,
|
|
374343
374368
|
appSecret: process.env.META_APP_SECRET,
|
|
374344
|
-
apiVersion:
|
|
374369
|
+
apiVersion: resolveMetaApiVersion(undefined) ?? "v25.0"
|
|
374345
374370
|
};
|
|
374346
374371
|
}
|
|
374347
374372
|
function ensureWhatsAppBusiness(instance4) {
|
|
@@ -374387,7 +374412,7 @@ async function readProfilePhotoUpload(c) {
|
|
|
374387
374412
|
fileType: blob.type || "image/jpeg"
|
|
374388
374413
|
};
|
|
374389
374414
|
}
|
|
374390
|
-
var
|
|
374415
|
+
var log121, whatsappBusinessRoutes, instanceAccess4, analyticsQuerySchema2, updateProfileSchema;
|
|
374391
374416
|
var init_whatsapp_business3 = __esm(() => {
|
|
374392
374417
|
init_dist6();
|
|
374393
374418
|
init_src6();
|
|
@@ -374396,8 +374421,9 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374396
374421
|
init_dist2();
|
|
374397
374422
|
init_zod();
|
|
374398
374423
|
init_oauth_token_cache();
|
|
374424
|
+
init_whatsapp_business_connection();
|
|
374399
374425
|
init_auth();
|
|
374400
|
-
|
|
374426
|
+
log121 = createLogger("api:whatsapp-business");
|
|
374401
374427
|
whatsappBusinessRoutes = new Hono2;
|
|
374402
374428
|
instanceAccess4 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
374403
374429
|
whatsappBusinessRoutes.use("/:id/whatsapp-business/*", instanceAccess4);
|
|
@@ -374423,7 +374449,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374423
374449
|
});
|
|
374424
374450
|
} catch (err2) {
|
|
374425
374451
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
374426
|
-
|
|
374452
|
+
log121.error("OAuth exchange failed", { error: message2 });
|
|
374427
374453
|
return c.json({ error: { code: "OAUTH_EXCHANGE_FAILED", message: message2 } }, 400);
|
|
374428
374454
|
}
|
|
374429
374455
|
});
|
|
@@ -374483,7 +374509,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374483
374509
|
await services.instances.update(id, { metaDisplayPhoneNumber: displayPhoneNumber });
|
|
374484
374510
|
}
|
|
374485
374511
|
} catch (err2) {
|
|
374486
|
-
|
|
374512
|
+
log121.warn("Failed to fetch phone_number info during connect \u2014 continuing", {
|
|
374487
374513
|
instanceId: id,
|
|
374488
374514
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
374489
374515
|
});
|
|
@@ -374509,7 +374535,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374509
374535
|
});
|
|
374510
374536
|
} catch (err2) {
|
|
374511
374537
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
374512
|
-
|
|
374538
|
+
log121.error("plugin.connect failed for whatsapp-business", { instanceId: id, error: message2 });
|
|
374513
374539
|
return c.json({ error: { code: "CONNECT_FAILED", message: message2 } }, 500);
|
|
374514
374540
|
}
|
|
374515
374541
|
return c.json({
|
|
@@ -374537,7 +374563,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374537
374563
|
return c.json({ ok: true });
|
|
374538
374564
|
} catch (err2) {
|
|
374539
374565
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
374540
|
-
|
|
374566
|
+
log121.error("register phone number failed", { instanceId: id, error: message2 });
|
|
374541
374567
|
return c.json({ error: { code: "REGISTER_FAILED", message: message2 } }, 500);
|
|
374542
374568
|
}
|
|
374543
374569
|
});
|
|
@@ -374556,7 +374582,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374556
374582
|
return c.json({ subscribed: result.success });
|
|
374557
374583
|
} catch (err2) {
|
|
374558
374584
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
374559
|
-
|
|
374585
|
+
log121.error("subscribe app failed", { instanceId: id, error: message2 });
|
|
374560
374586
|
return c.json({ error: { code: "SUBSCRIBE_FAILED", message: message2 } }, 500);
|
|
374561
374587
|
}
|
|
374562
374588
|
});
|
|
@@ -374594,7 +374620,7 @@ var init_whatsapp_business3 = __esm(() => {
|
|
|
374594
374620
|
try {
|
|
374595
374621
|
await plugin10.disconnect(id);
|
|
374596
374622
|
} catch (err2) {
|
|
374597
|
-
|
|
374623
|
+
log121.warn("plugin.disconnect failed during connection delete", {
|
|
374598
374624
|
instanceId: id,
|
|
374599
374625
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
374600
374626
|
});
|
|
@@ -374807,7 +374833,7 @@ function flowJsonInvalid(issues) {
|
|
|
374807
374833
|
issues
|
|
374808
374834
|
};
|
|
374809
374835
|
}
|
|
374810
|
-
var
|
|
374836
|
+
var log122, whatsappFlowsRoutes, instanceAccess5, idParamSchema8, flowIdParamSchema, FlowCategorySchema2, createBodySchema2, updateBodySchema, sendBodySchema;
|
|
374811
374837
|
var init_whatsapp_flows3 = __esm(() => {
|
|
374812
374838
|
init_dist6();
|
|
374813
374839
|
init_src6();
|
|
@@ -374820,7 +374846,7 @@ var init_whatsapp_flows3 = __esm(() => {
|
|
|
374820
374846
|
init_auth();
|
|
374821
374847
|
init_sealed_credentials();
|
|
374822
374848
|
init_whatsapp_business3();
|
|
374823
|
-
|
|
374849
|
+
log122 = createLogger("routes:whatsapp-flows");
|
|
374824
374850
|
whatsappFlowsRoutes = new Hono2;
|
|
374825
374851
|
instanceAccess5 = requireInstanceAccess((c) => c.req.param("id") ?? "");
|
|
374826
374852
|
idParamSchema8 = exports_external.object({
|
|
@@ -374931,7 +374957,7 @@ var init_whatsapp_flows3 = __esm(() => {
|
|
|
374931
374957
|
}
|
|
374932
374958
|
});
|
|
374933
374959
|
const status = await resolved.client.getBusinessPublicKey().catch(() => null);
|
|
374934
|
-
|
|
374960
|
+
log122.info("flow encryption key registered", { instanceId });
|
|
374935
374961
|
return c.json({
|
|
374936
374962
|
data: {
|
|
374937
374963
|
uploaded: true,
|
|
@@ -375063,7 +375089,7 @@ var init_whatsapp_flows3 = __esm(() => {
|
|
|
375063
375089
|
metadata: { flow: { ...flow, flowToken } }
|
|
375064
375090
|
});
|
|
375065
375091
|
if (!result.success) {
|
|
375066
|
-
|
|
375092
|
+
log122.error("flow send failed", { instanceId, to, error: result.error, errorCode: result.errorCode });
|
|
375067
375093
|
return c.json(jsonError2(result.error ?? "Flow send failed", result.errorCode ?? "SEND_FAILED"), 500);
|
|
375068
375094
|
}
|
|
375069
375095
|
return c.json({ messageId: result.messageId, flowToken }, 201);
|
|
@@ -375972,12 +375998,12 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
375972
375998
|
const tracker = getJourneyTracker();
|
|
375973
375999
|
tracker.recordCheckpoint(metadata.correlationId, "T4", JOURNEY_STAGES.T4);
|
|
375974
376000
|
}
|
|
375975
|
-
|
|
376001
|
+
log123.debug("Persisted message.received", {
|
|
375976
376002
|
externalId: payload.externalId,
|
|
375977
376003
|
instanceId: metadata.instanceId
|
|
375978
376004
|
});
|
|
375979
376005
|
} catch (error3) {
|
|
375980
|
-
|
|
376006
|
+
log123.error("Failed to persist message.received", {
|
|
375981
376007
|
externalId: payload.externalId,
|
|
375982
376008
|
error: String(error3)
|
|
375983
376009
|
});
|
|
@@ -376021,12 +376047,12 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
376021
376047
|
};
|
|
376022
376048
|
await sdb.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
376023
376049
|
});
|
|
376024
|
-
|
|
376050
|
+
log123.debug("Persisted message.sent", {
|
|
376025
376051
|
externalId: payload.externalId,
|
|
376026
376052
|
instanceId: metadata.instanceId
|
|
376027
376053
|
});
|
|
376028
376054
|
} catch (error3) {
|
|
376029
|
-
|
|
376055
|
+
log123.error("Failed to persist message.sent", {
|
|
376030
376056
|
externalId: payload.externalId,
|
|
376031
376057
|
error: String(error3)
|
|
376032
376058
|
});
|
|
@@ -376062,11 +376088,11 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
376062
376088
|
await sdb.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
376063
376089
|
}
|
|
376064
376090
|
});
|
|
376065
|
-
|
|
376091
|
+
log123.debug("Persisted message.delivered", {
|
|
376066
376092
|
externalId: payload.externalId
|
|
376067
376093
|
});
|
|
376068
376094
|
} catch (error3) {
|
|
376069
|
-
|
|
376095
|
+
log123.error("Failed to persist message.delivered", {
|
|
376070
376096
|
externalId: payload.externalId,
|
|
376071
376097
|
error: String(error3)
|
|
376072
376098
|
});
|
|
@@ -376101,11 +376127,11 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
376101
376127
|
await sdb.insert(omniEvents).values(newEvent).onConflictDoNothing({ target: omniEvents.id });
|
|
376102
376128
|
}
|
|
376103
376129
|
});
|
|
376104
|
-
|
|
376130
|
+
log123.debug("Persisted message.read", {
|
|
376105
376131
|
externalId: payload.externalId
|
|
376106
376132
|
});
|
|
376107
376133
|
} catch (error3) {
|
|
376108
|
-
|
|
376134
|
+
log123.error("Failed to persist message.read", {
|
|
376109
376135
|
externalId: payload.externalId,
|
|
376110
376136
|
error: String(error3)
|
|
376111
376137
|
});
|
|
@@ -376156,33 +376182,33 @@ async function setupEventPersistence(eventBus, db2) {
|
|
|
376156
376182
|
}
|
|
376157
376183
|
return updated.length;
|
|
376158
376184
|
});
|
|
376159
|
-
|
|
376185
|
+
log123.debug("Persisted message.failed", {
|
|
376160
376186
|
chatId: payload.chatId,
|
|
376161
376187
|
externalId: payload.externalId,
|
|
376162
376188
|
updatedRows,
|
|
376163
376189
|
error: payload.error
|
|
376164
376190
|
});
|
|
376165
376191
|
} catch (error3) {
|
|
376166
|
-
|
|
376192
|
+
log123.error("Failed to persist message.failed", {
|
|
376167
376193
|
chatId: payload.chatId,
|
|
376168
376194
|
error: String(error3)
|
|
376169
376195
|
});
|
|
376170
376196
|
}
|
|
376171
376197
|
}, { ...CONSUMER_OPTIONS, durable: "event-persistence-failed" });
|
|
376172
|
-
|
|
376198
|
+
log123.info("Event persistence initialized - listening for message events");
|
|
376173
376199
|
} catch (error3) {
|
|
376174
|
-
|
|
376200
|
+
log123.error("Failed to set up event persistence", { error: String(error3) });
|
|
376175
376201
|
throw error3;
|
|
376176
376202
|
}
|
|
376177
376203
|
}
|
|
376178
|
-
var
|
|
376204
|
+
var log123, CONSUMER_OPTIONS;
|
|
376179
376205
|
var init_event_persistence = __esm(() => {
|
|
376180
376206
|
init_src();
|
|
376181
376207
|
init_src5();
|
|
376182
376208
|
init_drizzle_orm();
|
|
376183
376209
|
init_tenant_scope();
|
|
376184
376210
|
init_worker_tenant_context();
|
|
376185
|
-
|
|
376211
|
+
log123 = createLogger("event-persistence");
|
|
376186
376212
|
CONSUMER_OPTIONS = {
|
|
376187
376213
|
queue: "event-persistence",
|
|
376188
376214
|
maxRetries: 3,
|
|
@@ -376266,27 +376292,27 @@ async function downloadMediaFromUrl(ctx, instanceId, messageId, mediaUrl, mimeTy
|
|
|
376266
376292
|
try {
|
|
376267
376293
|
const result = await ctx.mediaStorage.storeFromUrl(instanceId, messageId, mediaUrl, mimeType, platformTimestamp, fetchOptions, trustedTenantId);
|
|
376268
376294
|
await runMediaDb(ctx, trustedTenantId, () => ctx.mediaStorage.updateMessageLocalPath(messageId, result.localPath));
|
|
376269
|
-
|
|
376295
|
+
log124.debug("Downloaded media from URL", { messageId, filePath: result.localPath });
|
|
376270
376296
|
return result.localPath;
|
|
376271
376297
|
} catch (error3) {
|
|
376272
|
-
|
|
376298
|
+
log124.error("Failed to download media", { error: String(error3), mediaUrl });
|
|
376273
376299
|
return null;
|
|
376274
376300
|
}
|
|
376275
376301
|
}
|
|
376276
376302
|
async function downloadMediaViaPlugin(ctx, instanceId, messageId, channelType, mediaRef, fallbackMimeType, platformTimestamp, trustedTenantId) {
|
|
376277
376303
|
const plugin10 = await (ctx.resolveChannelPlugin ?? getPlugin)(channelType);
|
|
376278
376304
|
if (!plugin10?.downloadInboundMedia) {
|
|
376279
|
-
|
|
376305
|
+
log124.warn("Channel plugin cannot materialize deferred media", { channelType, messageId });
|
|
376280
376306
|
return null;
|
|
376281
376307
|
}
|
|
376282
376308
|
try {
|
|
376283
376309
|
const { buffer: buffer3, mimeType } = pluginMediaSchema.parse(await plugin10.downloadInboundMedia(instanceId, mediaRef));
|
|
376284
376310
|
const result = await ctx.mediaStorage.storeFromBuffer(instanceId, messageId, buffer3, mimeType || fallbackMimeType, platformTimestamp, trustedTenantId);
|
|
376285
376311
|
await runMediaDb(ctx, trustedTenantId, () => ctx.mediaStorage.updateMessageLocalPath(messageId, result.localPath));
|
|
376286
|
-
|
|
376312
|
+
log124.debug("Downloaded inbound media via plugin", { messageId, channelType, filePath: result.localPath });
|
|
376287
376313
|
return result.localPath;
|
|
376288
376314
|
} catch (error3) {
|
|
376289
|
-
|
|
376315
|
+
log124.error("Failed to download inbound media via plugin", {
|
|
376290
376316
|
error: String(error3),
|
|
376291
376317
|
channelType,
|
|
376292
376318
|
messageId
|
|
@@ -376304,7 +376330,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
376304
376330
|
chat2 = await runMediaDb(ctx, trustedTenantId, () => ctx.services.chats.findByExternalIdSmart(instanceId, chatId));
|
|
376305
376331
|
}
|
|
376306
376332
|
if (!chat2) {
|
|
376307
|
-
|
|
376333
|
+
log124.debug("Chat not found, cannot process media", { chatId, externalId });
|
|
376308
376334
|
return null;
|
|
376309
376335
|
}
|
|
376310
376336
|
const chatDbId = chat2.id;
|
|
@@ -376314,7 +376340,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
376314
376340
|
message2 = await runMediaDb(ctx, trustedTenantId, () => ctx.services.messages.getByExternalId(chatDbId, externalId));
|
|
376315
376341
|
}
|
|
376316
376342
|
if (!message2) {
|
|
376317
|
-
|
|
376343
|
+
log124.debug("Message not found after waiting, cannot process media", { externalId });
|
|
376318
376344
|
return null;
|
|
376319
376345
|
}
|
|
376320
376346
|
let filePath = message2.mediaLocalPath;
|
|
@@ -376329,7 +376355,7 @@ async function resolveMediaPath2(ctx, instanceId, chatId, externalId, content, m
|
|
|
376329
376355
|
return null;
|
|
376330
376356
|
}
|
|
376331
376357
|
if (!filePath) {
|
|
376332
|
-
|
|
376358
|
+
log124.debug("No media file path available", { externalId });
|
|
376333
376359
|
return null;
|
|
376334
376360
|
}
|
|
376335
376361
|
return {
|
|
@@ -376352,13 +376378,13 @@ async function resolveSafeMediaContentEventId(ctx, envelope2, eventId) {
|
|
|
376352
376378
|
return event?.id ?? null;
|
|
376353
376379
|
});
|
|
376354
376380
|
} catch (error3) {
|
|
376355
|
-
|
|
376381
|
+
log124.debug("Failed to validate media_content event FK", { eventId: id, error: String(error3) });
|
|
376356
376382
|
return null;
|
|
376357
376383
|
}
|
|
376358
376384
|
if (found)
|
|
376359
376385
|
return found;
|
|
376360
376386
|
if (Date.now() >= deadline) {
|
|
376361
|
-
|
|
376387
|
+
log124.debug("Skipping media_content event FK; omni_event not found", { eventId: id });
|
|
376362
376388
|
return null;
|
|
376363
376389
|
}
|
|
376364
376390
|
await new Promise((resolve4) => setTimeout(resolve4, pollMs));
|
|
@@ -376394,7 +376420,7 @@ async function persistProcessingResult(ctx, messageId, safeEventId, result, cont
|
|
|
376394
376420
|
await sdb.insert(mediaContent).values(row);
|
|
376395
376421
|
}
|
|
376396
376422
|
} catch (error3) {
|
|
376397
|
-
|
|
376423
|
+
log124.warn("Failed to insert media_content record (non-critical)", {
|
|
376398
376424
|
messageId,
|
|
376399
376425
|
error: String(error3)
|
|
376400
376426
|
});
|
|
@@ -376417,14 +376443,14 @@ async function processMessageMedia(ctx, payload, metadata, envelope2) {
|
|
|
376417
376443
|
const mimeType = getMimeType2(content);
|
|
376418
376444
|
const trustedTenantId = envelopeTenantId(envelope2);
|
|
376419
376445
|
if (!mimeType || !ctx.mediaService.canProcess(mimeType)) {
|
|
376420
|
-
|
|
376446
|
+
log124.debug("MIME type not processable or missing", { mimeType, externalId });
|
|
376421
376447
|
return;
|
|
376422
376448
|
}
|
|
376423
376449
|
const media = await resolveMediaPath2(ctx, instanceId, payload.chatId, externalId, content, mimeType, metadata.channelType, trustedTenantId);
|
|
376424
376450
|
if (!media)
|
|
376425
376451
|
return;
|
|
376426
376452
|
const processable = await ctx.mediaStorage.materializeForProcessing(media.filePath);
|
|
376427
|
-
|
|
376453
|
+
log124.info("Processing media", { messageId: media.messageId, mimeType, filePath: processable.path });
|
|
376428
376454
|
let result;
|
|
376429
376455
|
try {
|
|
376430
376456
|
result = await ctx.mediaService.process(processable.path, mimeType, {
|
|
@@ -376437,7 +376463,7 @@ async function processMessageMedia(ctx, payload, metadata, envelope2) {
|
|
|
376437
376463
|
}
|
|
376438
376464
|
if (!result.success) {
|
|
376439
376465
|
const reason2 = result.errorMessage ?? "unknown";
|
|
376440
|
-
|
|
376466
|
+
log124.warn("Media processing failed", { messageId: media.messageId, error: reason2 });
|
|
376441
376467
|
const processingType = result.processingType ?? inferProcessingType(content.type);
|
|
376442
376468
|
const errorColumn = getContentFieldForType(processingType, content.type);
|
|
376443
376469
|
if (errorColumn) {
|
|
@@ -376465,7 +376491,7 @@ async function processMessageMedia(ctx, payload, metadata, envelope2) {
|
|
|
376465
376491
|
}
|
|
376466
376492
|
const safeEventId = await resolveSafeMediaContentEventId(ctx, envelope2, eventId);
|
|
376467
376493
|
await runConsumerInTenantContext(ctx.db, envelope2, () => persistProcessingResult(ctx, media.messageId, safeEventId, result, content.type));
|
|
376468
|
-
|
|
376494
|
+
log124.info("Media processing complete", {
|
|
376469
376495
|
messageId: media.messageId,
|
|
376470
376496
|
processingType: result.processingType,
|
|
376471
376497
|
provider: result.provider,
|
|
@@ -376505,7 +376531,7 @@ async function publishMediaCrashEvents(ctx, eventId, payload, metadata, error3,
|
|
|
376505
376531
|
error: reason2
|
|
376506
376532
|
}, meta);
|
|
376507
376533
|
} catch (publishError) {
|
|
376508
|
-
|
|
376534
|
+
log124.error("Failed to publish media failure event", { error: String(publishError) });
|
|
376509
376535
|
}
|
|
376510
376536
|
}
|
|
376511
376537
|
async function resolveMediaIdForCrash(ctx, instanceId, payload, trustedTenantId) {
|
|
@@ -376519,7 +376545,7 @@ async function resolveMediaIdForCrash(ctx, instanceId, payload, trustedTenantId)
|
|
|
376519
376545
|
if (msg)
|
|
376520
376546
|
return msg.id;
|
|
376521
376547
|
} catch (lookupError) {
|
|
376522
|
-
|
|
376548
|
+
log124.debug("Failed to resolve DB message UUID for crash handler, falling back to externalId", {
|
|
376523
376549
|
error: String(lookupError),
|
|
376524
376550
|
instanceId,
|
|
376525
376551
|
chatId: payload.chatId
|
|
@@ -376592,7 +376618,7 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
376592
376618
|
channelType: metadata.channelType
|
|
376593
376619
|
}, event);
|
|
376594
376620
|
} catch (error3) {
|
|
376595
|
-
|
|
376621
|
+
log124.error("Failed to process media", {
|
|
376596
376622
|
externalId: payload.externalId,
|
|
376597
376623
|
error: String(error3)
|
|
376598
376624
|
});
|
|
@@ -376607,14 +376633,14 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
376607
376633
|
concurrency: 5
|
|
376608
376634
|
});
|
|
376609
376635
|
setGlobalCircuitBreakerStateChangeCallback((name, from, to) => {
|
|
376610
|
-
|
|
376636
|
+
log124.warn("Circuit breaker state change", { provider: name, from, to });
|
|
376611
376637
|
});
|
|
376612
376638
|
await eventBus.subscribePattern("media.health.request", async (event) => {
|
|
376613
376639
|
const tracker = getMediaHealthTracker();
|
|
376614
376640
|
const report = tracker.getReport();
|
|
376615
376641
|
const correlationId = event.metadata?.correlationId ?? event.id;
|
|
376616
376642
|
await eventBus.publishGeneric("system.media.health.response", { correlationId, report }, { source: "media-processor" });
|
|
376617
|
-
|
|
376643
|
+
log124.debug("Published media health report", {
|
|
376618
376644
|
correlationId,
|
|
376619
376645
|
totalRequests: report.overall.totalRequests,
|
|
376620
376646
|
successRate: report.overall.successRate
|
|
@@ -376623,9 +376649,9 @@ async function setupMediaProcessor(eventBus, db2, services) {
|
|
|
376623
376649
|
durable: "media-health-responder",
|
|
376624
376650
|
queue: "media-health-responder"
|
|
376625
376651
|
});
|
|
376626
|
-
|
|
376652
|
+
log124.info("Media processor initialized");
|
|
376627
376653
|
}
|
|
376628
|
-
var
|
|
376654
|
+
var log124, PROCESSABLE_MEDIA_TYPES, pluginMediaSchema;
|
|
376629
376655
|
var init_media_processor = __esm(() => {
|
|
376630
376656
|
init_src();
|
|
376631
376657
|
init_src5();
|
|
@@ -376636,7 +376662,7 @@ var init_media_processor = __esm(() => {
|
|
|
376636
376662
|
init_tenant_scope();
|
|
376637
376663
|
init_worker_tenant_context();
|
|
376638
376664
|
init_loader2();
|
|
376639
|
-
|
|
376665
|
+
log124 = createLogger("media-processor");
|
|
376640
376666
|
PROCESSABLE_MEDIA_TYPES = new Set(["audio", "image", "document", "video"]);
|
|
376641
376667
|
pluginMediaSchema = exports_external.object({
|
|
376642
376668
|
buffer: exports_external.instanceof(Buffer),
|
|
@@ -376667,7 +376693,7 @@ function createInflightRevocationMonitor(options) {
|
|
|
376667
376693
|
try {
|
|
376668
376694
|
admissible = await check2(tenantId);
|
|
376669
376695
|
} catch (error3) {
|
|
376670
|
-
|
|
376696
|
+
log125.warn("Admissibility check failed \u2014 refusing in-flight work", {
|
|
376671
376697
|
tenantId,
|
|
376672
376698
|
error: String(error3)
|
|
376673
376699
|
});
|
|
@@ -376681,10 +376707,10 @@ function createInflightRevocationMonitor(options) {
|
|
|
376681
376707
|
}
|
|
376682
376708
|
};
|
|
376683
376709
|
}
|
|
376684
|
-
var
|
|
376710
|
+
var log125, INFLIGHT_REVOCATION_CEILING_SECONDS = 30, InflightRevocationError;
|
|
376685
376711
|
var init_inflight_revocation = __esm(() => {
|
|
376686
376712
|
init_src();
|
|
376687
|
-
|
|
376713
|
+
log125 = createLogger("inflight-revocation");
|
|
376688
376714
|
InflightRevocationError = class InflightRevocationError extends Error {
|
|
376689
376715
|
code = "inflight_tenant_revoked";
|
|
376690
376716
|
constructor(tenantId) {
|
|
@@ -376758,7 +376784,7 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
376758
376784
|
await eventBus.subscribe("sync.started", async (event) => {
|
|
376759
376785
|
const payload = event.payload;
|
|
376760
376786
|
const { jobId, instanceId, type, config: config4 } = payload;
|
|
376761
|
-
|
|
376787
|
+
log126.info("Processing sync job", { jobId, instanceId, type });
|
|
376762
376788
|
const jobTenantId = trustedSyncTenant(event);
|
|
376763
376789
|
try {
|
|
376764
376790
|
await services.syncJobs.start(jobId, jobTenantId);
|
|
@@ -376786,12 +376812,12 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
376786
376812
|
case "history-push":
|
|
376787
376813
|
break;
|
|
376788
376814
|
default:
|
|
376789
|
-
|
|
376815
|
+
log126.warn("Unknown sync type", { jobId, type });
|
|
376790
376816
|
await services.syncJobs.fail(jobId, `Unknown sync type: ${type}`, jobTenantId);
|
|
376791
376817
|
}
|
|
376792
376818
|
} catch (error3) {
|
|
376793
376819
|
const errorMessage = error3 instanceof Error ? error3.message : String(error3);
|
|
376794
|
-
|
|
376820
|
+
log126.error("Sync job failed", { jobId, error: errorMessage });
|
|
376795
376821
|
await services.syncJobs.fail(jobId, errorMessage, jobTenantId);
|
|
376796
376822
|
}
|
|
376797
376823
|
}, {
|
|
@@ -376799,9 +376825,9 @@ async function setupSyncWorker(eventBus, services, channelRegistry2, database) {
|
|
|
376799
376825
|
queue: "sync-workers",
|
|
376800
376826
|
startFrom: "new"
|
|
376801
376827
|
});
|
|
376802
|
-
|
|
376828
|
+
log126.info("Sync worker initialized - listening for sync.started events");
|
|
376803
376829
|
} catch (error3) {
|
|
376804
|
-
|
|
376830
|
+
log126.error("Failed to set up sync worker", { error: String(error3) });
|
|
376805
376831
|
throw error3;
|
|
376806
376832
|
}
|
|
376807
376833
|
}
|
|
@@ -376839,20 +376865,20 @@ async function buildWhatsAppAnchors(database, instanceId) {
|
|
|
376839
376865
|
});
|
|
376840
376866
|
}
|
|
376841
376867
|
}
|
|
376842
|
-
|
|
376868
|
+
log126.info("Built WhatsApp anchors", { instanceId, anchorCount: anchors.length });
|
|
376843
376869
|
return anchors;
|
|
376844
376870
|
}
|
|
376845
376871
|
function buildAnchorsForExplicitChatJids(jobId, chatJids, dbAnchors) {
|
|
376846
|
-
|
|
376872
|
+
log126.info("Using explicit chatJids for sync", { jobId, chatJids });
|
|
376847
376873
|
const anchors = [];
|
|
376848
376874
|
for (const jid of chatJids) {
|
|
376849
376875
|
const dbAnchor = dbAnchors.find((a) => a.chatJid === jid);
|
|
376850
376876
|
if (dbAnchor) {
|
|
376851
|
-
|
|
376877
|
+
log126.debug("Found DB anchor for chatJid", { jobId, chatJid: jid, anchorId: dbAnchor.messageKey.id });
|
|
376852
376878
|
anchors.push(dbAnchor);
|
|
376853
376879
|
continue;
|
|
376854
376880
|
}
|
|
376855
|
-
|
|
376881
|
+
log126.debug("No DB anchor for chatJid, will fetch recent", { jobId, chatJid: jid });
|
|
376856
376882
|
anchors.push({
|
|
376857
376883
|
chatJid: jid,
|
|
376858
376884
|
messageKey: { remoteJid: jid, id: "", fromMe: false },
|
|
@@ -376878,7 +376904,7 @@ async function discoverAnchorsFromPlugin(jobId, instanceId, plugin10, dbAnchors,
|
|
|
376878
376904
|
discovered.push({ chatJid: jid, messageKey: { remoteJid: jid, id: "", fromMe: false }, timestamp: Date.now() });
|
|
376879
376905
|
}
|
|
376880
376906
|
if (discovered.length > 0) {
|
|
376881
|
-
|
|
376907
|
+
log126.info("Discovered chats from DB + Baileys not in anchors", {
|
|
376882
376908
|
jobId,
|
|
376883
376909
|
discoveredCount: discovered.length,
|
|
376884
376910
|
fromDb: dbExternalIds.length,
|
|
@@ -376904,7 +376930,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
376904
376930
|
await revocation.assertAdmissible();
|
|
376905
376931
|
let inflightRevoked = null;
|
|
376906
376932
|
if (!("fetchHistory" in plugin10) || typeof plugin10.fetchHistory !== "function") {
|
|
376907
|
-
|
|
376933
|
+
log126.warn("Plugin does not support fetchHistory", { channelType });
|
|
376908
376934
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
376909
376935
|
return;
|
|
376910
376936
|
}
|
|
@@ -376913,7 +376939,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
376913
376939
|
let fetched = 0;
|
|
376914
376940
|
let stored = 0;
|
|
376915
376941
|
let duplicates = 0;
|
|
376916
|
-
|
|
376942
|
+
log126.info("Starting message sync", {
|
|
376917
376943
|
jobId,
|
|
376918
376944
|
instanceId,
|
|
376919
376945
|
channelType,
|
|
@@ -376923,13 +376949,13 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
376923
376949
|
if (channelType === "whatsapp-baileys" && config4.chatJids?.length) {
|
|
376924
376950
|
const dbAnchors = handle ? await inSyncWorkerScope(envelope2, () => buildWhatsAppAnchors(handle, instanceId)) : [];
|
|
376925
376951
|
anchors = await resolveWhatsAppAnchors(jobId, instanceId, config4, plugin10, dbAnchors, services, envelope2);
|
|
376926
|
-
|
|
376952
|
+
log126.info("WhatsApp per-chat active sync", { jobId, anchorCount: anchors.length, chatJids: config4.chatJids });
|
|
376927
376953
|
} else if (channelType === "whatsapp-baileys") {
|
|
376928
376954
|
const dbAnchors = handle ? await inSyncWorkerScope(envelope2, () => buildWhatsAppAnchors(handle, instanceId)) : [];
|
|
376929
376955
|
const discoveredAnchors = await discoverAnchorsFromPlugin(jobId, instanceId, plugin10, dbAnchors, services, envelope2);
|
|
376930
376956
|
anchors = [...dbAnchors, ...discoveredAnchors];
|
|
376931
376957
|
if (anchors.length > 0) {
|
|
376932
|
-
|
|
376958
|
+
log126.info("WhatsApp default sync with DB+cache discovery", {
|
|
376933
376959
|
jobId,
|
|
376934
376960
|
instanceId,
|
|
376935
376961
|
dbAnchorCount: dbAnchors.length,
|
|
@@ -376937,7 +376963,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
376937
376963
|
totalAnchors: anchors.length
|
|
376938
376964
|
});
|
|
376939
376965
|
} else {
|
|
376940
|
-
|
|
376966
|
+
log126.info("WhatsApp passive sync (no prior data)", { jobId, instanceId });
|
|
376941
376967
|
}
|
|
376942
376968
|
}
|
|
376943
376969
|
const fetchOptions = {
|
|
@@ -377000,7 +377026,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
377000
377026
|
else
|
|
377001
377027
|
stored++;
|
|
377002
377028
|
} catch (error3) {
|
|
377003
|
-
|
|
377029
|
+
log126.warn("Failed to store synced message", {
|
|
377004
377030
|
externalId: msg.externalId,
|
|
377005
377031
|
error: String(error3)
|
|
377006
377032
|
});
|
|
@@ -377020,7 +377046,7 @@ async function processMessageSync(jobId, instanceId, channelType, config4, servi
|
|
|
377020
377046
|
}, jobTenantId);
|
|
377021
377047
|
await queueMediaBackfillAfterSync(services, config4, instanceId, jobId, stored, jobTenantId);
|
|
377022
377048
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
377023
|
-
|
|
377049
|
+
log126.info("Message sync completed", {
|
|
377024
377050
|
jobId,
|
|
377025
377051
|
fetched,
|
|
377026
377052
|
stored,
|
|
@@ -377042,9 +377068,9 @@ async function queueMediaBackfillAfterSync(services, config4, instanceId, jobId,
|
|
|
377042
377068
|
delayMaxMs: config4.delayMaxMs ?? 3000
|
|
377043
377069
|
};
|
|
377044
377070
|
const batch = await services.batchJobs.create(params, trustedTenantId);
|
|
377045
|
-
|
|
377071
|
+
log126.info("Queued media backfill batch after message sync", { jobId, batchJobId: batch.id, stored });
|
|
377046
377072
|
} catch (error3) {
|
|
377047
|
-
|
|
377073
|
+
log126.warn("Failed to queue media backfill batch after message sync", { jobId, error: String(error3) });
|
|
377048
377074
|
}
|
|
377049
377075
|
}
|
|
377050
377076
|
function mapContentType3(contentType) {
|
|
@@ -377093,14 +377119,14 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
377093
377119
|
await revocation.assertAdmissible();
|
|
377094
377120
|
let inflightRevoked = null;
|
|
377095
377121
|
if (!("fetchContacts" in plugin10) || typeof plugin10.fetchContacts !== "function") {
|
|
377096
|
-
|
|
377122
|
+
log126.warn("Plugin does not support fetchContacts", { channelType });
|
|
377097
377123
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
377098
377124
|
return;
|
|
377099
377125
|
}
|
|
377100
377126
|
let fetched = 0;
|
|
377101
377127
|
let stored = 0;
|
|
377102
377128
|
let linked = 0;
|
|
377103
|
-
|
|
377129
|
+
log126.info("Starting contacts sync", {
|
|
377104
377130
|
jobId,
|
|
377105
377131
|
instanceId,
|
|
377106
377132
|
channelType
|
|
@@ -377150,7 +377176,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
377150
377176
|
await updateDmChatName(services, instanceId, c.platformUserId, c.name, envelope2);
|
|
377151
377177
|
}
|
|
377152
377178
|
} catch (error3) {
|
|
377153
|
-
|
|
377179
|
+
log126.warn("Failed to store synced contact", {
|
|
377154
377180
|
platformUserId: c.platformUserId,
|
|
377155
377181
|
error: String(error3)
|
|
377156
377182
|
});
|
|
@@ -377169,7 +377195,7 @@ async function processContactsSync(jobId, instanceId, channelType, config4, serv
|
|
|
377169
377195
|
duplicates: 0
|
|
377170
377196
|
}, jobTenantId);
|
|
377171
377197
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
377172
|
-
|
|
377198
|
+
log126.info("Contacts sync completed", {
|
|
377173
377199
|
jobId,
|
|
377174
377200
|
fetched,
|
|
377175
377201
|
stored,
|
|
@@ -377221,7 +377247,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
377221
377247
|
let inflightRevoked = null;
|
|
377222
377248
|
const fetchMethod = channelType === "discord" ? "fetchGuilds" : "fetchGroups";
|
|
377223
377249
|
if (!(fetchMethod in plugin10) || typeof plugin10[fetchMethod] !== "function") {
|
|
377224
|
-
|
|
377250
|
+
log126.warn(`Plugin does not support ${fetchMethod}`, { channelType });
|
|
377225
377251
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
377226
377252
|
return;
|
|
377227
377253
|
}
|
|
@@ -377232,7 +377258,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
377232
377258
|
let fetched = 0;
|
|
377233
377259
|
let stored = 0;
|
|
377234
377260
|
let updated = 0;
|
|
377235
|
-
|
|
377261
|
+
log126.info("Starting groups sync", {
|
|
377236
377262
|
jobId,
|
|
377237
377263
|
instanceId,
|
|
377238
377264
|
channelType
|
|
@@ -377266,7 +377292,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
377266
377292
|
else
|
|
377267
377293
|
stored++;
|
|
377268
377294
|
} catch (error3) {
|
|
377269
|
-
|
|
377295
|
+
log126.warn("Failed to store synced group", {
|
|
377270
377296
|
externalId: g2.externalId,
|
|
377271
377297
|
error: String(error3)
|
|
377272
377298
|
});
|
|
@@ -377313,7 +377339,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
377313
377339
|
else
|
|
377314
377340
|
stored++;
|
|
377315
377341
|
} catch (error3) {
|
|
377316
|
-
|
|
377342
|
+
log126.warn("Failed to store synced guild", {
|
|
377317
377343
|
externalId: g2.externalId,
|
|
377318
377344
|
error: String(error3)
|
|
377319
377345
|
});
|
|
@@ -377330,7 +377356,7 @@ async function processGroupsSync(jobId, instanceId, channelType, _config, servic
|
|
|
377330
377356
|
duplicates: updated
|
|
377331
377357
|
}, jobTenantId);
|
|
377332
377358
|
await services.syncJobs.complete(jobId, jobTenantId);
|
|
377333
|
-
|
|
377359
|
+
log126.info("Groups sync completed", {
|
|
377334
377360
|
jobId,
|
|
377335
377361
|
fetched,
|
|
377336
377362
|
stored,
|
|
@@ -377454,7 +377480,7 @@ async function setupHistoryPushTracker(eventBus, services) {
|
|
|
377454
377480
|
throw error3;
|
|
377455
377481
|
}
|
|
377456
377482
|
}
|
|
377457
|
-
var
|
|
377483
|
+
var log126, RATE_LIMITS2, db2 = null, historyPushLog;
|
|
377458
377484
|
var init_sync_worker = __esm(() => {
|
|
377459
377485
|
init_src();
|
|
377460
377486
|
init_src5();
|
|
@@ -377463,7 +377489,7 @@ var init_sync_worker = __esm(() => {
|
|
|
377463
377489
|
init_periodic_tenant_work();
|
|
377464
377490
|
init_tenant_scope();
|
|
377465
377491
|
init_worker_tenant_context();
|
|
377466
|
-
|
|
377492
|
+
log126 = createLogger("sync-worker");
|
|
377467
377493
|
RATE_LIMITS2 = {
|
|
377468
377494
|
"whatsapp-baileys": 30,
|
|
377469
377495
|
discord: 50,
|
|
@@ -377485,7 +377511,7 @@ async function resolveChatId2(services, db3, tenantId, instanceId, externalId) {
|
|
|
377485
377511
|
const chat2 = await runTenantWorkDb(db3, tenantId, () => services.chats.findByExternalIdSmart(instanceId, externalId));
|
|
377486
377512
|
return chat2?.id ?? null;
|
|
377487
377513
|
} catch (err2) {
|
|
377488
|
-
|
|
377514
|
+
log127.warn("follow-up-hooks: failed to resolve chatId", { instanceId, externalId, error: String(err2) });
|
|
377489
377515
|
return null;
|
|
377490
377516
|
}
|
|
377491
377517
|
}
|
|
@@ -377596,16 +377622,16 @@ async function setupFollowUpHooks(eventBus, services, db3) {
|
|
|
377596
377622
|
retryDelayMs: 500,
|
|
377597
377623
|
startFrom: "new"
|
|
377598
377624
|
});
|
|
377599
|
-
|
|
377625
|
+
log127.info("Follow-up hooks active (message.sent/received, chat.handoff_activated, chat.archived, chat.closed)");
|
|
377600
377626
|
} catch (error3) {
|
|
377601
|
-
|
|
377627
|
+
log127.error("Failed to set up follow-up hooks", { error: String(error3) });
|
|
377602
377628
|
}
|
|
377603
377629
|
}
|
|
377604
|
-
var
|
|
377630
|
+
var log127;
|
|
377605
377631
|
var init_follow_up_hooks = __esm(() => {
|
|
377606
377632
|
init_src();
|
|
377607
377633
|
init_worker_tenant_context();
|
|
377608
|
-
|
|
377634
|
+
log127 = createLogger("follow-up-hooks");
|
|
377609
377635
|
});
|
|
377610
377636
|
|
|
377611
377637
|
// ../api/src/plugins/instance-monitor.ts
|
|
@@ -378046,6 +378072,7 @@ var logger7, DEFAULT_CONFIG3, STALE_TRANSITION_MAX_AGE_MS;
|
|
|
378046
378072
|
var init_instance_monitor = __esm(() => {
|
|
378047
378073
|
init_src5();
|
|
378048
378074
|
init_drizzle_orm();
|
|
378075
|
+
init_whatsapp_business_connection();
|
|
378049
378076
|
init_instance_owner_registry();
|
|
378050
378077
|
init_periodic_tenant_work();
|
|
378051
378078
|
init_tenant_scope();
|
|
@@ -378090,7 +378117,7 @@ async function resolveCallAgentChatIds(services, db3, ctx, trustedTenantId) {
|
|
|
378090
378117
|
senderId: ctx.senderId === ctx.chatId ? chat2.externalId : ctx.senderId
|
|
378091
378118
|
};
|
|
378092
378119
|
} catch {
|
|
378093
|
-
|
|
378120
|
+
log128.warn("call_agent: chat UUID not resolvable, using raw value (session may diverge)", {
|
|
378094
378121
|
chatId: ctx.chatId,
|
|
378095
378122
|
instanceId: ctx.instanceId
|
|
378096
378123
|
});
|
|
@@ -378177,7 +378204,7 @@ function buildAutomationEngineDeps(services, db3, options = {}) {
|
|
|
378177
378204
|
releaseIdleTimeoutClaim: (claimToken) => releaseIdleTimeoutClaim(claimToken)
|
|
378178
378205
|
};
|
|
378179
378206
|
}
|
|
378180
|
-
var
|
|
378207
|
+
var log128, UUID_RE3;
|
|
378181
378208
|
var init_automation_actions = __esm(() => {
|
|
378182
378209
|
init_src();
|
|
378183
378210
|
init_src5();
|
|
@@ -378186,7 +378213,7 @@ var init_automation_actions = __esm(() => {
|
|
|
378186
378213
|
init_tenant_scope();
|
|
378187
378214
|
init_worker_tenant_context();
|
|
378188
378215
|
init_loader2();
|
|
378189
|
-
|
|
378216
|
+
log128 = createLogger("automation-actions");
|
|
378190
378217
|
UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
378191
378218
|
});
|
|
378192
378219
|
|
|
@@ -378209,7 +378236,7 @@ async function createDailySyncJobs(services, type) {
|
|
|
378209
378236
|
});
|
|
378210
378237
|
jobsCreated++;
|
|
378211
378238
|
} catch (err2) {
|
|
378212
|
-
|
|
378239
|
+
log129.warn(`Failed to create ${type} sync job for instance`, {
|
|
378213
378240
|
instanceId: instance4.id,
|
|
378214
378241
|
error: String(err2)
|
|
378215
378242
|
});
|
|
@@ -378268,7 +378295,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378268
378295
|
recordScheduledJob("dead-letter-auto-retry", "success", durationSec);
|
|
378269
378296
|
const pendingCount = await services.deadLetters.getPendingCount();
|
|
378270
378297
|
deadLettersPending.set(pendingCount);
|
|
378271
|
-
|
|
378298
|
+
log129.info("Dead letter auto-retry completed", result);
|
|
378272
378299
|
} catch (err2) {
|
|
378273
378300
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378274
378301
|
recordScheduledJob("dead-letter-auto-retry", "failure", durationSec);
|
|
@@ -378290,7 +378317,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378290
378317
|
recordScheduledJob("payload-cleanup", "success", durationSec);
|
|
378291
378318
|
const stats = await services.payloadStore.getStats();
|
|
378292
378319
|
payloadStorageSize.set(stats.totalSizeCompressed);
|
|
378293
|
-
|
|
378320
|
+
log129.info("Payload cleanup completed", { deleted });
|
|
378294
378321
|
} catch (err2) {
|
|
378295
378322
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378296
378323
|
recordScheduledJob("payload-cleanup", "failure", durationSec);
|
|
@@ -378310,7 +378337,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378310
378337
|
const deleted = await services.deadLetters.cleanupExpired();
|
|
378311
378338
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378312
378339
|
recordScheduledJob("dead-letter-cleanup", "success", durationSec);
|
|
378313
|
-
|
|
378340
|
+
log129.info("Dead letter cleanup completed", { deleted });
|
|
378314
378341
|
} catch (err2) {
|
|
378315
378342
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378316
378343
|
recordScheduledJob("dead-letter-cleanup", "failure", durationSec);
|
|
@@ -378330,7 +378357,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378330
378357
|
const jobsCreated = await createDailySyncJobs(services, "contacts");
|
|
378331
378358
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378332
378359
|
recordScheduledJob("contacts-sync-daily", "success", durationSec);
|
|
378333
|
-
|
|
378360
|
+
log129.info("Daily contacts sync jobs created", { jobsCreated });
|
|
378334
378361
|
} catch (err2) {
|
|
378335
378362
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378336
378363
|
recordScheduledJob("contacts-sync-daily", "failure", durationSec);
|
|
@@ -378350,7 +378377,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378350
378377
|
const jobsCreated = await createDailySyncJobs(services, "groups");
|
|
378351
378378
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378352
378379
|
recordScheduledJob("groups-sync-daily", "success", durationSec);
|
|
378353
|
-
|
|
378380
|
+
log129.info("Daily groups sync jobs created", { jobsCreated });
|
|
378354
378381
|
} catch (err2) {
|
|
378355
378382
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378356
378383
|
recordScheduledJob("groups-sync-daily", "failure", durationSec);
|
|
@@ -378371,7 +378398,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378371
378398
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378372
378399
|
recordScheduledJob("follow-up-sweeper", "success", durationSec);
|
|
378373
378400
|
if (stats.scanned > 0) {
|
|
378374
|
-
|
|
378401
|
+
log129.debug("Follow-up sweep tick", stats);
|
|
378375
378402
|
}
|
|
378376
378403
|
} catch (err2) {
|
|
378377
378404
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
@@ -378394,7 +378421,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378394
378421
|
const stats = await scheduledMessages2.sweep();
|
|
378395
378422
|
recordScheduledJob("scheduled-message-sweeper", "success", (Date.now() - startTime3) / 1000);
|
|
378396
378423
|
if (stats.scanned > 0) {
|
|
378397
|
-
|
|
378424
|
+
log129.debug("Scheduled-message sweep tick", { ...stats });
|
|
378398
378425
|
}
|
|
378399
378426
|
} catch (err2) {
|
|
378400
378427
|
recordScheduledJob("scheduled-message-sweeper", "failure", (Date.now() - startTime3) / 1000);
|
|
@@ -378417,7 +378444,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378417
378444
|
const instanceCount = await refreshUnreadCounts(services, channelRegistry2);
|
|
378418
378445
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378419
378446
|
recordScheduledJob("unread-count-refresh", "success", durationSec);
|
|
378420
|
-
|
|
378447
|
+
log129.debug("Refreshed unread counts", { instanceCount });
|
|
378421
378448
|
} catch (err2) {
|
|
378422
378449
|
const durationSec = (Date.now() - startTime3) / 1000;
|
|
378423
378450
|
recordScheduledJob("unread-count-refresh", "failure", durationSec);
|
|
@@ -378428,7 +378455,7 @@ function setupScheduler(services, channelRegistry2) {
|
|
|
378428
378455
|
});
|
|
378429
378456
|
updateSchedulerMetrics();
|
|
378430
378457
|
scheduler.start();
|
|
378431
|
-
|
|
378458
|
+
log129.info("Scheduler started", {
|
|
378432
378459
|
jobs: scheduler.listJobs().map((j2) => ({
|
|
378433
378460
|
name: j2.name,
|
|
378434
378461
|
cron: j2.cron,
|
|
@@ -378448,16 +378475,16 @@ function updateSchedulerMetrics() {
|
|
|
378448
378475
|
function stopScheduler() {
|
|
378449
378476
|
const scheduler = getScheduler();
|
|
378450
378477
|
scheduler.stop();
|
|
378451
|
-
|
|
378478
|
+
log129.info("Scheduler stopped");
|
|
378452
378479
|
}
|
|
378453
|
-
var
|
|
378480
|
+
var log129;
|
|
378454
378481
|
var init_scheduler2 = __esm(() => {
|
|
378455
378482
|
init_src();
|
|
378456
378483
|
init_esm5();
|
|
378457
378484
|
init_sentry_scrub();
|
|
378458
378485
|
init_scheduled_messages();
|
|
378459
378486
|
init_periodic_tenant_work();
|
|
378460
|
-
|
|
378487
|
+
log129 = createLogger("scheduler:setup");
|
|
378461
378488
|
});
|
|
378462
378489
|
|
|
378463
378490
|
// ../api/src/services/agent-heartbeat.ts
|
|
@@ -378469,11 +378496,11 @@ class AgentHeartbeatConsumer {
|
|
|
378469
378496
|
return;
|
|
378470
378497
|
const { natsConnection, turnService, db: db3 } = options;
|
|
378471
378498
|
if (natsConnection.isClosed()) {
|
|
378472
|
-
|
|
378499
|
+
log130.warn("Cannot start agent-heartbeat: NATS connection is closed");
|
|
378473
378500
|
return;
|
|
378474
378501
|
}
|
|
378475
378502
|
this.subscription = natsConnection.subscribe(HEARTBEAT_SUBJECT);
|
|
378476
|
-
|
|
378503
|
+
log130.info("Agent heartbeat consumer started", { subject: HEARTBEAT_SUBJECT });
|
|
378477
378504
|
const sub = this.subscription;
|
|
378478
378505
|
this.loop = (async () => {
|
|
378479
378506
|
for await (const msg of sub) {
|
|
@@ -378481,25 +378508,25 @@ class AgentHeartbeatConsumer {
|
|
|
378481
378508
|
const raw2 = sc3.decode(msg.data);
|
|
378482
378509
|
const parsed = parseHeartbeat(raw2);
|
|
378483
378510
|
if (!parsed) {
|
|
378484
|
-
|
|
378511
|
+
log130.warn("Discarded malformed agent heartbeat", {
|
|
378485
378512
|
subject: msg.subject,
|
|
378486
378513
|
raw: raw2.slice(0, 200)
|
|
378487
378514
|
});
|
|
378488
378515
|
continue;
|
|
378489
378516
|
}
|
|
378490
378517
|
runDetachedFromTenantScope(async () => recordHeartbeatActivity(turnService, db3, parsed)).catch((error3) => {
|
|
378491
|
-
|
|
378518
|
+
log130.warn("recordActivity failed for heartbeat (turn likely closed)", {
|
|
378492
378519
|
turnId: parsed.turnId,
|
|
378493
378520
|
error: error3 instanceof Error ? error3.message : String(error3)
|
|
378494
378521
|
});
|
|
378495
378522
|
});
|
|
378496
|
-
|
|
378523
|
+
log130.debug("Agent heartbeat applied", {
|
|
378497
378524
|
turnId: parsed.turnId,
|
|
378498
378525
|
instanceId: parsed.instanceId,
|
|
378499
378526
|
chatId: parsed.chatId
|
|
378500
378527
|
});
|
|
378501
378528
|
} catch (error3) {
|
|
378502
|
-
|
|
378529
|
+
log130.warn("Failed to process agent heartbeat", {
|
|
378503
378530
|
subject: msg.subject,
|
|
378504
378531
|
error: error3 instanceof Error ? error3.message : String(error3)
|
|
378505
378532
|
});
|
|
@@ -378516,7 +378543,7 @@ class AgentHeartbeatConsumer {
|
|
|
378516
378543
|
await this.loop;
|
|
378517
378544
|
} catch {} finally {
|
|
378518
378545
|
this.loop = null;
|
|
378519
|
-
|
|
378546
|
+
log130.info("Agent heartbeat consumer stopped");
|
|
378520
378547
|
}
|
|
378521
378548
|
}
|
|
378522
378549
|
}
|
|
@@ -378558,14 +378585,14 @@ async function closeAgentHeartbeat() {
|
|
|
378558
378585
|
await consumer.stop();
|
|
378559
378586
|
consumer = null;
|
|
378560
378587
|
}
|
|
378561
|
-
var import_nats6,
|
|
378588
|
+
var import_nats6, log130, sc3, HEARTBEAT_SUBJECT = "omni.agent.heartbeat.>", consumer = null;
|
|
378562
378589
|
var init_agent_heartbeat = __esm(() => {
|
|
378563
378590
|
init_src();
|
|
378564
378591
|
init_instance_owner_registry();
|
|
378565
378592
|
init_tenant_scope();
|
|
378566
378593
|
init_worker_tenant_context();
|
|
378567
378594
|
import_nats6 = __toESM(require_mod4(), 1);
|
|
378568
|
-
|
|
378595
|
+
log130 = createLogger("agent-heartbeat");
|
|
378569
378596
|
sc3 = import_nats6.StringCodec();
|
|
378570
378597
|
});
|
|
378571
378598
|
|
|
@@ -378580,7 +378607,7 @@ class TurnMonitor {
|
|
|
378580
378607
|
start() {
|
|
378581
378608
|
if (this.intervalId)
|
|
378582
378609
|
return;
|
|
378583
|
-
|
|
378610
|
+
log131.info("Turn monitor started", {
|
|
378584
378611
|
pollIntervalMs: POLL_INTERVAL_MS2,
|
|
378585
378612
|
nudgeMs: NUDGE_THRESHOLD_MS,
|
|
378586
378613
|
defaultStalledMs: DEFAULT_STALLED_THRESHOLD_MS,
|
|
@@ -378592,7 +378619,7 @@ class TurnMonitor {
|
|
|
378592
378619
|
if (this.intervalId) {
|
|
378593
378620
|
clearInterval(this.intervalId);
|
|
378594
378621
|
this.intervalId = null;
|
|
378595
|
-
|
|
378622
|
+
log131.info("Turn monitor stopped");
|
|
378596
378623
|
}
|
|
378597
378624
|
}
|
|
378598
378625
|
async tick() {
|
|
@@ -378616,7 +378643,7 @@ class TurnMonitor {
|
|
|
378616
378643
|
env: this.deps.env
|
|
378617
378644
|
}, (turn, tenantId) => this.processTurn(turn, tenantId));
|
|
378618
378645
|
} catch (error3) {
|
|
378619
|
-
|
|
378646
|
+
log131.error("Turn monitor tick failed", { error: String(error3) });
|
|
378620
378647
|
} finally {
|
|
378621
378648
|
this.running = false;
|
|
378622
378649
|
}
|
|
@@ -378647,13 +378674,13 @@ class TurnMonitor {
|
|
|
378647
378674
|
idleSec,
|
|
378648
378675
|
message: `Turn idle for ${idleSec}s. Are you still working?`
|
|
378649
378676
|
});
|
|
378650
|
-
|
|
378677
|
+
log131.info("Turn nudge emitted", { turnId, nudgeCount, idleSec });
|
|
378651
378678
|
}
|
|
378652
378679
|
async handleStalled(turnId, instanceId, chatId, stalledAtMs, threshold, tenantId) {
|
|
378653
378680
|
await runTenantWorkDb(this.deps.db, tenantId, () => this.deps.turnService.incrementNudge(turnId));
|
|
378654
378681
|
const payload = { turnId, instanceId, chatId, stalledAtMs, threshold };
|
|
378655
378682
|
publishTurnStalled(instanceId, chatId, payload);
|
|
378656
|
-
|
|
378683
|
+
log131.warn("Turn stalled \u2014 internal event emitted (no channel message sent)", payload);
|
|
378657
378684
|
}
|
|
378658
378685
|
async handleTimeout(turnId, instanceId, chatId, idleSec, nudgeCount, tenantId) {
|
|
378659
378686
|
const closed = await runTenantWorkDb(this.deps.db, tenantId, () => this.deps.turnService.close(turnId, {
|
|
@@ -378676,16 +378703,16 @@ class TurnMonitor {
|
|
|
378676
378703
|
nudgeCount,
|
|
378677
378704
|
messagesSent: closed.messagesSent
|
|
378678
378705
|
});
|
|
378679
|
-
|
|
378706
|
+
log131.info("Turn force-closed (timeout)", { turnId, duration, nudgeCount });
|
|
378680
378707
|
}
|
|
378681
378708
|
}
|
|
378682
|
-
var
|
|
378709
|
+
var log131, NUDGE_THRESHOLD_MS = 120000, DEFAULT_STALLED_THRESHOLD_MS = 600000, TIMEOUT_THRESHOLD_MS = 1800000, POLL_INTERVAL_MS2 = 1e4;
|
|
378683
378710
|
var init_turn_monitor = __esm(() => {
|
|
378684
378711
|
init_src();
|
|
378685
378712
|
init_periodic_tenant_work();
|
|
378686
378713
|
init_worker_tenant_context();
|
|
378687
378714
|
init_turn_events();
|
|
378688
|
-
|
|
378715
|
+
log131 = createLogger("turn-monitor");
|
|
378689
378716
|
});
|
|
378690
378717
|
|
|
378691
378718
|
// ../api/src/tenancy/enforcement-posture.ts
|
|
@@ -378765,7 +378792,7 @@ class TenantStreamRegistry {
|
|
|
378765
378792
|
try {
|
|
378766
378793
|
binding.close(reason2);
|
|
378767
378794
|
} catch (err2) {
|
|
378768
|
-
|
|
378795
|
+
log132.warn("stream termination failed", {
|
|
378769
378796
|
tenantId,
|
|
378770
378797
|
reason: reason2,
|
|
378771
378798
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
@@ -378787,7 +378814,7 @@ async function sweepRevokedStreamSubscriptions(authPlaneDb, registry5, env2 = pr
|
|
|
378787
378814
|
try {
|
|
378788
378815
|
state = await readState(authPlaneDb, tenantId);
|
|
378789
378816
|
} catch (err2) {
|
|
378790
|
-
|
|
378817
|
+
log132.warn("stream revocation read failed; terminating fail-closed", {
|
|
378791
378818
|
tenantId,
|
|
378792
378819
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
378793
378820
|
});
|
|
@@ -378812,7 +378839,7 @@ function terminateSupersededEpochs(registry5, tenantId, currentEpoch) {
|
|
|
378812
378839
|
try {
|
|
378813
378840
|
binding.close("tenant_revoked");
|
|
378814
378841
|
} catch (err2) {
|
|
378815
|
-
|
|
378842
|
+
log132.warn("stream termination failed", {
|
|
378816
378843
|
tenantId,
|
|
378817
378844
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
378818
378845
|
});
|
|
@@ -378828,17 +378855,17 @@ function startStreamRevocationSweeper(authPlaneDb, registry5, env2 = process.env
|
|
|
378828
378855
|
const timer2 = setInterval(() => {
|
|
378829
378856
|
sweepRevokedStreamSubscriptions(authPlaneDb, registry5, env2).then((stats) => {
|
|
378830
378857
|
if (stats.terminated > 0) {
|
|
378831
|
-
|
|
378858
|
+
log132.info("terminated revoked stream subscriptions", {
|
|
378832
378859
|
terminated: stats.terminated,
|
|
378833
378860
|
tenantsChecked: stats.tenantsChecked
|
|
378834
378861
|
});
|
|
378835
378862
|
}
|
|
378836
|
-
}, (err2) =>
|
|
378863
|
+
}, (err2) => log132.warn("stream revocation sweep failed", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
378837
378864
|
}, resolveStreamSweepIntervalMs());
|
|
378838
378865
|
timer2.unref?.();
|
|
378839
378866
|
return { stop: () => clearInterval(timer2) };
|
|
378840
378867
|
}
|
|
378841
|
-
var
|
|
378868
|
+
var log132, UUID7, STREAM_TERMINATION_CEILING_SECONDS = 30, readTenantRevocationState = async (authPlaneDb, tenantId) => {
|
|
378842
378869
|
const [row] = await authPlaneDb.select({ status: tenants.status, revocationEpoch: tenants.revocationEpoch }).from(tenants).where(eq(tenants.id, tenantId)).limit(1);
|
|
378843
378870
|
return row ?? null;
|
|
378844
378871
|
};
|
|
@@ -378846,7 +378873,7 @@ var init_tenant_stream_subscriptions = __esm(() => {
|
|
|
378846
378873
|
init_src();
|
|
378847
378874
|
init_src5();
|
|
378848
378875
|
init_drizzle_orm();
|
|
378849
|
-
|
|
378876
|
+
log132 = createLogger("tenant-stream-subscriptions");
|
|
378850
378877
|
UUID7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
378851
378878
|
});
|
|
378852
378879
|
|
|
@@ -378921,12 +378948,12 @@ function printStartupBanner(options) {
|
|
|
378921
378948
|
process.stdout.write(`${line3}
|
|
378922
378949
|
`);
|
|
378923
378950
|
}
|
|
378924
|
-
|
|
378951
|
+
log133.info("Server ready", { host, port, version: version3 });
|
|
378925
378952
|
}
|
|
378926
|
-
var
|
|
378953
|
+
var log133, COLORS2, BOX, ANSI_ESCAPE_PATTERN;
|
|
378927
378954
|
var init_startup_banner = __esm(() => {
|
|
378928
378955
|
init_src();
|
|
378929
|
-
|
|
378956
|
+
log133 = createLogger("api:startup");
|
|
378930
378957
|
COLORS2 = {
|
|
378931
378958
|
reset: "\x1B[0m",
|
|
378932
378959
|
dim: "\x1B[2m",
|
|
@@ -379029,7 +379056,7 @@ class VoiceStreamRegistry {
|
|
|
379029
379056
|
}
|
|
379030
379057
|
}
|
|
379031
379058
|
});
|
|
379032
|
-
|
|
379059
|
+
log134.info("Voice WS client connected", {
|
|
379033
379060
|
sessionId: client.params.sessionId,
|
|
379034
379061
|
format: client.params.format,
|
|
379035
379062
|
filterUser: client.params.filterUserId ?? "all"
|
|
@@ -379118,12 +379145,12 @@ async function authorizeVoiceApiKey(validate, apiKey) {
|
|
|
379118
379145
|
return false;
|
|
379119
379146
|
}
|
|
379120
379147
|
}
|
|
379121
|
-
var
|
|
379148
|
+
var log134, opusCodec = null;
|
|
379122
379149
|
var init_voice3 = __esm(() => {
|
|
379123
379150
|
init_src();
|
|
379124
379151
|
init_src3();
|
|
379125
379152
|
init_tenant_stream_subscriptions();
|
|
379126
|
-
|
|
379153
|
+
log134 = createLogger("ws:voice");
|
|
379127
379154
|
});
|
|
379128
379155
|
|
|
379129
379156
|
// ../api/src/ws/voice-upgrade-authorization.ts
|
|
@@ -379449,65 +379476,65 @@ function setupShutdownHandlers(server, earlyShutdown) {
|
|
|
379449
379476
|
}
|
|
379450
379477
|
async function setupEventBusServices(eventBus, services, db3) {
|
|
379451
379478
|
if (!eventBus) {
|
|
379452
|
-
|
|
379479
|
+
log135.warn("Skipping event bus services (no event bus)");
|
|
379453
379480
|
return;
|
|
379454
379481
|
}
|
|
379455
379482
|
try {
|
|
379456
379483
|
await setupMessagePersistence(eventBus, services);
|
|
379457
379484
|
} catch (error3) {
|
|
379458
|
-
|
|
379485
|
+
log135.error("Failed to set up message persistence", { error: String(error3) });
|
|
379459
379486
|
}
|
|
379460
379487
|
try {
|
|
379461
379488
|
await setupMediaProcessor(eventBus, db3, services);
|
|
379462
379489
|
} catch (error3) {
|
|
379463
|
-
|
|
379490
|
+
log135.error("Failed to set up media processor", { error: String(error3) });
|
|
379464
379491
|
}
|
|
379465
379492
|
try {
|
|
379466
379493
|
globalDispatcherCleanup = await setupAgentResponder(eventBus, services, db3);
|
|
379467
379494
|
} catch (error3) {
|
|
379468
|
-
|
|
379495
|
+
log135.error("Failed to set up agent dispatcher", { error: String(error3) });
|
|
379469
379496
|
}
|
|
379470
379497
|
try {
|
|
379471
379498
|
await services.automations.startEngine(buildAutomationEngineDeps(services, db3));
|
|
379472
379499
|
} catch (error3) {
|
|
379473
|
-
|
|
379500
|
+
log135.error("Failed to start automation engine", { error: String(error3) });
|
|
379474
379501
|
}
|
|
379475
379502
|
try {
|
|
379476
379503
|
await setupSessionCleaner(eventBus, services, db3);
|
|
379477
379504
|
} catch (error3) {
|
|
379478
|
-
|
|
379505
|
+
log135.error("Failed to set up session cleaner", { error: String(error3) });
|
|
379479
379506
|
}
|
|
379480
379507
|
try {
|
|
379481
379508
|
await setupFollowUpHooks(eventBus, services, db3);
|
|
379482
379509
|
} catch (error3) {
|
|
379483
|
-
|
|
379510
|
+
log135.error("Failed to set up follow-up hooks", { error: String(error3) });
|
|
379484
379511
|
}
|
|
379485
379512
|
if (globalChannelRegistry) {
|
|
379486
379513
|
try {
|
|
379487
379514
|
await setupSyncWorker(eventBus, services, globalChannelRegistry, db3);
|
|
379488
379515
|
} catch (error3) {
|
|
379489
|
-
|
|
379516
|
+
log135.error("Failed to set up sync worker", { error: String(error3) });
|
|
379490
379517
|
}
|
|
379491
379518
|
}
|
|
379492
379519
|
try {
|
|
379493
379520
|
await setupHistoryPushTracker(eventBus, services);
|
|
379494
379521
|
} catch (error3) {
|
|
379495
|
-
|
|
379522
|
+
log135.error("Failed to set up history-push tracker", { error: String(error3) });
|
|
379496
379523
|
}
|
|
379497
379524
|
try {
|
|
379498
379525
|
await initTurnEvents(NATS_URL);
|
|
379499
379526
|
} catch (error3) {
|
|
379500
|
-
|
|
379527
|
+
log135.error("Failed to initialize turn events", { error: String(error3) });
|
|
379501
379528
|
}
|
|
379502
379529
|
try {
|
|
379503
379530
|
const turnEventsConn = getTurnEventsConnection();
|
|
379504
379531
|
if (turnEventsConn) {
|
|
379505
379532
|
initAgentHeartbeat({ natsConnection: turnEventsConn, turnService: services.turns, db: services.db });
|
|
379506
379533
|
} else {
|
|
379507
|
-
|
|
379534
|
+
log135.warn("Skipping agent heartbeat consumer: no NATS connection");
|
|
379508
379535
|
}
|
|
379509
379536
|
} catch (error3) {
|
|
379510
|
-
|
|
379537
|
+
log135.error("Failed to initialize agent heartbeat consumer", { error: String(error3) });
|
|
379511
379538
|
}
|
|
379512
379539
|
try {
|
|
379513
379540
|
globalTurnMonitor = new TurnMonitor({
|
|
@@ -379517,23 +379544,23 @@ async function setupEventBusServices(eventBus, services, db3) {
|
|
|
379517
379544
|
authPlaneDb: services.authPlane.db
|
|
379518
379545
|
});
|
|
379519
379546
|
globalTurnMonitor.start();
|
|
379520
|
-
|
|
379547
|
+
log135.info("Turn monitor started");
|
|
379521
379548
|
} catch (error3) {
|
|
379522
|
-
|
|
379549
|
+
log135.error("Failed to start turn monitor", { error: String(error3) });
|
|
379523
379550
|
}
|
|
379524
379551
|
}
|
|
379525
379552
|
async function waitForDatabaseReady(db3, maxAttempts = 30) {
|
|
379526
|
-
|
|
379553
|
+
log135.info("Waiting for database readiness");
|
|
379527
379554
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
379528
379555
|
try {
|
|
379529
379556
|
await db3.execute(sql`SELECT 1`);
|
|
379530
|
-
|
|
379557
|
+
log135.info("Database ready", { attempt });
|
|
379531
379558
|
return;
|
|
379532
379559
|
} catch {
|
|
379533
379560
|
if (attempt === maxAttempts) {
|
|
379534
379561
|
throw new Error(`Database not ready after ${maxAttempts} attempts`);
|
|
379535
379562
|
}
|
|
379536
|
-
|
|
379563
|
+
log135.warn("Database not ready, retrying...", { attempt });
|
|
379537
379564
|
await new Promise((resolve4) => setTimeout(resolve4, 1000));
|
|
379538
379565
|
}
|
|
379539
379566
|
}
|
|
@@ -379551,7 +379578,7 @@ async function runStartupMigrations(db3, enforced) {
|
|
|
379551
379578
|
return;
|
|
379552
379579
|
});
|
|
379553
379580
|
if (enforced && scrubDdlCredential()) {
|
|
379554
|
-
|
|
379581
|
+
log135.info("DDL credential scrubbed from process environment");
|
|
379555
379582
|
}
|
|
379556
379583
|
}
|
|
379557
379584
|
}
|
|
@@ -379560,39 +379587,39 @@ async function verifyEnforcedRuntimeIdentity(db3, mode) {
|
|
|
379560
379587
|
return;
|
|
379561
379588
|
try {
|
|
379562
379589
|
const identity = await assertEnforcedRuntimeIdentity(db3);
|
|
379563
|
-
|
|
379590
|
+
log135.info("Enforced runtime identity verified", {
|
|
379564
379591
|
currentUser: identity.currentUser,
|
|
379565
379592
|
forcedTables: identity.enforcement.forced.length
|
|
379566
379593
|
});
|
|
379567
379594
|
} catch (error3) {
|
|
379568
|
-
|
|
379595
|
+
log135.error("Enforcement-mode startup refused", { error: String(error3) });
|
|
379569
379596
|
await closeDb();
|
|
379570
379597
|
throw error3;
|
|
379571
379598
|
}
|
|
379572
379599
|
}
|
|
379573
379600
|
async function main() {
|
|
379574
|
-
|
|
379601
|
+
log135.info("Starting Omni API v2");
|
|
379575
379602
|
enableDefaultMetrics();
|
|
379576
379603
|
if (process.env.PGSERVE_EMBEDDED === "true") {
|
|
379577
|
-
|
|
379604
|
+
log135.warn("PGSERVE_EMBEDDED=true is set but embedded mode was removed in pgserve-singleton-no-proxy. Run `omni doctor --fix` (or `pgserve install` directly) to migrate to consumer-only pgserve. omni-api will continue using DATABASE_URL.");
|
|
379578
379605
|
}
|
|
379579
379606
|
const enforcementMode = resolveEnforcementMode();
|
|
379580
|
-
warnOnMixedTenancyState(enforcementMode, (message2) =>
|
|
379607
|
+
warnOnMixedTenancyState(enforcementMode, (message2) => log135.warn(message2));
|
|
379581
379608
|
const enforcedIdentities = enforcementMode === "enforced" ? resolveEnforcedBootIdentities() : null;
|
|
379582
379609
|
const databaseUrl = enforcedIdentities ? enforcedIdentities.runtimeUrl : getDefaultDatabaseUrl();
|
|
379583
379610
|
if (enforcementMode === "enforced") {
|
|
379584
|
-
|
|
379611
|
+
log135.info("Connecting to database", { enforcementMode });
|
|
379585
379612
|
} else {
|
|
379586
|
-
|
|
379613
|
+
log135.info("Connecting to database");
|
|
379587
379614
|
}
|
|
379588
379615
|
const db3 = createDb({ url: databaseUrl });
|
|
379589
379616
|
globalDbRef = db3;
|
|
379590
379617
|
const earlyShutdown = async () => {
|
|
379591
|
-
|
|
379618
|
+
log135.info("Shutdown during startup \u2014 cleaning up");
|
|
379592
379619
|
try {
|
|
379593
379620
|
await closeDb();
|
|
379594
379621
|
} catch (err2) {
|
|
379595
|
-
|
|
379622
|
+
log135.error("Cleanup failed during early shutdown", { error: String(err2) });
|
|
379596
379623
|
} finally {
|
|
379597
379624
|
process.exit(1);
|
|
379598
379625
|
}
|
|
@@ -379605,7 +379632,7 @@ async function main() {
|
|
|
379605
379632
|
await closeDb();
|
|
379606
379633
|
throw error3;
|
|
379607
379634
|
}
|
|
379608
|
-
|
|
379635
|
+
log135.info("Running database migrations");
|
|
379609
379636
|
const migrationStart = Date.now();
|
|
379610
379637
|
try {
|
|
379611
379638
|
await runStartupMigrations(db3, enforcedIdentities);
|
|
@@ -379613,26 +379640,26 @@ async function main() {
|
|
|
379613
379640
|
await closeDb();
|
|
379614
379641
|
throw error3;
|
|
379615
379642
|
}
|
|
379616
|
-
|
|
379643
|
+
log135.info("Database migrations complete", { durationMs: Date.now() - migrationStart });
|
|
379617
379644
|
await verifyEnforcedRuntimeIdentity(db3, enforcementMode);
|
|
379618
379645
|
try {
|
|
379619
379646
|
const driftReport = await verifyCriticalColumns(db3, API_CRITICAL_COLUMNS);
|
|
379620
379647
|
if (!driftReport.ok) {
|
|
379621
|
-
|
|
379648
|
+
log135.error(formatDriftReport(driftReport), { drift: driftReport.drift });
|
|
379622
379649
|
await closeDb();
|
|
379623
379650
|
process.exit(1);
|
|
379624
379651
|
}
|
|
379625
379652
|
} catch (error3) {
|
|
379626
|
-
|
|
379653
|
+
log135.error("Schema drift check failed", { error: String(error3) });
|
|
379627
379654
|
await closeDb();
|
|
379628
379655
|
process.exit(1);
|
|
379629
379656
|
}
|
|
379630
379657
|
try {
|
|
379631
379658
|
const [countRow] = await db3.select({ count: sql`count(*)::int` }).from(instances);
|
|
379632
379659
|
const rowCount = countRow?.count ?? 0;
|
|
379633
|
-
|
|
379660
|
+
log135.info("Post-migration content snapshot", { DB_ROW_COUNT_INSTANCES: rowCount });
|
|
379634
379661
|
} catch (error3) {
|
|
379635
|
-
|
|
379662
|
+
log135.warn("Failed to read instances row count (non-fatal)", { error: String(error3) });
|
|
379636
379663
|
}
|
|
379637
379664
|
const eventBus = await connectToNats(db3);
|
|
379638
379665
|
if (eventBus) {
|
|
@@ -379653,9 +379680,9 @@ async function main() {
|
|
|
379653
379680
|
try {
|
|
379654
379681
|
await services.settings.seedDefaults();
|
|
379655
379682
|
} catch (error3) {
|
|
379656
|
-
|
|
379683
|
+
log135.error("Failed to seed default settings", { error: String(error3) });
|
|
379657
379684
|
}
|
|
379658
|
-
|
|
379685
|
+
log135.info("Initializing API key");
|
|
379659
379686
|
let apiKeyInfo;
|
|
379660
379687
|
try {
|
|
379661
379688
|
const keyResult = await services.apiKeys.initializePrimaryKey();
|
|
@@ -379665,17 +379692,17 @@ async function main() {
|
|
|
379665
379692
|
isFromEnv: keyResult.isFromEnv
|
|
379666
379693
|
};
|
|
379667
379694
|
if (keyResult.isNew) {
|
|
379668
|
-
|
|
379695
|
+
log135.info("Generated new primary API key");
|
|
379669
379696
|
} else if (keyResult.isFromEnv) {
|
|
379670
|
-
|
|
379697
|
+
log135.info("Using primary API key from environment");
|
|
379671
379698
|
} else {
|
|
379672
|
-
|
|
379699
|
+
log135.info("Using existing primary API key");
|
|
379673
379700
|
}
|
|
379674
379701
|
} catch (error3) {
|
|
379675
|
-
|
|
379702
|
+
log135.error("Failed to initialize primary API key", { error: String(error3) });
|
|
379676
379703
|
}
|
|
379677
379704
|
await setupEventBusServices(eventBus, services, db3);
|
|
379678
|
-
|
|
379705
|
+
log135.info("Starting scheduler");
|
|
379679
379706
|
setupScheduler(services, globalChannelRegistry);
|
|
379680
379707
|
const server = startBunServer(app);
|
|
379681
379708
|
printStartupBanner({
|
|
@@ -379689,7 +379716,7 @@ async function main() {
|
|
|
379689
379716
|
});
|
|
379690
379717
|
setupShutdownHandlers(server, earlyShutdown);
|
|
379691
379718
|
}
|
|
379692
|
-
var import__package3,
|
|
379719
|
+
var import__package3, log135, natsLog, pluginLog, shutdownLog, PORT, HOST, NATS_URL, voiceStreamRegistry, globalEventBus = null, globalChannelRegistry = null, globalInstanceMonitor = null, globalDispatcherCleanup = null, globalTurnMonitor = null, globalDbRef = null, globalServicesRef = null, globalStreamSweeper = null;
|
|
379693
379720
|
var init_src9 = __esm(() => {
|
|
379694
379721
|
init_instrument2();
|
|
379695
379722
|
init_tracing5();
|
|
@@ -379722,7 +379749,7 @@ var init_src9 = __esm(() => {
|
|
|
379722
379749
|
level: process.env.LOG_LEVEL ?? "info",
|
|
379723
379750
|
format: process.env.LOG_FORMAT ?? "auto"
|
|
379724
379751
|
});
|
|
379725
|
-
|
|
379752
|
+
log135 = createLogger("api:startup");
|
|
379726
379753
|
natsLog = createLogger("api:nats");
|
|
379727
379754
|
pluginLog = createLogger("api:plugins");
|
|
379728
379755
|
shutdownLog = createLogger("api:shutdown");
|
|
@@ -379731,7 +379758,7 @@ var init_src9 = __esm(() => {
|
|
|
379731
379758
|
NATS_URL = process.env.NATS_URL ?? "nats://localhost:4222";
|
|
379732
379759
|
voiceStreamRegistry = new VoiceStreamRegistry;
|
|
379733
379760
|
main().catch((error3) => {
|
|
379734
|
-
|
|
379761
|
+
log135.error("Failed to start API server", { error: String(error3) });
|
|
379735
379762
|
process.exit(1);
|
|
379736
379763
|
});
|
|
379737
379764
|
});
|