@automagik/omni 2.260901.2 → 2.260902.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/webhooks.d.ts +29 -0
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/index.js +92 -16
- package/dist/sdk/client.d.ts +81 -12
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/types.generated.d.ts +215 -3
- package/dist/sdk/types.generated.d.ts.map +1 -1
- package/dist/server/index.js +273 -115
- 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.
|
|
242904
|
+
version: "2.260902.1",
|
|
242905
242905
|
type: "module",
|
|
242906
242906
|
exports: {
|
|
242907
242907
|
".": {
|
|
@@ -345619,6 +345619,10 @@ async function consumeStream(generator, sender, instanceId, chatId, traceId) {
|
|
|
345619
345619
|
function extractThreadId(messages4) {
|
|
345620
345620
|
return (messages4[0]?.payload.rawPayload ?? {}).threadId;
|
|
345621
345621
|
}
|
|
345622
|
+
function extractCancelThreadId(messages4) {
|
|
345623
|
+
const parsed = CancelThreadPayloadSchema.safeParse(messages4[0]?.payload.rawPayload ?? {});
|
|
345624
|
+
return (parsed.success ? parsed.data.cancelThreadId : undefined) ?? extractThreadId(messages4);
|
|
345625
|
+
}
|
|
345622
345626
|
function extractKhalSessionId(messages4) {
|
|
345623
345627
|
for (const message2 of messages4) {
|
|
345624
345628
|
const rawPayload = message2.payload.rawPayload ?? {};
|
|
@@ -345759,8 +345763,9 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
|
|
|
345759
345763
|
const streamKey = `${instance4.id}:${chatId}`;
|
|
345760
345764
|
activeStreams.set(streamKey, sender);
|
|
345761
345765
|
const cancelController = new AbortController;
|
|
345762
|
-
const runKey = runAbortKey(instance4.id, chatId,
|
|
345763
|
-
|
|
345766
|
+
const runKey = runAbortKey(instance4.id, chatId, extractCancelThreadId(messages4));
|
|
345767
|
+
const runEntry = { controller: cancelController, startedAt: Date.now(), sender };
|
|
345768
|
+
activeRunAborts.set(runKey, runEntry);
|
|
345764
345769
|
trigger.abortSignal = cancelController.signal;
|
|
345765
345770
|
const streamDispatchStart = Date.now();
|
|
345766
345771
|
try {
|
|
@@ -345794,7 +345799,8 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
|
|
|
345794
345799
|
return false;
|
|
345795
345800
|
} finally {
|
|
345796
345801
|
activeStreams.delete(streamKey);
|
|
345797
|
-
activeRunAborts.
|
|
345802
|
+
if (activeRunAborts.get(runKey) === runEntry)
|
|
345803
|
+
activeRunAborts.delete(runKey);
|
|
345798
345804
|
}
|
|
345799
345805
|
}
|
|
345800
345806
|
function formatMediaContent(msg) {
|
|
@@ -346004,10 +346010,11 @@ function resolveReplySuppression(flags) {
|
|
|
346004
346010
|
return "run_cancelled_by_user";
|
|
346005
346011
|
return null;
|
|
346006
346012
|
}
|
|
346007
|
-
async function triggerProviderWithCancellation(provider, trigger, spanAttributes, instanceId, chatId, traceId) {
|
|
346013
|
+
async function triggerProviderWithCancellation(provider, trigger, spanAttributes, instanceId, chatId, traceId, cancelThreadId = trigger.source.threadId) {
|
|
346008
346014
|
const cancelController = new AbortController;
|
|
346009
|
-
const runKey = runAbortKey(instanceId, chatId,
|
|
346010
|
-
|
|
346015
|
+
const runKey = runAbortKey(instanceId, chatId, cancelThreadId);
|
|
346016
|
+
const runEntry = { controller: cancelController, startedAt: Date.now() };
|
|
346017
|
+
activeRunAborts.set(runKey, runEntry);
|
|
346011
346018
|
try {
|
|
346012
346019
|
const result = await withLifecycleSpan("omni.dispatch_to_agno", spanAttributes, () => provider.trigger({
|
|
346013
346020
|
...trigger,
|
|
@@ -346022,7 +346029,8 @@ async function triggerProviderWithCancellation(provider, trigger, spanAttributes
|
|
|
346022
346029
|
}
|
|
346023
346030
|
throw err2;
|
|
346024
346031
|
} finally {
|
|
346025
|
-
activeRunAborts.
|
|
346032
|
+
if (activeRunAborts.get(runKey) === runEntry)
|
|
346033
|
+
activeRunAborts.delete(runKey);
|
|
346026
346034
|
}
|
|
346027
346035
|
}
|
|
346028
346036
|
async function dispatchViaProvider(services, instance4, messages4, triggerType, channel5, chatId, senderId, personId, senderName, traceId, rawEvent, db2, extraContextMessages, senderAgentId) {
|
|
@@ -346098,7 +346106,7 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
|
|
|
346098
346106
|
...lifecycleBase,
|
|
346099
346107
|
stage: "dispatch_to_agno",
|
|
346100
346108
|
extra: { trigger_type: triggerType, provider_id: provider.id, provider_schema: provider.schema }
|
|
346101
|
-
}), instance4.id, chatId, traceId);
|
|
346109
|
+
}), instance4.id, chatId, traceId, extractCancelThreadId(messages4));
|
|
346102
346110
|
if (!triggerOutcome)
|
|
346103
346111
|
return true;
|
|
346104
346112
|
const { result, cancelled: runCancelled } = triggerOutcome;
|
|
@@ -346488,6 +346496,7 @@ function takeQueuedAck(chatKey) {
|
|
|
346488
346496
|
}
|
|
346489
346497
|
async function ackQueuedMessage(info2) {
|
|
346490
346498
|
const chatKey = `${info2.instanceId}:${info2.chatId}`;
|
|
346499
|
+
let entry;
|
|
346491
346500
|
try {
|
|
346492
346501
|
const existing = queuedMessageAcks.get(chatKey);
|
|
346493
346502
|
if (existing && Date.now() - existing.at < QUEUED_ACK_TIMEOUT_MS)
|
|
@@ -346496,16 +346505,22 @@ async function ackQueuedMessage(info2) {
|
|
|
346496
346505
|
const messageId = info2.message.payload.externalId;
|
|
346497
346506
|
if (!instance4 || !messageId)
|
|
346498
346507
|
return;
|
|
346499
|
-
|
|
346508
|
+
entry = { at: Date.now() };
|
|
346500
346509
|
queuedMessageAcks.set(chatKey, entry);
|
|
346501
346510
|
const channel5 = info2.message.metadata.channelType ?? instance4.channel;
|
|
346502
346511
|
const plugin10 = await getPlugin(channel5) ?? null;
|
|
346503
|
-
|
|
346512
|
+
const handle = startAck(plugin10, createPluginAckProvider(plugin10), instance4.id, info2.chatId, messageId, channel5, {
|
|
346504
346513
|
...buildAckConfig(instance4),
|
|
346505
346514
|
ackTimeoutMs: QUEUED_ACK_TIMEOUT_MS
|
|
346506
346515
|
});
|
|
346516
|
+
if (queuedMessageAcks.get(chatKey) !== entry) {
|
|
346517
|
+
handle.release();
|
|
346518
|
+
return;
|
|
346519
|
+
}
|
|
346520
|
+
entry.handle = handle;
|
|
346507
346521
|
} catch (error3) {
|
|
346508
|
-
queuedMessageAcks.
|
|
346522
|
+
if (entry && queuedMessageAcks.get(chatKey) === entry)
|
|
346523
|
+
queuedMessageAcks.delete(chatKey);
|
|
346509
346524
|
log91.debug("Failed to ack queued message", { chatId: info2.chatId, error: String(error3) });
|
|
346510
346525
|
}
|
|
346511
346526
|
}
|
|
@@ -347876,7 +347891,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
|
|
|
347876
347891
|
log91.info("Agent dispatcher shutdown complete");
|
|
347877
347892
|
};
|
|
347878
347893
|
}
|
|
347879
|
-
var import_api32, log91, agentDispatchLimiter, _natsGenieProviderCtor, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, LIFECYCLE_PREVIEW_MAX_CHARS = 160, LIFECYCLE_SENSITIVE_KEY_PARTS, PRESENCE_DEFAULT_MIN_MS = 5000, PRESENCE_DEFAULT_MAX_WAIT_MS = 30000, activeMessageDebouncer = null, DEFAULT_DISPATCH_ERROR_MESSAGE = "Opa, tive um probleminha aqui \uD83D\uDE05 Pode mandar de novo?", DEFAULT_ERROR_HANDOFF_MESSAGE = "T\xF4 com um probleminha t\xE9cnico aqui agora. Logo algu\xE9m do time vai entrar em contato com voc\xEA.", TRANSIENT_DISPATCH_ERROR_PATTERNS, TRANSIENT_DISPATCH_RETRY_DELAYS_MS, CHANNEL_MESSAGE_LIMITS, DEFAULT_MESSAGE_LIMIT = 4000, MEDIA_BASE_PATH3, MEDIA_ICONS, MEDIA_WAIT_NULL, mediaCompletions, mediaResultCache, MEDIA_WAIT_TIMEOUT_MS = 30000, DEFAULT_SEND_MEDIA_PATH_TYPES, BOT_PREFIX = "\uD83E\uDD16 ", activeStreams, activeRunAborts, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", queuedMessageAcks, QUEUED_ACK_TIMEOUT_MS = 120000, providerCache, openclawClientPool, _openClawClientCtor, nullFilterWarnedInstances, ACTIVE_OWNER_IDENTIFIER_CACHE_TTL_MS = 1e4, cachedActiveOwnerIdentifiers = null, cachedActiveOwnerIdentifiersAt = 0, tenantCachedActiveOwnerIdentifiers, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
|
|
347894
|
+
var import_api32, log91, agentDispatchLimiter, _natsGenieProviderCtor, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, LIFECYCLE_PREVIEW_MAX_CHARS = 160, LIFECYCLE_SENSITIVE_KEY_PARTS, PRESENCE_DEFAULT_MIN_MS = 5000, PRESENCE_DEFAULT_MAX_WAIT_MS = 30000, activeMessageDebouncer = null, DEFAULT_DISPATCH_ERROR_MESSAGE = "Opa, tive um probleminha aqui \uD83D\uDE05 Pode mandar de novo?", DEFAULT_ERROR_HANDOFF_MESSAGE = "T\xF4 com um probleminha t\xE9cnico aqui agora. Logo algu\xE9m do time vai entrar em contato com voc\xEA.", TRANSIENT_DISPATCH_ERROR_PATTERNS, TRANSIENT_DISPATCH_RETRY_DELAYS_MS, CHANNEL_MESSAGE_LIMITS, DEFAULT_MESSAGE_LIMIT = 4000, MEDIA_BASE_PATH3, MEDIA_ICONS, MEDIA_WAIT_NULL, mediaCompletions, mediaResultCache, MEDIA_WAIT_TIMEOUT_MS = 30000, DEFAULT_SEND_MEDIA_PATH_TYPES, BOT_PREFIX = "\uD83E\uDD16 ", activeStreams, activeRunAborts, CancelThreadPayloadSchema, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", queuedMessageAcks, QUEUED_ACK_TIMEOUT_MS = 120000, providerCache, openclawClientPool, _openClawClientCtor, nullFilterWarnedInstances, ACTIVE_OWNER_IDENTIFIER_CACHE_TTL_MS = 1e4, cachedActiveOwnerIdentifiers = null, cachedActiveOwnerIdentifiersAt = 0, tenantCachedActiveOwnerIdentifiers, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
|
|
347880
347895
|
var init_agent_dispatcher = __esm(() => {
|
|
347881
347896
|
init_src2();
|
|
347882
347897
|
init_src();
|
|
@@ -347884,6 +347899,7 @@ var init_agent_dispatcher = __esm(() => {
|
|
|
347884
347899
|
init_src8();
|
|
347885
347900
|
init_esm5();
|
|
347886
347901
|
init_drizzle_orm();
|
|
347902
|
+
init_zod();
|
|
347887
347903
|
init_idempotency();
|
|
347888
347904
|
init_sentry_scrub();
|
|
347889
347905
|
init_agent_runner();
|
|
@@ -347934,6 +347950,7 @@ var init_agent_dispatcher = __esm(() => {
|
|
|
347934
347950
|
DEFAULT_SEND_MEDIA_PATH_TYPES = ["image", "video", "document"];
|
|
347935
347951
|
activeStreams = new Map;
|
|
347936
347952
|
activeRunAborts = new Map;
|
|
347953
|
+
CancelThreadPayloadSchema = exports_external.object({ cancelThreadId: exports_external.string().min(1).optional() });
|
|
347937
347954
|
sessionActivityStore = new InMemorySessionActivityStore;
|
|
347938
347955
|
PROC_REACT_START = { audio: "\uD83C\uDFA7", image: "\uD83D\uDC40", video: "\uD83D\uDC40", document: "\uD83D\uDC40" };
|
|
347939
347956
|
queuedMessageAcks = new Map;
|
|
@@ -352912,9 +352929,23 @@ function openProviderSecrets(tenantId, row) {
|
|
|
352912
352929
|
|
|
352913
352930
|
class ProviderService {
|
|
352914
352931
|
db;
|
|
352932
|
+
clientCacheInvalidators = [];
|
|
352915
352933
|
constructor(db2) {
|
|
352916
352934
|
this.db = db2;
|
|
352917
352935
|
}
|
|
352936
|
+
onProviderChanged(invalidate) {
|
|
352937
|
+
this.clientCacheInvalidators.push(invalidate);
|
|
352938
|
+
}
|
|
352939
|
+
invalidateCaches(providerId) {
|
|
352940
|
+
runAfterTenantCommit(() => {
|
|
352941
|
+
invalidateProviderCache(providerId);
|
|
352942
|
+
for (const invalidate of this.clientCacheInvalidators) {
|
|
352943
|
+
try {
|
|
352944
|
+
invalidate(providerId);
|
|
352945
|
+
} catch {}
|
|
352946
|
+
}
|
|
352947
|
+
});
|
|
352948
|
+
}
|
|
352918
352949
|
get tenantId() {
|
|
352919
352950
|
return currentTenantScope()?.tenantId ?? null;
|
|
352920
352951
|
}
|
|
@@ -352955,7 +352986,7 @@ class ProviderService {
|
|
|
352955
352986
|
if (!updated) {
|
|
352956
352987
|
throw new NotFoundError("AgentProvider", id);
|
|
352957
352988
|
}
|
|
352958
|
-
|
|
352989
|
+
this.invalidateCaches(id);
|
|
352959
352990
|
return openProviderSecrets(tenantId, updated);
|
|
352960
352991
|
}
|
|
352961
352992
|
async delete(id) {
|
|
@@ -352963,7 +352994,7 @@ class ProviderService {
|
|
|
352963
352994
|
if (!result.length) {
|
|
352964
352995
|
throw new NotFoundError("AgentProvider", id);
|
|
352965
352996
|
}
|
|
352966
|
-
|
|
352997
|
+
this.invalidateCaches(id);
|
|
352967
352998
|
}
|
|
352968
352999
|
async checkHealth(id) {
|
|
352969
353000
|
const provider = await this.getById(id);
|
|
@@ -355406,6 +355437,9 @@ function createServices(db2, eventBus) {
|
|
|
355406
355437
|
batchJobs2.setAuthPlane(authPlane.db);
|
|
355407
355438
|
const mediaStorage = new MediaStorageService(db2);
|
|
355408
355439
|
mediaStorage.setTenantAdmissibilityCheck((tenantId) => isTenantWorkAdmissible(authPlane.db, tenantId));
|
|
355440
|
+
const providers2 = new ProviderService(db2);
|
|
355441
|
+
const agentRunner = new AgentRunnerService(db2);
|
|
355442
|
+
providers2.onProviderChanged((providerId) => agentRunner.clearCache(providerId));
|
|
355409
355443
|
return {
|
|
355410
355444
|
agents: new AgentService(db2, eventBus),
|
|
355411
355445
|
agentState: new AgentStateService(eventBus),
|
|
@@ -355418,7 +355452,7 @@ function createServices(db2, eventBus) {
|
|
|
355418
355452
|
events: new EventService(db2),
|
|
355419
355453
|
settings,
|
|
355420
355454
|
access: new AccessService(db2, eventBus, accessCache),
|
|
355421
|
-
providers:
|
|
355455
|
+
providers: providers2,
|
|
355422
355456
|
routes: new RouteService(db2, routeResolver),
|
|
355423
355457
|
routeResolver,
|
|
355424
355458
|
deadLetters,
|
|
@@ -355430,7 +355464,7 @@ function createServices(db2, eventBus) {
|
|
|
355430
355464
|
messages: new MessageService(db2, eventBus),
|
|
355431
355465
|
syncJobs: new SyncJobService(db2, eventBus),
|
|
355432
355466
|
batchJobs: batchJobs2,
|
|
355433
|
-
agentRunner
|
|
355467
|
+
agentRunner,
|
|
355434
355468
|
tts,
|
|
355435
355469
|
turns: new TurnService(db2),
|
|
355436
355470
|
consumerOffsets: new ConsumerOffsetService(db2),
|
|
@@ -355833,6 +355867,13 @@ var init_error3 = __esm(() => {
|
|
|
355833
355867
|
});
|
|
355834
355868
|
|
|
355835
355869
|
// ../api/src/middleware/rate-limit.ts
|
|
355870
|
+
function resolveClientIp(trustedProxyHeaderValue, remoteAddr) {
|
|
355871
|
+
const raw2 = trustedProxyHeaderValue ?? remoteAddr;
|
|
355872
|
+
if (!raw2)
|
|
355873
|
+
return;
|
|
355874
|
+
const hops = raw2.split(",").map((hop) => hop.trim()).filter(Boolean);
|
|
355875
|
+
return hops.at(-1);
|
|
355876
|
+
}
|
|
355836
355877
|
function createRateLimiter2(config4 = RATE_LIMITS.general, keyPrefix = "ratelimit") {
|
|
355837
355878
|
return createMiddleware(async (c, next) => {
|
|
355838
355879
|
const apiKey = c.get("apiKey");
|
|
@@ -355840,8 +355881,7 @@ function createRateLimiter2(config4 = RATE_LIMITS.general, keyPrefix = "ratelimi
|
|
|
355840
355881
|
const trustedProxyIp = trustedProxyHeader ? c.req.header(trustedProxyHeader) : undefined;
|
|
355841
355882
|
const server = c.env;
|
|
355842
355883
|
const remoteAddr = server?.remoteAddr ?? server?.requestIP?.(c.req.raw)?.address;
|
|
355843
|
-
const
|
|
355844
|
-
const normalizedIp = rawIp?.split(",")[0]?.trim() || undefined;
|
|
355884
|
+
const normalizedIp = resolveClientIp(trustedProxyIp, remoteAddr);
|
|
355845
355885
|
const identifier = apiKey?.id ? `api:${apiKey.id}` : normalizedIp ? `ip:${normalizedIp}` : "anon";
|
|
355846
355886
|
const key = `${keyPrefix}:${identifier}`;
|
|
355847
355887
|
const now = Date.now();
|
|
@@ -360507,7 +360547,10 @@ var init_messages4 = __esm(() => {
|
|
|
360507
360547
|
instanceId: exports_external.string().uuid().openapi({ description: "Instance UUID" }),
|
|
360508
360548
|
to: exports_external.string().openapi({ description: "Recipient" }),
|
|
360509
360549
|
audioSizeKb: exports_external.number().openapi({ description: "Audio size in KB" }),
|
|
360510
|
-
durationMs: exports_external.number().openapi({ description: "Audio duration in ms" })
|
|
360550
|
+
durationMs: exports_external.number().openapi({ description: "Audio duration in ms" }),
|
|
360551
|
+
senderAgentId: exports_external.string().uuid().nullable().optional().openapi({
|
|
360552
|
+
description: "Present when the request set sentBy: 'agent' \u2014 the agent the send was attributed to, or null when the instance has no configured agent (attribution did not happen)"
|
|
360553
|
+
})
|
|
360511
360554
|
});
|
|
360512
360555
|
});
|
|
360513
360556
|
|
|
@@ -361627,6 +361670,7 @@ var init_voice = __esm(() => {
|
|
|
361627
361670
|
|
|
361628
361671
|
// ../api/src/schemas/openapi/webhooks.ts
|
|
361629
361672
|
function registerWebhookSchemas(registry4) {
|
|
361673
|
+
registry4.register("WebhookSignatureConfig", WebhookSignatureConfigSchema);
|
|
361630
361674
|
registry4.register("WebhookSource", WebhookSourceSchema);
|
|
361631
361675
|
registry4.register("CreateWebhookSourceRequest", CreateWebhookSourceSchema);
|
|
361632
361676
|
registry4.register("TriggerEventRequest", TriggerEventSchema);
|
|
@@ -361767,16 +361811,22 @@ function registerWebhookSchemas(registry4) {
|
|
|
361767
361811
|
}
|
|
361768
361812
|
var WebhookSignatureConfigSchema, WebhookSourceSchema, CreateWebhookSourceSchema, TriggerEventSchema, WebhookReceiveResponseSchema;
|
|
361769
361813
|
var init_webhooks2 = __esm(() => {
|
|
361814
|
+
init_src5();
|
|
361770
361815
|
init_zod_openapi();
|
|
361771
361816
|
init_common4();
|
|
361772
361817
|
WebhookSignatureConfigSchema = exports_external.object({
|
|
361773
|
-
algorithm: exports_external.enum(
|
|
361818
|
+
algorithm: exports_external.enum(webhookSignatureAlgorithms).openapi({
|
|
361774
361819
|
description: "How to verify: HMAC over the raw request body, or direct token match"
|
|
361775
361820
|
}),
|
|
361776
|
-
header: exports_external.string().openapi({
|
|
361777
|
-
|
|
361778
|
-
|
|
361821
|
+
header: exports_external.string().min(1).max(200).openapi({
|
|
361822
|
+
description: "Header carrying the signature/token (e.g. X-Hub-Signature-256). 1-200 characters"
|
|
361823
|
+
}),
|
|
361824
|
+
prefix: exports_external.string().max(50).optional().openapi({
|
|
361825
|
+
description: 'Prefix before the hex digest (e.g. "sha256="), at most 50 characters. HMAC algorithms only \u2014 rejected with token-match'
|
|
361779
361826
|
})
|
|
361827
|
+
}).refine((config4) => config4.algorithm !== "token-match" || config4.prefix === undefined, {
|
|
361828
|
+
message: "prefix is not applicable to algorithm 'token-match'",
|
|
361829
|
+
path: ["prefix"]
|
|
361780
361830
|
});
|
|
361781
361831
|
WebhookSourceSchema = exports_external.object({
|
|
361782
361832
|
id: exports_external.string().uuid().openapi({ description: "Source UUID" }),
|
|
@@ -361790,14 +361840,14 @@ var init_webhooks2 = __esm(() => {
|
|
|
361790
361840
|
updatedAt: exports_external.string().datetime().openapi({ description: "Last update timestamp" })
|
|
361791
361841
|
});
|
|
361792
361842
|
CreateWebhookSourceSchema = exports_external.object({
|
|
361793
|
-
name: exports_external.string().min(1).max(100).openapi({ description: "Unique source name" }),
|
|
361843
|
+
name: exports_external.string().min(1).max(100).openapi({ description: "Unique source name (e.g., github, stripe, agno)" }),
|
|
361794
361844
|
description: exports_external.string().optional().openapi({ description: "Description" }),
|
|
361795
361845
|
expectedHeaders: exports_external.record(exports_external.string(), exports_external.boolean()).optional().openapi({ description: "Headers to validate" }),
|
|
361796
361846
|
signatureConfig: WebhookSignatureConfigSchema.nullable().optional().openapi({
|
|
361797
|
-
description: "Signature verification config; required for the source to be reachable on the public ingress"
|
|
361847
|
+
description: "Signature verification config; required for the source to be reachable on the public ingress. " + "Always paired with signatureSecret: a config without a stored secret is rejected (400), and clearing " + "the config (null) also clears the stored secret."
|
|
361798
361848
|
}),
|
|
361799
361849
|
signatureSecret: exports_external.string().min(8).max(512).nullable().optional().openapi({
|
|
361800
|
-
description: "Shared secret used by signatureConfig (write-only, never returned)"
|
|
361850
|
+
description: "Shared secret used by signatureConfig (write-only, never returned; 8-512 characters). Cannot be set " + "without a signatureConfig (given in the same request, or already stored on update); null clears it."
|
|
361801
361851
|
}),
|
|
361802
361852
|
enabled: exports_external.boolean().default(true).openapi({ description: "Whether enabled" })
|
|
361803
361853
|
});
|
|
@@ -365273,6 +365323,27 @@ var init_handoffs = __esm(() => {
|
|
|
365273
365323
|
});
|
|
365274
365324
|
});
|
|
365275
365325
|
|
|
365326
|
+
// ../api/src/lib/whatsapp-business-connection.ts
|
|
365327
|
+
function applyWhatsAppBusinessConnectionOptions(options, input) {
|
|
365328
|
+
if (input.metaAccessToken)
|
|
365329
|
+
options.metaAccessToken = input.metaAccessToken;
|
|
365330
|
+
if (input.metaPhoneNumberId)
|
|
365331
|
+
options.metaPhoneNumberId = input.metaPhoneNumberId;
|
|
365332
|
+
if (input.metaWabaId)
|
|
365333
|
+
options.metaWabaId = input.metaWabaId;
|
|
365334
|
+
if (input.metaAppId)
|
|
365335
|
+
options.metaAppId = input.metaAppId;
|
|
365336
|
+
if (input.metaBusinessId)
|
|
365337
|
+
options.metaBusinessId = input.metaBusinessId;
|
|
365338
|
+
const apiVersion = process.env.META_GRAPH_API_VERSION ?? input.metaApiVersion;
|
|
365339
|
+
if (apiVersion)
|
|
365340
|
+
options.metaApiVersion = apiVersion;
|
|
365341
|
+
if (input.metaDisplayPhoneNumber)
|
|
365342
|
+
options.metaDisplayPhoneNumber = input.metaDisplayPhoneNumber;
|
|
365343
|
+
if (input.metaConnectionMethod)
|
|
365344
|
+
options.metaConnectionMethod = input.metaConnectionMethod;
|
|
365345
|
+
}
|
|
365346
|
+
|
|
365276
365347
|
// ../../node_modules/.bun/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
|
|
365277
365348
|
var require_QRMode = __commonJS((exports, module) => {
|
|
365278
365349
|
module.exports = {
|
|
@@ -366430,7 +366501,7 @@ class AgentReplayService {
|
|
|
366430
366501
|
SELECT 1 FROM ${messages2} AS reply
|
|
366431
366502
|
WHERE reply.chat_id = ${messages2.chatId}
|
|
366432
366503
|
AND reply.is_from_me = true
|
|
366433
|
-
AND
|
|
366504
|
+
AND (reply.raw_payload -> 'omniSystemNotice') IS DISTINCT FROM 'true'::jsonb
|
|
366434
366505
|
AND reply.platform_timestamp > ${messages2.platformTimestamp}
|
|
366435
366506
|
AND reply.deleted_at IS NULL
|
|
366436
366507
|
)`, cursorId ? or2(gt(messages2.platformTimestamp, cursorTimestamp), and2(eq(messages2.platformTimestamp, cursorTimestamp), gt(messages2.id, cursorId))) : gt(messages2.platformTimestamp, cursorTimestamp), lte(messages2.platformTimestamp, now))).orderBy(asc(messages2.platformTimestamp), asc(messages2.id)).limit(PAGE_SIZE));
|
|
@@ -366698,6 +366769,9 @@ function applyChannelSpecificConnectionOptions(options, input) {
|
|
|
366698
366769
|
case "hermes":
|
|
366699
366770
|
applyHermesConnectionOptions(options, input);
|
|
366700
366771
|
return;
|
|
366772
|
+
case "whatsapp-business":
|
|
366773
|
+
applyWhatsAppBusinessConnectionOptions(options, input);
|
|
366774
|
+
return;
|
|
366701
366775
|
}
|
|
366702
366776
|
}
|
|
366703
366777
|
function buildInstanceConnectionOptions(input) {
|
|
@@ -366841,7 +366915,15 @@ function buildConnectConnectionOptions(instance4, body, forceNewQr) {
|
|
|
366841
366915
|
hermesUsername: body.hermesUsername ?? instance4.hermesUsername,
|
|
366842
366916
|
hermesPassword: body.hermesPassword ?? instance4.hermesPassword,
|
|
366843
366917
|
hermesMediaId: body.hermesMediaId ?? instance4.hermesMediaId,
|
|
366844
|
-
hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace
|
|
366918
|
+
hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace,
|
|
366919
|
+
metaAccessToken: instance4.metaAccessToken,
|
|
366920
|
+
metaPhoneNumberId: instance4.metaPhoneNumberId,
|
|
366921
|
+
metaWabaId: instance4.metaWabaId,
|
|
366922
|
+
metaAppId: instance4.metaAppId,
|
|
366923
|
+
metaBusinessId: instance4.metaBusinessId,
|
|
366924
|
+
metaApiVersion: instance4.metaApiVersion,
|
|
366925
|
+
metaDisplayPhoneNumber: instance4.metaDisplayPhoneNumber,
|
|
366926
|
+
metaConnectionMethod: instance4.metaConnectionMethod
|
|
366845
366927
|
});
|
|
366846
366928
|
}
|
|
366847
366929
|
function hydrateConnectionOptionsForInstance(plugin10, instance4, options) {
|
|
@@ -367579,6 +367661,9 @@ var init_instances3 = __esm(() => {
|
|
|
367579
367661
|
if (instance4.channel === "hermes") {
|
|
367580
367662
|
applyHermesConnectionOptions(restartOptions, instance4);
|
|
367581
367663
|
}
|
|
367664
|
+
if (instance4.channel === "whatsapp-business") {
|
|
367665
|
+
applyWhatsAppBusinessConnectionOptions(restartOptions, instance4);
|
|
367666
|
+
}
|
|
367582
367667
|
if (instance4.channel === "whatsapp-baileys" && instance4.markOnlineOnConnect != null) {
|
|
367583
367668
|
restartOptions.whatsapp = {
|
|
367584
367669
|
...restartOptions.whatsapp,
|
|
@@ -371179,7 +371264,12 @@ var init_messages5 = __esm(() => {
|
|
|
371179
371264
|
...list ? { list } : {}
|
|
371180
371265
|
},
|
|
371181
371266
|
replyTo,
|
|
371182
|
-
metadata: {
|
|
371267
|
+
metadata: {
|
|
371268
|
+
...mentions ? { mentions } : {},
|
|
371269
|
+
...replyContext,
|
|
371270
|
+
...senderAgentId ? { senderAgentId } : {},
|
|
371271
|
+
...instance4.messageFormatMode ? { messageFormatMode: instance4.messageFormatMode } : {}
|
|
371272
|
+
}
|
|
371183
371273
|
};
|
|
371184
371274
|
if (correlationId && tracker.isTracking(correlationId)) {
|
|
371185
371275
|
tracker.recordCheckpoint(correlationId, "T8", JOURNEY_STAGES.T8);
|
|
@@ -374111,35 +374201,41 @@ var init_voice2 = __esm(() => {
|
|
|
374111
374201
|
});
|
|
374112
374202
|
});
|
|
374113
374203
|
|
|
374204
|
+
// ../api/src/utils/json-body.ts
|
|
374205
|
+
function parseJsonObjectBody(rawBody) {
|
|
374206
|
+
if (!rawBody)
|
|
374207
|
+
return {};
|
|
374208
|
+
let parsed;
|
|
374209
|
+
try {
|
|
374210
|
+
parsed = JSON.parse(rawBody);
|
|
374211
|
+
} catch {
|
|
374212
|
+
throw new ValidationError2(NOT_AN_OBJECT);
|
|
374213
|
+
}
|
|
374214
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
374215
|
+
throw new ValidationError2(NOT_AN_OBJECT);
|
|
374216
|
+
}
|
|
374217
|
+
return parsed;
|
|
374218
|
+
}
|
|
374219
|
+
var NOT_AN_OBJECT = "Request body must be a JSON object";
|
|
374220
|
+
var init_json_body = __esm(() => {
|
|
374221
|
+
init_src();
|
|
374222
|
+
});
|
|
374223
|
+
|
|
374114
374224
|
// ../api/src/routes/v2/webhooks.ts
|
|
374115
374225
|
function sanitizeSource(source) {
|
|
374116
374226
|
const { signatureSecret, ...rest } = source;
|
|
374117
374227
|
return { ...rest, hasSignatureSecret: Boolean(signatureSecret) };
|
|
374118
374228
|
}
|
|
374119
|
-
var webhooksRoutes,
|
|
374229
|
+
var webhooksRoutes, createWebhookSourceSchema, updateWebhookSourceSchema, listQuerySchema21, triggerEventSchema;
|
|
374120
374230
|
var init_webhooks3 = __esm(() => {
|
|
374121
374231
|
init_dist6();
|
|
374122
|
-
init_src5();
|
|
374123
374232
|
init_dist2();
|
|
374124
374233
|
init_zod();
|
|
374234
|
+
init_webhooks2();
|
|
374125
374235
|
init_api_keys();
|
|
374236
|
+
init_json_body();
|
|
374126
374237
|
webhooksRoutes = new Hono2;
|
|
374127
|
-
|
|
374128
|
-
algorithm: exports_external.enum(webhookSignatureAlgorithms).describe("How to verify: HMAC over the raw body, or token match"),
|
|
374129
|
-
header: exports_external.string().min(1).max(200).describe("Header carrying the signature/token (e.g. X-Hub-Signature-256)"),
|
|
374130
|
-
prefix: exports_external.string().max(50).optional().describe("Prefix before the hex digest (HMAC algorithms only)")
|
|
374131
|
-
}).refine((config4) => config4.algorithm !== "token-match" || config4.prefix === undefined, {
|
|
374132
|
-
message: "prefix is not applicable to algorithm 'token-match'",
|
|
374133
|
-
path: ["prefix"]
|
|
374134
|
-
});
|
|
374135
|
-
createWebhookSourceSchema = exports_external.object({
|
|
374136
|
-
name: exports_external.string().min(1).max(100).describe("Unique source name (e.g., github, stripe, agno)"),
|
|
374137
|
-
description: exports_external.string().optional().describe("Description of the webhook source"),
|
|
374138
|
-
expectedHeaders: exports_external.record(exports_external.string(), exports_external.boolean()).optional().describe("Headers to validate"),
|
|
374139
|
-
signatureConfig: signatureConfigSchema.nullable().optional().describe("Signature verification config"),
|
|
374140
|
-
signatureSecret: exports_external.string().min(8).max(512).nullable().optional().describe("Shared secret (write-only)"),
|
|
374141
|
-
enabled: exports_external.boolean().default(true).describe("Whether source is enabled")
|
|
374142
|
-
});
|
|
374238
|
+
createWebhookSourceSchema = CreateWebhookSourceSchema;
|
|
374143
374239
|
updateWebhookSourceSchema = createWebhookSourceSchema.partial();
|
|
374144
374240
|
listQuerySchema21 = exports_external.object({
|
|
374145
374241
|
enabled: exports_external.coerce.boolean().optional()
|
|
@@ -374179,12 +374275,7 @@ var init_webhooks3 = __esm(() => {
|
|
|
374179
374275
|
const sourceName = c.req.param("source");
|
|
374180
374276
|
const services = c.get("services");
|
|
374181
374277
|
const rawBody = await c.req.text();
|
|
374182
|
-
|
|
374183
|
-
try {
|
|
374184
|
-
payload = rawBody ? JSON.parse(rawBody) : {};
|
|
374185
|
-
} catch {
|
|
374186
|
-
payload = {};
|
|
374187
|
-
}
|
|
374278
|
+
const payload = parseJsonObjectBody(rawBody);
|
|
374188
374279
|
const headers = {};
|
|
374189
374280
|
for (const [key, value] of Object.entries(c.req.header())) {
|
|
374190
374281
|
headers[key.toLowerCase()] = value ?? "";
|
|
@@ -375484,18 +375575,14 @@ function createApp(db2, eventBus = null, channelRegistry2 = null) {
|
|
|
375484
375575
|
const sourceName = c.req.param("source");
|
|
375485
375576
|
const services2 = c.get("services");
|
|
375486
375577
|
const rawBody = await c.req.text();
|
|
375487
|
-
let payload
|
|
375488
|
-
|
|
375489
|
-
|
|
375490
|
-
|
|
375491
|
-
|
|
375492
|
-
|
|
375493
|
-
parsed = undefined;
|
|
375494
|
-
}
|
|
375495
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
375496
|
-
return c.json({ error: { code: "VALIDATION", message: "Request body must be a JSON object" } }, 400);
|
|
375578
|
+
let payload;
|
|
375579
|
+
try {
|
|
375580
|
+
payload = parseJsonObjectBody(rawBody);
|
|
375581
|
+
} catch (error3) {
|
|
375582
|
+
if (error3 instanceof ValidationError2) {
|
|
375583
|
+
return c.json({ error: { code: "VALIDATION", message: error3.message } }, 400);
|
|
375497
375584
|
}
|
|
375498
|
-
|
|
375585
|
+
throw error3;
|
|
375499
375586
|
}
|
|
375500
375587
|
const headers = {};
|
|
375501
375588
|
for (const [key, value] of Object.entries(c.req.header())) {
|
|
@@ -375598,6 +375685,7 @@ var init_app = __esm(() => {
|
|
|
375598
375685
|
init_v2();
|
|
375599
375686
|
init_platform_tenants2();
|
|
375600
375687
|
init_a2a_discovery();
|
|
375688
|
+
init_json_body();
|
|
375601
375689
|
httpLog = createLogger("http");
|
|
375602
375690
|
});
|
|
375603
375691
|
|
|
@@ -377572,7 +377660,7 @@ function buildInstanceConnectOptions(instance4) {
|
|
|
377572
377660
|
applyTwilioWhatsAppOptions(options, instance4);
|
|
377573
377661
|
}
|
|
377574
377662
|
if (instance4.channel === "whatsapp-business") {
|
|
377575
|
-
|
|
377663
|
+
applyWhatsAppBusinessConnectionOptions(options, instance4);
|
|
377576
377664
|
}
|
|
377577
377665
|
if (instance4.channel === "hermes") {
|
|
377578
377666
|
applyHermesOptions(options, instance4);
|
|
@@ -377591,24 +377679,6 @@ function applyHermesOptions(options, instance4) {
|
|
|
377591
377679
|
if (instance4.hermesTemplateNamespace)
|
|
377592
377680
|
options.hermesTemplateNamespace = instance4.hermesTemplateNamespace;
|
|
377593
377681
|
}
|
|
377594
|
-
function applyWhatsAppBusinessOptions(options, instance4) {
|
|
377595
|
-
if (instance4.metaAccessToken)
|
|
377596
|
-
options.metaAccessToken = instance4.metaAccessToken;
|
|
377597
|
-
if (instance4.metaPhoneNumberId)
|
|
377598
|
-
options.metaPhoneNumberId = instance4.metaPhoneNumberId;
|
|
377599
|
-
if (instance4.metaWabaId)
|
|
377600
|
-
options.metaWabaId = instance4.metaWabaId;
|
|
377601
|
-
if (instance4.metaAppId)
|
|
377602
|
-
options.metaAppId = instance4.metaAppId;
|
|
377603
|
-
if (instance4.metaBusinessId)
|
|
377604
|
-
options.metaBusinessId = instance4.metaBusinessId;
|
|
377605
|
-
if (instance4.metaApiVersion)
|
|
377606
|
-
options.metaApiVersion = instance4.metaApiVersion;
|
|
377607
|
-
if (instance4.metaDisplayPhoneNumber)
|
|
377608
|
-
options.metaDisplayPhoneNumber = instance4.metaDisplayPhoneNumber;
|
|
377609
|
-
if (instance4.metaConnectionMethod)
|
|
377610
|
-
options.metaConnectionMethod = instance4.metaConnectionMethod;
|
|
377611
|
-
}
|
|
377612
377682
|
function applyGupshupOptions(options, instance4) {
|
|
377613
377683
|
if (instance4.gupshupCallbackUrl)
|
|
377614
377684
|
options.gupshupCallbackUrl = instance4.gupshupCallbackUrl;
|
|
@@ -385377,16 +385447,33 @@ async function checkBoltHealth(connection) {
|
|
|
385377
385447
|
}
|
|
385378
385448
|
|
|
385379
385449
|
// ../channel-slack/src/handlers/agent-sessions.ts
|
|
385450
|
+
init_zod();
|
|
385451
|
+
var AgentSessionStoppedEventSchema = exports_external.object({
|
|
385452
|
+
channel: exports_external.string().min(1),
|
|
385453
|
+
thread_ts: exports_external.string().optional(),
|
|
385454
|
+
user: exports_external.string().optional(),
|
|
385455
|
+
event_ts: exports_external.string().optional(),
|
|
385456
|
+
streaming_message_ts: exports_external.array(exports_external.string()).optional()
|
|
385457
|
+
}).passthrough();
|
|
385380
385458
|
function setupAgentSessionHandlers(app, instanceId, callbacks, logger5) {
|
|
385381
385459
|
app.event("agent_session_stopped", async ({ event }) => {
|
|
385382
|
-
const
|
|
385383
|
-
|
|
385384
|
-
if (!channelId)
|
|
385460
|
+
const channelHint = event?.channel;
|
|
385461
|
+
if (typeof channelHint !== "string" || channelHint.length === 0)
|
|
385385
385462
|
return;
|
|
385386
|
-
const
|
|
385387
|
-
|
|
385388
|
-
|
|
385389
|
-
|
|
385463
|
+
const parsed = AgentSessionStoppedEventSchema.safeParse(event);
|
|
385464
|
+
if (!parsed.success) {
|
|
385465
|
+
logger5.warn("Ignoring malformed agent_session_stopped event", {
|
|
385466
|
+
instanceId,
|
|
385467
|
+
channelId: channelHint,
|
|
385468
|
+
issues: parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
|
385469
|
+
});
|
|
385470
|
+
return;
|
|
385471
|
+
}
|
|
385472
|
+
const channelId = parsed.data.channel;
|
|
385473
|
+
const threadTs = parsed.data.thread_ts;
|
|
385474
|
+
const userId = parsed.data.user;
|
|
385475
|
+
const eventTs = parsed.data.event_ts;
|
|
385476
|
+
const streamingMessageTs = parsed.data.streaming_message_ts ?? [];
|
|
385390
385477
|
logger5.info("Agent session stopped by user", { instanceId, channelId, threadTs, userId, streamingMessageTs });
|
|
385391
385478
|
await callbacks.onSessionStopped(instanceId, { channelId, threadTs, userId, streamingMessageTs, eventTs });
|
|
385392
385479
|
});
|
|
@@ -385717,6 +385804,7 @@ function buildRawPayload(meta, msg, extra) {
|
|
|
385717
385804
|
ts: meta.ts,
|
|
385718
385805
|
threadTs: meta.threadTs,
|
|
385719
385806
|
threadId: !meta.isDm && meta.threadTs ? meta.threadTs : undefined,
|
|
385807
|
+
cancelThreadId: meta.threadTs,
|
|
385720
385808
|
channelType: meta.channelType,
|
|
385721
385809
|
teamId: meta.teamId,
|
|
385722
385810
|
isDm: meta.isDm,
|
|
@@ -386332,6 +386420,7 @@ function createNativeStreamSender(options) {
|
|
|
386332
386420
|
} = options;
|
|
386333
386421
|
let streamer;
|
|
386334
386422
|
let lastSentContent = "";
|
|
386423
|
+
let streamTs;
|
|
386335
386424
|
let stopped = false;
|
|
386336
386425
|
let fallback;
|
|
386337
386426
|
function buildFallback() {
|
|
@@ -386362,7 +386451,7 @@ function createNativeStreamSender(options) {
|
|
|
386362
386451
|
channel: channelId,
|
|
386363
386452
|
...threadTs ? { thread_ts: threadTs } : {}
|
|
386364
386453
|
});
|
|
386365
|
-
await streamer.append({ markdown_text: firstChunk });
|
|
386454
|
+
noteStreamTs(await streamer.append({ markdown_text: firstChunk }));
|
|
386366
386455
|
lastSentContent = firstChunk;
|
|
386367
386456
|
} catch (err2) {
|
|
386368
386457
|
logger5.warn("native-stream: chat.startStream failed, falling back to replace mode", {
|
|
@@ -386372,12 +386461,27 @@ function createNativeStreamSender(options) {
|
|
|
386372
386461
|
fallback = buildFallback();
|
|
386373
386462
|
}
|
|
386374
386463
|
}
|
|
386464
|
+
function noteStreamTs(response) {
|
|
386465
|
+
if (streamTs || typeof response !== "object" || response === null)
|
|
386466
|
+
return;
|
|
386467
|
+
const ts = response.ts;
|
|
386468
|
+
if (typeof ts === "string" && ts.length > 0)
|
|
386469
|
+
streamTs = ts;
|
|
386470
|
+
}
|
|
386471
|
+
function resolveStreamTs() {
|
|
386472
|
+
if (streamTs)
|
|
386473
|
+
return streamTs;
|
|
386474
|
+
const fromStreamer = streamer?.streamTs;
|
|
386475
|
+
if (typeof fromStreamer === "string" && fromStreamer.length > 0)
|
|
386476
|
+
streamTs = fromStreamer;
|
|
386477
|
+
return streamTs;
|
|
386478
|
+
}
|
|
386375
386479
|
async function appendDelta(newContent) {
|
|
386376
386480
|
const delta = newContent.slice(lastSentContent.length);
|
|
386377
386481
|
if (!delta)
|
|
386378
386482
|
return;
|
|
386379
386483
|
try {
|
|
386380
|
-
await streamer?.append({ markdown_text: delta });
|
|
386484
|
+
noteStreamTs(await streamer?.append({ markdown_text: delta }));
|
|
386381
386485
|
lastSentContent = newContent;
|
|
386382
386486
|
} catch (err2) {
|
|
386383
386487
|
logger5.warn("native-stream: append failed", { error: String(err2) });
|
|
@@ -386437,6 +386541,16 @@ function createNativeStreamSender(options) {
|
|
|
386437
386541
|
if (fallback)
|
|
386438
386542
|
return fallback.cancel ? fallback.cancel() : fallback.abort();
|
|
386439
386543
|
await stopStream();
|
|
386544
|
+
},
|
|
386545
|
+
markStoppedByPlatform(stoppedTs) {
|
|
386546
|
+
if (fallback || stopped || !streamer)
|
|
386547
|
+
return false;
|
|
386548
|
+
const ts = resolveStreamTs();
|
|
386549
|
+
if (!ts || !stoppedTs.includes(ts))
|
|
386550
|
+
return false;
|
|
386551
|
+
stopped = true;
|
|
386552
|
+
logger5.debug("native-stream: stream already halted by Slack, skipping chat.stopStream", { channelId, ts });
|
|
386553
|
+
return true;
|
|
386440
386554
|
}
|
|
386441
386555
|
};
|
|
386442
386556
|
}
|
|
@@ -386598,6 +386712,7 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
386598
386712
|
activeThreads = new Map;
|
|
386599
386713
|
presenceStatusTimers = new Map;
|
|
386600
386714
|
pendingAckReactions = new Map;
|
|
386715
|
+
activeNativeStreams = new Map;
|
|
386601
386716
|
async onInitialize(_context) {}
|
|
386602
386717
|
async onDestroy() {
|
|
386603
386718
|
for (const [instanceId, connection] of this.connections) {
|
|
@@ -386625,6 +386740,7 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
386625
386740
|
this.presenceStatusTimers.clear();
|
|
386626
386741
|
this.activeThreads.clear();
|
|
386627
386742
|
this.pendingAckReactions.clear();
|
|
386743
|
+
this.activeNativeStreams.clear();
|
|
386628
386744
|
}
|
|
386629
386745
|
async connect(instanceId, config2) {
|
|
386630
386746
|
const existing = this.connections.get(instanceId);
|
|
@@ -386729,6 +386845,10 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
386729
386845
|
clearTimeout(timer);
|
|
386730
386846
|
this.presenceStatusTimers.delete(key);
|
|
386731
386847
|
}
|
|
386848
|
+
for (const key of this.activeNativeStreams.keys()) {
|
|
386849
|
+
if (key.startsWith(`${instanceId}:`))
|
|
386850
|
+
this.activeNativeStreams.delete(key);
|
|
386851
|
+
}
|
|
386732
386852
|
for (const key of this.pendingAckReactions.keys()) {
|
|
386733
386853
|
if (key.startsWith(`${instanceId}:`))
|
|
386734
386854
|
this.pendingAckReactions.delete(key);
|
|
@@ -386790,29 +386910,40 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
386790
386910
|
const threadTs = this.resolveThreadTs(replyToMode, replyToMessageId, undefined);
|
|
386791
386911
|
const streamMode = resolveStreamMode(slackConfig.streamMode);
|
|
386792
386912
|
const throttleMs = resolveStreamThrottle(slackConfig.streamThrottleMs);
|
|
386793
|
-
const
|
|
386794
|
-
|
|
386795
|
-
|
|
386796
|
-
|
|
386797
|
-
|
|
386798
|
-
|
|
386799
|
-
|
|
386800
|
-
|
|
386801
|
-
|
|
386802
|
-
|
|
386803
|
-
|
|
386804
|
-
|
|
386805
|
-
|
|
386806
|
-
|
|
386807
|
-
|
|
386808
|
-
|
|
386809
|
-
|
|
386810
|
-
|
|
386811
|
-
|
|
386812
|
-
|
|
386813
|
-
|
|
386814
|
-
|
|
386913
|
+
const streamKey = `${instanceId}:${chatId}`;
|
|
386914
|
+
let native;
|
|
386915
|
+
let base2;
|
|
386916
|
+
if (streamMode === "native") {
|
|
386917
|
+
native = createNativeStreamSender({
|
|
386918
|
+
client: connection.actingClient,
|
|
386919
|
+
channelId: chatId,
|
|
386920
|
+
threadTs,
|
|
386921
|
+
throttleMs,
|
|
386922
|
+
username: slackConfig.defaultUsername,
|
|
386923
|
+
iconUrl: slackConfig.defaultIconUrl,
|
|
386924
|
+
iconEmoji: slackConfig.defaultIconEmoji,
|
|
386925
|
+
formatMode: options?.formatMode ?? "convert",
|
|
386926
|
+
logger: this.logger
|
|
386927
|
+
});
|
|
386928
|
+
base2 = native;
|
|
386929
|
+
this.trackNativeStream(streamKey, native);
|
|
386930
|
+
} else {
|
|
386931
|
+
base2 = createSlackStreamSender({
|
|
386932
|
+
client: connection.actingClient,
|
|
386933
|
+
channelId: chatId,
|
|
386934
|
+
threadTs,
|
|
386935
|
+
streamMode,
|
|
386936
|
+
throttleMs,
|
|
386937
|
+
username: slackConfig.defaultUsername,
|
|
386938
|
+
iconUrl: slackConfig.defaultIconUrl,
|
|
386939
|
+
iconEmoji: slackConfig.defaultIconEmoji,
|
|
386940
|
+
formatMode: options?.formatMode ?? "convert",
|
|
386941
|
+
logger: this.logger
|
|
386942
|
+
});
|
|
386943
|
+
}
|
|
386815
386944
|
const cleanup = () => {
|
|
386945
|
+
if (native)
|
|
386946
|
+
this.untrackNativeStream(streamKey, native);
|
|
386816
386947
|
this.removeAckReaction(instanceId, chatId, connection, replyToMessageId, threadTs);
|
|
386817
386948
|
this.clearActiveTyping(instanceId, chatId, connection, threadTs).catch(() => {});
|
|
386818
386949
|
};
|
|
@@ -386837,6 +386968,32 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
386837
386968
|
}
|
|
386838
386969
|
};
|
|
386839
386970
|
}
|
|
386971
|
+
trackNativeStream(streamKey, sender) {
|
|
386972
|
+
let set = this.activeNativeStreams.get(streamKey);
|
|
386973
|
+
if (!set) {
|
|
386974
|
+
set = new Set;
|
|
386975
|
+
this.activeNativeStreams.set(streamKey, set);
|
|
386976
|
+
}
|
|
386977
|
+
set.add(sender);
|
|
386978
|
+
}
|
|
386979
|
+
untrackNativeStream(streamKey, sender) {
|
|
386980
|
+
const set = this.activeNativeStreams.get(streamKey);
|
|
386981
|
+
if (!set)
|
|
386982
|
+
return;
|
|
386983
|
+
set.delete(sender);
|
|
386984
|
+
if (set.size === 0)
|
|
386985
|
+
this.activeNativeStreams.delete(streamKey);
|
|
386986
|
+
}
|
|
386987
|
+
markStreamsStoppedByPlatform(instanceId, channelId, stoppedTs) {
|
|
386988
|
+
if (stoppedTs.length === 0)
|
|
386989
|
+
return;
|
|
386990
|
+
const senders2 = this.activeNativeStreams.get(`${instanceId}:${channelId}`);
|
|
386991
|
+
if (!senders2)
|
|
386992
|
+
return;
|
|
386993
|
+
for (const sender of senders2) {
|
|
386994
|
+
sender.markStoppedByPlatform(stoppedTs);
|
|
386995
|
+
}
|
|
386996
|
+
}
|
|
386840
386997
|
async sendTyping(instanceId, chatId, duration) {
|
|
386841
386998
|
await this.sendPresenceStatus(instanceId, chatId, duration === 0 ? "paused" : "typing", duration);
|
|
386842
386999
|
}
|
|
@@ -387238,6 +387395,7 @@ class SlackPlugin extends BaseChannelPlugin {
|
|
|
387238
387395
|
async handleAgentSessionStopped(instanceId, connection, args) {
|
|
387239
387396
|
const parsedEventTs = args.eventTs ? Number.parseFloat(args.eventTs) : Number.NaN;
|
|
387240
387397
|
const requestedAt = Number.isFinite(parsedEventTs) ? Math.round(parsedEventTs * 1000) : Date.now();
|
|
387398
|
+
this.markStreamsStoppedByPlatform(instanceId, args.channelId, args.streamingMessageTs ?? []);
|
|
387241
387399
|
try {
|
|
387242
387400
|
await this.eventBus.publish("agent.run.cancel_requested", {
|
|
387243
387401
|
instanceId,
|