@automagik/omni 2.260901.1 → 2.260901.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12312,6 +12312,7 @@ var init_types3 = __esm(() => {
12312
12312
  "batch-job.cancelled",
12313
12313
  "batch-job.failed",
12314
12314
  "agent.state.changed",
12315
+ "agent.run.cancel_requested",
12315
12316
  "agent.task.created",
12316
12317
  "agent.task.updated",
12317
12318
  "agent.task.completed",
@@ -128288,7 +128289,7 @@ import { fileURLToPath } from "url";
128288
128289
  // package.json
128289
128290
  var package_default = {
128290
128291
  name: "@automagik/omni",
128291
- version: "2.260901.1",
128292
+ version: "2.260901.3",
128292
128293
  description: "LLM-optimized CLI for Omni",
128293
128294
  type: "module",
128294
128295
  bin: {
@@ -174,6 +174,7 @@ var init_types2 = __esm(() => {
174
174
  "batch-job.cancelled",
175
175
  "batch-job.failed",
176
176
  "agent.state.changed",
177
+ "agent.run.cancel_requested",
177
178
  "agent.task.created",
178
179
  "agent.task.updated",
179
180
  "agent.task.completed",
@@ -36795,7 +36796,7 @@ function ensureCleanup() {
36795
36796
  }
36796
36797
  }
36797
36798
  function startAck(plugin2, ackProvider, instanceId, chatId, messageId, channel2, config2) {
36798
- const noopHandle = { remove() {} };
36799
+ const noopHandle = { remove() {}, release() {} };
36799
36800
  if (config2.reactionAck !== "on") {
36800
36801
  return noopHandle;
36801
36802
  }
@@ -36830,6 +36831,12 @@ function startAck(plugin2, ackProvider, instanceId, chatId, messageId, channel2,
36830
36831
  if (ackProvider) {
36831
36832
  ackProvider.removeAck(instanceId, chatId, messageId, emoji).catch(() => {});
36832
36833
  }
36834
+ },
36835
+ release() {
36836
+ if (removed)
36837
+ return;
36838
+ removed = true;
36839
+ clearTimeout(timer);
36833
36840
  }
36834
36841
  };
36835
36842
  }
@@ -242894,7 +242901,7 @@ var init_sentry_scrub = __esm(() => {
242894
242901
  var require_package7 = __commonJS((exports, module) => {
242895
242902
  module.exports = {
242896
242903
  name: "@omni/api",
242897
- version: "2.260901.1",
242904
+ version: "2.260901.3",
242898
242905
  type: "module",
242899
242906
  exports: {
242900
242907
  ".": {
@@ -343539,14 +343546,16 @@ var init_loader2 = __esm(() => {
343539
343546
  class MessageDebouncer {
343540
343547
  buffers = new Map;
343541
343548
  timers = new Map;
343542
- inFlight = new Set;
343549
+ inFlight = new Map;
343543
343550
  firstBufferedAt = new Map;
343544
343551
  lastConfig = new Map;
343545
343552
  onFlush;
343546
343553
  now;
343547
- constructor(onFlush, now = Date.now) {
343554
+ options;
343555
+ constructor(onFlush, now = Date.now, options = {}) {
343548
343556
  this.onFlush = onFlush;
343549
343557
  this.now = now;
343558
+ this.options = options;
343550
343559
  }
343551
343560
  getChatKey(instanceId, chatId) {
343552
343561
  return `${instanceId}:${chatId}`;
@@ -343559,8 +343568,19 @@ class MessageDebouncer {
343559
343568
  if (!this.firstBufferedAt.has(chatKey))
343560
343569
  this.firstBufferedAt.set(chatKey, this.now());
343561
343570
  this.lastConfig.set(chatKey, config4);
343562
- if (this.inFlight.has(chatKey))
343571
+ if (this.inFlight.has(chatKey)) {
343572
+ const blockingTraceId = this.inFlight.get(chatKey);
343573
+ const queuePosition = buffer3.length;
343574
+ log89.info("agent_dispatch_queued", {
343575
+ instanceId,
343576
+ chatId,
343577
+ traceId: message2.metadata.traceId,
343578
+ queuePosition,
343579
+ blockingTraceId
343580
+ });
343581
+ this.options.onQueuedBehindActiveRun?.({ instanceId, chatId, message: message2, queuePosition, blockingTraceId });
343563
343582
  return;
343583
+ }
343564
343584
  this.restartTimer(chatKey, config4);
343565
343585
  }
343566
343586
  hasPending(instanceId, chatId) {
@@ -343621,7 +343641,7 @@ class MessageDebouncer {
343621
343641
  clearTimeout(timer2);
343622
343642
  if (!messages4?.length)
343623
343643
  return;
343624
- this.inFlight.add(chatKey);
343644
+ this.inFlight.set(chatKey, messages4[0]?.metadata.traceId);
343625
343645
  try {
343626
343646
  await this.onFlush(chatKey, messages4);
343627
343647
  } catch (error3) {
@@ -345473,6 +345493,51 @@ async function fetchChatMetadata(services, instanceId, chatId, chatType, trusted
345473
345493
  return {};
345474
345494
  }
345475
345495
  }
345496
+ function runAbortKey(instanceId, chatId, threadId2) {
345497
+ return `${instanceId}:${chatId}:${threadId2 ?? ""}`;
345498
+ }
345499
+ async function cancelActiveAgentRun(instanceId, chatId, reason, opts) {
345500
+ let entry = activeRunAborts.get(runAbortKey(instanceId, chatId, opts?.threadId));
345501
+ if (!entry && opts?.threadId) {
345502
+ entry = activeRunAborts.get(runAbortKey(instanceId, chatId));
345503
+ }
345504
+ if (!entry) {
345505
+ log91.info("Agent run cancel requested but nothing in flight", {
345506
+ instanceId,
345507
+ chatId,
345508
+ threadId: opts?.threadId,
345509
+ reason
345510
+ });
345511
+ return false;
345512
+ }
345513
+ if (opts?.requestedAt !== undefined && entry.startedAt > opts.requestedAt) {
345514
+ log91.info("Agent run cancel ignored \u2014 run started after the stop request", {
345515
+ instanceId,
345516
+ chatId,
345517
+ threadId: opts?.threadId,
345518
+ startedAt: entry.startedAt,
345519
+ requestedAt: opts.requestedAt,
345520
+ reason
345521
+ });
345522
+ return false;
345523
+ }
345524
+ log91.info("Cancelling in-flight agent run", {
345525
+ instanceId,
345526
+ chatId,
345527
+ threadId: opts?.threadId,
345528
+ reason,
345529
+ hasActiveStream: !!entry.sender
345530
+ });
345531
+ entry.controller.abort();
345532
+ if (entry.sender) {
345533
+ try {
345534
+ await (entry.sender.cancel ? entry.sender.cancel() : entry.sender.abort());
345535
+ } catch (err2) {
345536
+ log91.warn("Stream sender cancel failed during run cancellation", { instanceId, chatId, error: String(err2) });
345537
+ }
345538
+ }
345539
+ return true;
345540
+ }
345476
345541
  async function routeStreamDelta(sender, delta) {
345477
345542
  switch (delta.phase) {
345478
345543
  case "thinking":
@@ -345693,6 +345758,10 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
345693
345758
  const sender = resolved.createSender(instance4.id, chatId, replyToId, chatType, { formatMode });
345694
345759
  const streamKey = `${instance4.id}:${chatId}`;
345695
345760
  activeStreams.set(streamKey, sender);
345761
+ const cancelController = new AbortController;
345762
+ const runKey = runAbortKey(instance4.id, chatId, rawThreadId);
345763
+ activeRunAborts.set(runKey, { controller: cancelController, startedAt: Date.now(), sender });
345764
+ trigger.abortSignal = cancelController.signal;
345696
345765
  const streamDispatchStart = Date.now();
345697
345766
  try {
345698
345767
  const generator = resolved.provider.triggerStream(trigger);
@@ -345707,8 +345776,12 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
345707
345776
  attributes: { provider_type: resolved.provider.schema }
345708
345777
  });
345709
345778
  }
345710
- return streamResult;
345779
+ return cancelController.signal.aborted ? true : streamResult;
345711
345780
  } catch (err2) {
345781
+ if (cancelController.signal.aborted) {
345782
+ log91.info("Streaming dispatch cancelled by user", { instanceId: instance4.id, chatId, traceId });
345783
+ return true;
345784
+ }
345712
345785
  log91.error("Streaming dispatch failed, falling back", {
345713
345786
  instanceId: instance4.id,
345714
345787
  chatId,
@@ -345721,6 +345794,7 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
345721
345794
  return false;
345722
345795
  } finally {
345723
345796
  activeStreams.delete(streamKey);
345797
+ activeRunAborts.delete(runKey);
345724
345798
  }
345725
345799
  }
345726
345800
  function formatMediaContent(msg) {
@@ -345919,6 +345993,38 @@ async function dispatchViaTurnBasedProvider(services, instance4, provider, trigg
345919
345993
  });
345920
345994
  return true;
345921
345995
  }
345996
+ function resolveReplySuppression(flags) {
345997
+ if (flags.handoffTriggered)
345998
+ return "handoff_triggered";
345999
+ if (flags.errorHandoffDone)
346000
+ return "error_handoff";
346001
+ if (flags.supersededByNewerInbound)
346002
+ return "superseded_by_newer_inbound";
346003
+ if (flags.runCancelled)
346004
+ return "run_cancelled_by_user";
346005
+ return null;
346006
+ }
346007
+ async function triggerProviderWithCancellation(provider, trigger, spanAttributes, instanceId, chatId, traceId) {
346008
+ const cancelController = new AbortController;
346009
+ const runKey = runAbortKey(instanceId, chatId, trigger.source.threadId);
346010
+ activeRunAborts.set(runKey, { controller: cancelController, startedAt: Date.now() });
346011
+ try {
346012
+ const result = await withLifecycleSpan("omni.dispatch_to_agno", spanAttributes, () => provider.trigger({
346013
+ ...trigger,
346014
+ abortSignal: cancelController.signal,
346015
+ traceContext: activeProviderTraceContext() ?? trigger.traceContext
346016
+ }));
346017
+ return { result, cancelled: cancelController.signal.aborted };
346018
+ } catch (err2) {
346019
+ if (cancelController.signal.aborted) {
346020
+ log91.info("Agent run cancelled by user during dispatch", { instanceId, chatId, traceId });
346021
+ return null;
346022
+ }
346023
+ throw err2;
346024
+ } finally {
346025
+ activeRunAborts.delete(runKey);
346026
+ }
346027
+ }
345922
346028
  async function dispatchViaProvider(services, instance4, messages4, triggerType, channel5, chatId, senderId, personId, senderName, traceId, rawEvent, db2, extraContextMessages, senderAgentId) {
345923
346029
  const provider = await getAgentProvider(services, instance4, db2);
345924
346030
  if (!provider)
@@ -345988,11 +346094,14 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
345988
346094
  }
345989
346095
  const correlationId = messages4[0]?.metadata.correlationId;
345990
346096
  const dispatchStart = Date.now();
345991
- const result = await withLifecycleSpan("omni.dispatch_to_agno", buildLifecycleSpanAttributes({
346097
+ const triggerOutcome = await triggerProviderWithCancellation(provider, trigger, buildLifecycleSpanAttributes({
345992
346098
  ...lifecycleBase,
345993
346099
  stage: "dispatch_to_agno",
345994
346100
  extra: { trigger_type: triggerType, provider_id: provider.id, provider_schema: provider.schema }
345995
- }), () => provider.trigger({ ...trigger, traceContext: activeProviderTraceContext() ?? trigger.traceContext }));
346101
+ }), instance4.id, chatId, traceId);
346102
+ if (!triggerOutcome)
346103
+ return true;
346104
+ const { result, cancelled: runCancelled } = triggerOutcome;
345996
346105
  const dispatchDurationMs = Date.now() - dispatchStart;
345997
346106
  if (sentryEnabled()) {
345998
346107
  exports_public_api2.count("agent.dispatch", 1, { attributes: { provider_type: provider.schema } });
@@ -346005,7 +346114,13 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
346005
346114
  const handoffTriggered = chatAfterRun?.settings?.agentPaused === true;
346006
346115
  const supersededByNewerInbound = !handoffTriggered && isReplySuperseded(instance4, chatId);
346007
346116
  const errorHandoffDone = await maybeTriggerErrorHandoff(services, db2, channel5, instance4, chatId, result?.metadata.customerErrorBlocked === true, handoffTriggered, messages4[0]?.metadata.trustedTenantId);
346008
- if (result && result.parts.length > 0 && !handoffTriggered && !errorHandoffDone && !supersededByNewerInbound) {
346117
+ const suppressReason = resolveReplySuppression({
346118
+ handoffTriggered,
346119
+ errorHandoffDone,
346120
+ supersededByNewerInbound,
346121
+ runCancelled
346122
+ });
346123
+ if (result && result.parts.length > 0 && !suppressReason) {
346009
346124
  const selfChat = isSelfChat(chatId, instance4.ownerIdentifier);
346010
346125
  const rawParts = selfChat ? result.parts.map((p2) => `${BOT_PREFIX}${p2}`) : result.parts;
346011
346126
  const parts = await Promise.all(rawParts.map((part) => executeBeforeMessageWriteHooks(instance4.id, chatId, part)));
@@ -346021,13 +346136,9 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
346021
346136
  }), () => sendResponseParts(channel5, instance4.id, chatId, parts, getSplitDelayConfig(instance4), _fmtMode, replyTo, correlationId, senderAgentId));
346022
346137
  recordJourneyCheckpoint(correlationId, "T9", JOURNEY_STAGES.T9);
346023
346138
  await forwardToChainedInstance(instance4, parts, correlationId, messages4);
346024
- } else if (handoffTriggered) {
346025
- log91.info("Agent response suppressed \u2014 handoff triggered during run", {
346026
- instanceId: instance4.id,
346027
- chatId
346028
- });
346029
- } else if (supersededByNewerInbound) {
346030
- log91.info("Agent response discarded \u2014 superseded by newer inbound", {
346139
+ } else if (suppressReason) {
346140
+ log91.info("Agent response suppressed", {
346141
+ reason: suppressReason,
346031
346142
  instanceId: instance4.id,
346032
346143
  chatId,
346033
346144
  parts: result?.parts.length ?? 0,
@@ -346370,6 +346481,34 @@ function buildAckConfig(instance4) {
346370
346481
  ackTimeoutMs: inst.ackTimeoutMs ?? 30000
346371
346482
  };
346372
346483
  }
346484
+ function takeQueuedAck(chatKey) {
346485
+ const entry = queuedMessageAcks.get(chatKey);
346486
+ queuedMessageAcks.delete(chatKey);
346487
+ return entry?.handle;
346488
+ }
346489
+ async function ackQueuedMessage(info2) {
346490
+ const chatKey = `${info2.instanceId}:${info2.chatId}`;
346491
+ try {
346492
+ const existing = queuedMessageAcks.get(chatKey);
346493
+ if (existing && Date.now() - existing.at < QUEUED_ACK_TIMEOUT_MS)
346494
+ return;
346495
+ const instance4 = info2.message.metadata.resolvedInstance;
346496
+ const messageId = info2.message.payload.externalId;
346497
+ if (!instance4 || !messageId)
346498
+ return;
346499
+ const entry = { at: Date.now() };
346500
+ queuedMessageAcks.set(chatKey, entry);
346501
+ const channel5 = info2.message.metadata.channelType ?? instance4.channel;
346502
+ const plugin10 = await getPlugin(channel5) ?? null;
346503
+ entry.handle = startAck(plugin10, createPluginAckProvider(plugin10), instance4.id, info2.chatId, messageId, channel5, {
346504
+ ...buildAckConfig(instance4),
346505
+ ackTimeoutMs: QUEUED_ACK_TIMEOUT_MS
346506
+ });
346507
+ } catch (error3) {
346508
+ queuedMessageAcks.delete(chatKey);
346509
+ log91.debug("Failed to ack queued message", { chatId: info2.chatId, error: String(error3) });
346510
+ }
346511
+ }
346373
346512
  async function dispatchToAgent(services, instance4, msgs, triggerType, channel5, chatId, senderId, personId, senderName, traceId, senderAgentId, perThreadExtraContext, db2) {
346374
346513
  const firstMsg = msgs[0];
346375
346514
  if (!firstMsg)
@@ -347463,10 +347602,13 @@ async function setupAgentDispatcher(eventBus, services, db2) {
347463
347602
  }
347464
347603
  }
347465
347604
  }, 60000);
347466
- const debouncer = new MessageDebouncer(async (_chatKey, messages4) => {
347605
+ const onDebouncedFlush = async (chatKey, messages4) => {
347606
+ const queuedAck = takeQueuedAck(chatKey);
347467
347607
  const firstMsg = messages4[0];
347468
- if (!firstMsg)
347608
+ if (!firstMsg) {
347609
+ queuedAck?.remove();
347469
347610
  return;
347611
+ }
347470
347612
  const instanceId = firstMsg.metadata.instanceId;
347471
347613
  let instance4;
347472
347614
  if (firstMsg.metadata.resolvedInstance) {
@@ -347475,6 +347617,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
347475
347617
  const baseInstance = await runDispatchDb(db2, firstMsg.metadata.trustedTenantId, () => agentRunner.getInstanceWithProvider(instanceId));
347476
347618
  if (!baseInstance) {
347477
347619
  log91.warn("Instance not found for debounced messages", { instanceId });
347620
+ queuedAck?.remove();
347478
347621
  return;
347479
347622
  }
347480
347623
  const externalChatId = firstMsg.payload.chatId;
@@ -347484,13 +347627,19 @@ async function setupAgentDispatcher(eventBus, services, db2) {
347484
347627
  }
347485
347628
  const msgContext = buildMessageContext(firstMsg.payload, instance4);
347486
347629
  const triggerType = classifyMessageTrigger(msgContext);
347487
- if (await shouldSkipViaGate(triggerType, firstMsg, instance4, messages4, services))
347630
+ if (await shouldSkipViaGate(triggerType, firstMsg, instance4, messages4, services)) {
347631
+ queuedAck?.remove();
347488
347632
  return;
347633
+ }
347489
347634
  if (firstMsg.metadata.journeyTracked && firstMsg.metadata.correlationId) {
347490
347635
  const tracker = getJourneyTracker();
347491
347636
  tracker.recordCheckpoint(firstMsg.metadata.correlationId, "T5", JOURNEY_STAGES.T5);
347492
347637
  }
347638
+ queuedAck?.release();
347493
347639
  await processAgentResponse(services, instance4, messages4, triggerType, db2, eventBus);
347640
+ };
347641
+ const debouncer = new MessageDebouncer(onDebouncedFlush, Date.now, {
347642
+ onQueuedBehindActiveRun: (info2) => void ackQueuedMessage(info2)
347494
347643
  });
347495
347644
  activeMessageDebouncer = debouncer;
347496
347645
  try {
@@ -347656,7 +347805,24 @@ async function setupAgentDispatcher(eventBus, services, db2) {
347656
347805
  queue: "agent-dispatcher-media",
347657
347806
  startFrom: "new"
347658
347807
  });
347659
- log91.info("Agent dispatcher initialized (message + reaction + reaction-removed + media triggers)");
347808
+ await eventBus.subscribe("agent.run.cancel_requested", async (event) => {
347809
+ const payload = event.payload;
347810
+ try {
347811
+ await cancelActiveAgentRun(payload.instanceId, payload.chatId, payload.reason, {
347812
+ threadId: payload.threadId,
347813
+ requestedAt: payload.requestedAt
347814
+ });
347815
+ } catch (error3) {
347816
+ log91.error("Error cancelling agent run", {
347817
+ instanceId: payload.instanceId,
347818
+ chatId: payload.chatId,
347819
+ error: String(error3)
347820
+ });
347821
+ }
347822
+ }, {
347823
+ startFrom: "new"
347824
+ });
347825
+ log91.info("Agent dispatcher initialized (message + reaction + reaction-removed + media + cancel triggers)");
347660
347826
  } catch (error3) {
347661
347827
  log91.error("Failed to set up agent dispatcher", { error: String(error3) });
347662
347828
  clearInterval(mediaCleanupInterval);
@@ -347710,7 +347876,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
347710
347876
  log91.info("Agent dispatcher shutdown complete");
347711
347877
  };
347712
347878
  }
347713
- 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, sessionActivityStore, PROC_REACT_START, PROC_REACT_DONE = "\u2705", 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;
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;
347714
347880
  var init_agent_dispatcher = __esm(() => {
347715
347881
  init_src2();
347716
347882
  init_src();
@@ -347767,8 +347933,10 @@ var init_agent_dispatcher = __esm(() => {
347767
347933
  mediaResultCache = new Map;
347768
347934
  DEFAULT_SEND_MEDIA_PATH_TYPES = ["image", "video", "document"];
347769
347935
  activeStreams = new Map;
347936
+ activeRunAborts = new Map;
347770
347937
  sessionActivityStore = new InMemorySessionActivityStore;
347771
347938
  PROC_REACT_START = { audio: "\uD83C\uDFA7", image: "\uD83D\uDC40", video: "\uD83D\uDC40", document: "\uD83D\uDC40" };
347939
+ queuedMessageAcks = new Map;
347772
347940
  providerCache = new Map;
347773
347941
  openclawClientPool = new Map;
347774
347942
  _openClawClientCtor = OpenClawClient;
@@ -365105,6 +365273,27 @@ var init_handoffs = __esm(() => {
365105
365273
  });
365106
365274
  });
365107
365275
 
365276
+ // ../api/src/lib/whatsapp-business-connection.ts
365277
+ function applyWhatsAppBusinessConnectionOptions(options, input) {
365278
+ if (input.metaAccessToken)
365279
+ options.metaAccessToken = input.metaAccessToken;
365280
+ if (input.metaPhoneNumberId)
365281
+ options.metaPhoneNumberId = input.metaPhoneNumberId;
365282
+ if (input.metaWabaId)
365283
+ options.metaWabaId = input.metaWabaId;
365284
+ if (input.metaAppId)
365285
+ options.metaAppId = input.metaAppId;
365286
+ if (input.metaBusinessId)
365287
+ options.metaBusinessId = input.metaBusinessId;
365288
+ const apiVersion = process.env.META_GRAPH_API_VERSION ?? input.metaApiVersion;
365289
+ if (apiVersion)
365290
+ options.metaApiVersion = apiVersion;
365291
+ if (input.metaDisplayPhoneNumber)
365292
+ options.metaDisplayPhoneNumber = input.metaDisplayPhoneNumber;
365293
+ if (input.metaConnectionMethod)
365294
+ options.metaConnectionMethod = input.metaConnectionMethod;
365295
+ }
365296
+
365108
365297
  // ../../node_modules/.bun/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
365109
365298
  var require_QRMode = __commonJS((exports, module) => {
365110
365299
  module.exports = {
@@ -366530,6 +366719,9 @@ function applyChannelSpecificConnectionOptions(options, input) {
366530
366719
  case "hermes":
366531
366720
  applyHermesConnectionOptions(options, input);
366532
366721
  return;
366722
+ case "whatsapp-business":
366723
+ applyWhatsAppBusinessConnectionOptions(options, input);
366724
+ return;
366533
366725
  }
366534
366726
  }
366535
366727
  function buildInstanceConnectionOptions(input) {
@@ -366673,7 +366865,15 @@ function buildConnectConnectionOptions(instance4, body, forceNewQr) {
366673
366865
  hermesUsername: body.hermesUsername ?? instance4.hermesUsername,
366674
366866
  hermesPassword: body.hermesPassword ?? instance4.hermesPassword,
366675
366867
  hermesMediaId: body.hermesMediaId ?? instance4.hermesMediaId,
366676
- hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace
366868
+ hermesTemplateNamespace: body.hermesTemplateNamespace ?? instance4.hermesTemplateNamespace,
366869
+ metaAccessToken: instance4.metaAccessToken,
366870
+ metaPhoneNumberId: instance4.metaPhoneNumberId,
366871
+ metaWabaId: instance4.metaWabaId,
366872
+ metaAppId: instance4.metaAppId,
366873
+ metaBusinessId: instance4.metaBusinessId,
366874
+ metaApiVersion: instance4.metaApiVersion,
366875
+ metaDisplayPhoneNumber: instance4.metaDisplayPhoneNumber,
366876
+ metaConnectionMethod: instance4.metaConnectionMethod
366677
366877
  });
366678
366878
  }
366679
366879
  function hydrateConnectionOptionsForInstance(plugin10, instance4, options) {
@@ -367411,6 +367611,9 @@ var init_instances3 = __esm(() => {
367411
367611
  if (instance4.channel === "hermes") {
367412
367612
  applyHermesConnectionOptions(restartOptions, instance4);
367413
367613
  }
367614
+ if (instance4.channel === "whatsapp-business") {
367615
+ applyWhatsAppBusinessConnectionOptions(restartOptions, instance4);
367616
+ }
367414
367617
  if (instance4.channel === "whatsapp-baileys" && instance4.markOnlineOnConnect != null) {
367415
367618
  restartOptions.whatsapp = {
367416
367619
  ...restartOptions.whatsapp,
@@ -371011,7 +371214,12 @@ var init_messages5 = __esm(() => {
371011
371214
  ...list ? { list } : {}
371012
371215
  },
371013
371216
  replyTo,
371014
- metadata: { ...mentions ? { mentions } : {}, ...replyContext, ...senderAgentId ? { senderAgentId } : {} }
371217
+ metadata: {
371218
+ ...mentions ? { mentions } : {},
371219
+ ...replyContext,
371220
+ ...senderAgentId ? { senderAgentId } : {},
371221
+ ...instance4.messageFormatMode ? { messageFormatMode: instance4.messageFormatMode } : {}
371222
+ }
371015
371223
  };
371016
371224
  if (correlationId && tracker.isTracking(correlationId)) {
371017
371225
  tracker.recordCheckpoint(correlationId, "T8", JOURNEY_STAGES.T8);
@@ -377404,7 +377612,7 @@ function buildInstanceConnectOptions(instance4) {
377404
377612
  applyTwilioWhatsAppOptions(options, instance4);
377405
377613
  }
377406
377614
  if (instance4.channel === "whatsapp-business") {
377407
- applyWhatsAppBusinessOptions(options, instance4);
377615
+ applyWhatsAppBusinessConnectionOptions(options, instance4);
377408
377616
  }
377409
377617
  if (instance4.channel === "hermes") {
377410
377618
  applyHermesOptions(options, instance4);
@@ -377423,24 +377631,6 @@ function applyHermesOptions(options, instance4) {
377423
377631
  if (instance4.hermesTemplateNamespace)
377424
377632
  options.hermesTemplateNamespace = instance4.hermesTemplateNamespace;
377425
377633
  }
377426
- function applyWhatsAppBusinessOptions(options, instance4) {
377427
- if (instance4.metaAccessToken)
377428
- options.metaAccessToken = instance4.metaAccessToken;
377429
- if (instance4.metaPhoneNumberId)
377430
- options.metaPhoneNumberId = instance4.metaPhoneNumberId;
377431
- if (instance4.metaWabaId)
377432
- options.metaWabaId = instance4.metaWabaId;
377433
- if (instance4.metaAppId)
377434
- options.metaAppId = instance4.metaAppId;
377435
- if (instance4.metaBusinessId)
377436
- options.metaBusinessId = instance4.metaBusinessId;
377437
- if (instance4.metaApiVersion)
377438
- options.metaApiVersion = instance4.metaApiVersion;
377439
- if (instance4.metaDisplayPhoneNumber)
377440
- options.metaDisplayPhoneNumber = instance4.metaDisplayPhoneNumber;
377441
- if (instance4.metaConnectionMethod)
377442
- options.metaConnectionMethod = instance4.metaConnectionMethod;
377443
- }
377444
377634
  function applyGupshupOptions(options, instance4) {
377445
377635
  if (instance4.gupshupCallbackUrl)
377446
377636
  options.gupshupCallbackUrl = instance4.gupshupCallbackUrl;
@@ -385208,6 +385398,23 @@ async function checkBoltHealth(connection) {
385208
385398
  }
385209
385399
  }
385210
385400
 
385401
+ // ../channel-slack/src/handlers/agent-sessions.ts
385402
+ function setupAgentSessionHandlers(app, instanceId, callbacks, logger5) {
385403
+ app.event("agent_session_stopped", async ({ event }) => {
385404
+ const evt = event;
385405
+ const channelId = evt.channel;
385406
+ if (!channelId)
385407
+ return;
385408
+ const threadTs = evt.thread_ts;
385409
+ const userId = evt.user;
385410
+ const eventTs = evt.event_ts;
385411
+ const streamingMessageTs = Array.isArray(evt.streaming_message_ts) ? evt.streaming_message_ts : [];
385412
+ logger5.info("Agent session stopped by user", { instanceId, channelId, threadTs, userId, streamingMessageTs });
385413
+ await callbacks.onSessionStopped(instanceId, { channelId, threadTs, userId, streamingMessageTs, eventTs });
385414
+ });
385415
+ logger5.info("Agent session handlers registered", { instanceId });
385416
+ }
385417
+
385211
385418
  // ../channel-slack/src/handlers/commands.ts
385212
385419
  function setupCommandHandlers(app, instanceId, commandNames, callbacks, logger5) {
385213
385420
  for (const commandName of commandNames) {
@@ -385687,10 +385894,62 @@ function setupReactionHandlers2(app, instanceId, botUserId, callbacks, logger5)
385687
385894
 
385688
385895
  // ../channel-slack/src/handlers/typing.ts
385689
385896
  var CLEAR_STATUS = "";
385897
+ var AGENT_API_UNAVAILABLE_ERRORS = new Set([
385898
+ "unknown_method",
385899
+ "feature_disabled",
385900
+ "method_deprecated",
385901
+ "missing_scope",
385902
+ "not_allowed_token_type"
385903
+ ]);
385904
+ var agentApiUnavailable = new WeakSet;
385905
+ function slackErrorCode(err2) {
385906
+ return err2?.data?.error;
385907
+ }
385690
385908
  async function setSlackThreadStatus(params) {
385691
385909
  const { client, channelId, threadTs, status, loadingMessages, logger: logger5, instanceId } = params;
385692
- if (!threadTs)
385693
- return false;
385910
+ if (!threadTs) {
385911
+ logger5.debug("setSlackThreadStatus: skipped, no thread timestamp", {
385912
+ instanceId,
385913
+ channelId,
385914
+ reason: "no_thread_ts",
385915
+ clearing: status.length === 0
385916
+ });
385917
+ return { delivered: false };
385918
+ }
385919
+ const clearing = status.length === 0;
385920
+ const logContext = {
385921
+ instanceId,
385922
+ channelId,
385923
+ threadTs,
385924
+ clearing,
385925
+ statusLength: status.length,
385926
+ loadingMessageCount: loadingMessages?.length ?? 0
385927
+ };
385928
+ if (typeof client.apiCall === "function" && !agentApiUnavailable.has(client)) {
385929
+ try {
385930
+ await client.apiCall("agents.sessions.setStatus", {
385931
+ channel_id: channelId,
385932
+ thread_ts: threadTs,
385933
+ status: clearing ? "active" : "processing"
385934
+ });
385935
+ return { delivered: true, method: "agents.sessions.setStatus" };
385936
+ } catch (err2) {
385937
+ const code = slackErrorCode(err2);
385938
+ if (code && AGENT_API_UNAVAILABLE_ERRORS.has(code)) {
385939
+ agentApiUnavailable.add(client);
385940
+ logger5.info("agents.sessions.setStatus unavailable, falling back to assistant.threads.setStatus", {
385941
+ instanceId,
385942
+ channelId,
385943
+ error: code
385944
+ });
385945
+ } else {
385946
+ logger5.warn("agents.sessions.setStatus failed, trying legacy fallback", {
385947
+ ...logContext,
385948
+ error: String(err2)
385949
+ });
385950
+ }
385951
+ }
385952
+ }
385694
385953
  const payload = {
385695
385954
  channel_id: channelId,
385696
385955
  thread_ts: threadTs,
@@ -385698,27 +385957,19 @@ async function setSlackThreadStatus(params) {
385698
385957
  ...loadingMessages?.length ? { loading_messages: loadingMessages } : {}
385699
385958
  };
385700
385959
  try {
385701
- const clientAny = client;
385702
- if (typeof clientAny.assistant?.threads?.setStatus === "function") {
385703
- await clientAny.assistant.threads.setStatus(payload);
385704
- return true;
385960
+ const legacyClient = client;
385961
+ if (typeof legacyClient.assistant?.threads?.setStatus === "function") {
385962
+ await legacyClient.assistant.threads.setStatus(payload);
385963
+ return { delivered: true, method: "assistant.threads.setStatus" };
385705
385964
  }
385706
- if (typeof clientAny.apiCall === "function") {
385707
- await clientAny.apiCall("assistant.threads.setStatus", payload);
385708
- return true;
385965
+ if (typeof legacyClient.apiCall === "function") {
385966
+ await legacyClient.apiCall("assistant.threads.setStatus", payload);
385967
+ return { delivered: true, method: "assistant.threads.setStatus" };
385709
385968
  }
385710
385969
  } catch (err2) {
385711
- logger5.warn("setSlackThreadStatus: failed", {
385712
- instanceId,
385713
- channelId,
385714
- threadTs,
385715
- clearing: status.length === 0,
385716
- statusLength: status.length,
385717
- loadingMessageCount: loadingMessages?.length ?? 0,
385718
- error: String(err2)
385719
- });
385970
+ logger5.warn("setSlackThreadStatus: failed", { ...logContext, error: String(err2) });
385720
385971
  }
385721
- return false;
385972
+ return { delivered: false, method: "assistant.threads.setStatus" };
385722
385973
  }
385723
385974
  async function clearTypingStatus(params) {
385724
385975
  return setSlackThreadStatus({ ...params, status: CLEAR_STATUS });
@@ -385893,6 +386144,7 @@ function createSlackStreamSender(options) {
385893
386144
  let finalized = false;
385894
386145
  let pendingContent;
385895
386146
  let throttleTimer;
386147
+ let lastContent = "";
385896
386148
  function formatText(text) {
385897
386149
  return formatMode === "passthrough" ? text : markdownToMrkdwn(text);
385898
386150
  }
@@ -385951,6 +386203,8 @@ function createSlackStreamSender(options) {
385951
386203
  }
385952
386204
  }
385953
386205
  async function finalize(text) {
386206
+ if (finalized)
386207
+ return;
385954
386208
  finalized = true;
385955
386209
  if (throttleTimer) {
385956
386210
  clearTimeout(throttleTimer);
@@ -385976,31 +386230,60 @@ function createSlackStreamSender(options) {
385976
386230
  await sendInitial(chunk);
385977
386231
  }
385978
386232
  }
386233
+ async function deleteDraft() {
386234
+ if (draftTs && !finalized) {
386235
+ try {
386236
+ await client.chat.delete({ channel: channelId, ts: draftTs });
386237
+ } catch {}
386238
+ }
386239
+ finalized = true;
386240
+ }
386241
+ async function cancelKeepingPartial() {
386242
+ if (finalized)
386243
+ return;
386244
+ if (lastContent.trim()) {
386245
+ await finalize(lastContent);
386246
+ return;
386247
+ }
386248
+ await deleteDraft();
386249
+ }
385979
386250
  if (streamMode === "off") {
385980
386251
  return {
385981
386252
  async onThinkingDelta(_delta) {},
385982
386253
  async onContentDelta(_delta) {},
385983
386254
  async onFinal(delta) {
385984
- await sendInitial(delta.content);
386255
+ if (finalized)
386256
+ return;
385985
386257
  finalized = true;
386258
+ await sendInitial(delta.content);
385986
386259
  },
385987
386260
  async onError(delta) {
385988
- await sendInitial(`Error: ${delta.error}`);
386261
+ if (finalized)
386262
+ return;
385989
386263
  finalized = true;
386264
+ await sendInitial(`Error: ${delta.error}`);
385990
386265
  },
385991
386266
  async abort() {
385992
386267
  finalized = true;
386268
+ },
386269
+ async cancel() {
386270
+ finalized = true;
385993
386271
  }
385994
386272
  };
385995
386273
  }
385996
386274
  if (streamMode === "status_final") {
385997
386275
  return {
385998
386276
  async onThinkingDelta(_delta) {
386277
+ if (finalized)
386278
+ return;
385999
386279
  if (!draftTs) {
386000
386280
  await sendInitial("_Thinking..._");
386001
386281
  }
386002
386282
  },
386003
- async onContentDelta(_delta) {
386283
+ async onContentDelta(delta) {
386284
+ if (finalized)
386285
+ return;
386286
+ lastContent = delta.content;
386004
386287
  if (!draftTs) {
386005
386288
  await sendInitial("_Thinking..._");
386006
386289
  }
@@ -386012,17 +386295,17 @@ function createSlackStreamSender(options) {
386012
386295
  await finalize(`Error: ${delta.error}`);
386013
386296
  },
386014
386297
  async abort() {
386015
- if (draftTs && !finalized) {
386016
- try {
386017
- await client.chat.delete({ channel: channelId, ts: draftTs });
386018
- } catch {}
386019
- }
386020
- finalized = true;
386298
+ await deleteDraft();
386299
+ },
386300
+ async cancel() {
386301
+ await cancelKeepingPartial();
386021
386302
  }
386022
386303
  };
386023
386304
  }
386024
386305
  return {
386025
386306
  async onThinkingDelta(delta) {
386307
+ if (finalized)
386308
+ return;
386026
386309
  const text = `_${delta.thinking}_`;
386027
386310
  if (!draftTs) {
386028
386311
  await sendInitial(text);
@@ -386031,7 +386314,10 @@ function createSlackStreamSender(options) {
386031
386314
  }
386032
386315
  },
386033
386316
  async onContentDelta(delta) {
386317
+ if (finalized)
386318
+ return;
386034
386319
  const text = delta.content;
386320
+ lastContent = text;
386035
386321
  if (!draftTs) {
386036
386322
  await sendInitial(text);
386037
386323
  } else {
@@ -386045,12 +386331,10 @@ function createSlackStreamSender(options) {
386045
386331
  await finalize(`Error: ${delta.error}`);
386046
386332
  },
386047
386333
  async abort() {
386048
- if (draftTs && !finalized) {
386049
- try {
386050
- await client.chat.delete({ channel: channelId, ts: draftTs });
386051
- } catch {}
386052
- }
386053
- finalized = true;
386334
+ await deleteDraft();
386335
+ },
386336
+ async cancel() {
386337
+ await cancelKeepingPartial();
386054
386338
  }
386055
386339
  };
386056
386340
  }
@@ -386142,6 +386426,8 @@ function createNativeStreamSender(options) {
386142
386426
  async onContentDelta(delta) {
386143
386427
  if (fallback)
386144
386428
  return fallback.onContentDelta(delta);
386429
+ if (stopped)
386430
+ return;
386145
386431
  const content = delta.content;
386146
386432
  if (!content)
386147
386433
  return;
@@ -386168,6 +386454,11 @@ function createNativeStreamSender(options) {
386168
386454
  if (fallback)
386169
386455
  return fallback.abort();
386170
386456
  await stopStream();
386457
+ },
386458
+ async cancel() {
386459
+ if (fallback)
386460
+ return fallback.cancel ? fallback.cancel() : fallback.abort();
386461
+ await stopStream();
386171
386462
  }
386172
386463
  };
386173
386464
  }
@@ -386561,6 +386852,10 @@ class SlackPlugin extends BaseChannelPlugin {
386561
386852
  async abort() {
386562
386853
  await base2.abort();
386563
386854
  cleanup();
386855
+ },
386856
+ async cancel() {
386857
+ await (base2.cancel ? base2.cancel() : base2.abort());
386858
+ cleanup();
386564
386859
  }
386565
386860
  };
386566
386861
  }
@@ -386568,29 +386863,43 @@ class SlackPlugin extends BaseChannelPlugin {
386568
386863
  await this.sendPresenceStatus(instanceId, chatId, duration === 0 ? "paused" : "typing", duration);
386569
386864
  }
386570
386865
  async sendPresenceStatus(instanceId, chatId, type, duration, options) {
386571
- const method = "assistant.threads.setStatus";
386866
+ const nominalMethod = "agents.sessions.setStatus";
386572
386867
  const connection = this.connections.get(instanceId);
386573
386868
  if (!connection)
386574
- return { delivered: false, method, reason: "not_connected" };
386869
+ return { delivered: false, method: nominalMethod, reason: "not_connected" };
386575
386870
  const threadTs = options?.threadId ?? this.activeThreads.get(`${instanceId}:${chatId}`);
386576
- if (!threadTs)
386577
- return { delivered: false, method, reason: "no_active_thread" };
386871
+ if (!threadTs) {
386872
+ this.logger.debug("Slack presence status skipped", {
386873
+ instanceId,
386874
+ chatId,
386875
+ type,
386876
+ reason: "no_active_thread"
386877
+ });
386878
+ return { delivered: false, method: nominalMethod, reason: "no_active_thread" };
386879
+ }
386578
386880
  const shouldClear = type === "paused";
386579
386881
  const status = shouldClear ? "" : options?.status ?? (type === "recording" ? "is recording..." : "is typing...");
386580
386882
  const timerKey = this.presenceStatusTimerKey(instanceId, chatId, threadTs);
386581
- const delivered = status === "" ? await clearTypingStatus({
386883
+ const statusResult = status === "" ? await clearTypingStatus({
386582
386884
  client: connection.actingClient,
386583
386885
  channelId: chatId,
386584
386886
  threadTs,
386585
- logger: this.logger
386887
+ logger: this.logger,
386888
+ instanceId
386586
386889
  }) : await setSlackThreadStatus({
386587
386890
  client: connection.actingClient,
386588
386891
  channelId: chatId,
386589
386892
  threadTs,
386590
386893
  status,
386591
386894
  loadingMessages: options?.loadingMessages,
386592
- logger: this.logger
386895
+ logger: this.logger,
386896
+ instanceId
386593
386897
  });
386898
+ const { delivered, method } = statusResult;
386899
+ const usedLegacy = method === "assistant.threads.setStatus";
386900
+ const sessionStatus = shouldClear ? "active" : "processing";
386901
+ const appliedStatus = !delivered || usedLegacy ? status : sessionStatus;
386902
+ const appliedLoadingMessages = !delivered || usedLegacy ? options?.loadingMessages : undefined;
386594
386903
  if (delivered) {
386595
386904
  this.clearPresenceStatusTimer(timerKey);
386596
386905
  }
@@ -386616,12 +386925,18 @@ class SlackPlugin extends BaseChannelPlugin {
386616
386925
  this.presenceStatusTimers.set(timerKey, timer);
386617
386926
  timer.unref?.();
386618
386927
  }
386619
- return delivered ? { delivered: true, method, threadId: threadTs, status, loadingMessages: options?.loadingMessages } : {
386620
- delivered: false,
386928
+ return delivered ? {
386929
+ delivered: true,
386621
386930
  method,
386622
386931
  threadId: threadTs,
386623
- status,
386624
- loadingMessages: options?.loadingMessages,
386932
+ status: appliedStatus,
386933
+ loadingMessages: appliedLoadingMessages
386934
+ } : {
386935
+ delivered: false,
386936
+ method: method ?? nominalMethod,
386937
+ threadId: threadTs,
386938
+ status: appliedStatus,
386939
+ loadingMessages: appliedLoadingMessages,
386625
386940
  reason: "slack_status_failed"
386626
386941
  };
386627
386942
  }
@@ -386942,6 +387257,37 @@ class SlackPlugin extends BaseChannelPlugin {
386942
387257
  break;
386943
387258
  }
386944
387259
  }
387260
+ async handleAgentSessionStopped(instanceId, connection, args) {
387261
+ const parsedEventTs = args.eventTs ? Number.parseFloat(args.eventTs) : Number.NaN;
387262
+ const requestedAt = Number.isFinite(parsedEventTs) ? Math.round(parsedEventTs * 1000) : Date.now();
387263
+ try {
387264
+ await this.eventBus.publish("agent.run.cancel_requested", {
387265
+ instanceId,
387266
+ chatId: args.channelId,
387267
+ threadId: args.threadTs,
387268
+ requestedBy: args.userId,
387269
+ requestedAt,
387270
+ reason: "user_stop"
387271
+ }, {
387272
+ instanceId,
387273
+ channelType: this.id,
387274
+ source: `channel:${this.id}`
387275
+ });
387276
+ } catch (err2) {
387277
+ this.logger.error("Failed to publish agent.run.cancel_requested", {
387278
+ instanceId,
387279
+ chatId: args.channelId,
387280
+ error: String(err2)
387281
+ });
387282
+ }
387283
+ await clearTypingStatus({
387284
+ client: connection.actingClient,
387285
+ channelId: args.channelId,
387286
+ threadTs: args.threadTs ?? this.activeThreads.get(`${instanceId}:${args.channelId}`),
387287
+ logger: this.logger,
387288
+ instanceId
387289
+ });
387290
+ }
386945
387291
  trackActiveThread(instanceId, channelId, threadTs) {
386946
387292
  this.activeThreads.set(`${instanceId}:${channelId}`, threadTs);
386947
387293
  }
@@ -387059,6 +387405,11 @@ class SlackPlugin extends BaseChannelPlugin {
387059
387405
  await this.handleReactionReceived(instId, messageId, chatId, userId, emoji, action);
387060
387406
  }
387061
387407
  }, this.logger);
387408
+ setupAgentSessionHandlers(connection.app, instanceId, {
387409
+ onSessionStopped: async (instId, args) => {
387410
+ await this.handleAgentSessionStopped(instId, connection, args);
387411
+ }
387412
+ }, this.logger);
387062
387413
  setupInteractionHandlers2(connection.app, instanceId, {
387063
387414
  onInteraction: async (_instId, payload) => {
387064
387415
  await this.handleInteraction(payload);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260901.1",
3
+ "version": "2.260901.3",
4
4
  "description": "LLM-optimized CLI for Omni",
5
5
  "type": "module",
6
6
  "bin": {