@automagik/omni 2.260619.3 → 2.260622.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -124960,7 +124960,7 @@ import { fileURLToPath } from "url";
124960
124960
  // package.json
124961
124961
  var package_default = {
124962
124962
  name: "@automagik/omni",
124963
- version: "2.260619.3",
124963
+ version: "2.260622.1",
124964
124964
  description: "LLM-optimized CLI for Omni",
124965
124965
  type: "module",
124966
124966
  bin: {
@@ -225245,7 +225245,7 @@ var init_sentry_scrub = __esm(() => {
225245
225245
  var require_package7 = __commonJS((exports, module) => {
225246
225246
  module.exports = {
225247
225247
  name: "@omni/api",
225248
- version: "2.260619.3",
225248
+ version: "2.260622.1",
225249
225249
  type: "module",
225250
225250
  exports: {
225251
225251
  ".": {
@@ -336856,6 +336856,175 @@ var init_turn_events = __esm(() => {
336856
336856
  sc2 = import_nats5.StringCodec();
336857
336857
  });
336858
336858
 
336859
+ // ../api/src/plugins/agent-dispatch-limiter.ts
336860
+ function parsePositiveInt(env2, key, fallback, logger6) {
336861
+ const raw2 = env2[key];
336862
+ if (raw2 === undefined || raw2 === "")
336863
+ return fallback;
336864
+ const parsed = Number.parseInt(raw2, 10);
336865
+ if (!Number.isFinite(parsed) || parsed <= 0) {
336866
+ logger6?.warn("Invalid agent dispatch limiter env value, using default", { key, value: raw2, fallback });
336867
+ return fallback;
336868
+ }
336869
+ return parsed;
336870
+ }
336871
+ function loadAgentDispatchLimiterConfig(env2 = process.env, logger6) {
336872
+ return {
336873
+ defaultConcurrency: parsePositiveInt(env2, "OMNI_AGENT_DISPATCH_CONCURRENCY_DEFAULT", DEFAULT_AGENT_DISPATCH_CONCURRENCY, logger6),
336874
+ maxQueueDepth: parsePositiveInt(env2, "OMNI_AGENT_DISPATCH_QUEUE_MAX_DEPTH", DEFAULT_AGENT_DISPATCH_QUEUE_MAX_DEPTH, logger6),
336875
+ maxQueueWaitMs: parsePositiveInt(env2, "OMNI_AGENT_DISPATCH_QUEUE_MAX_WAIT_MS", DEFAULT_AGENT_DISPATCH_QUEUE_MAX_WAIT_MS, logger6),
336876
+ perChatConcurrency: parsePositiveInt(env2, "OMNI_AGENT_DISPATCH_PER_CHAT_CONCURRENCY", DEFAULT_AGENT_DISPATCH_PER_CHAT_CONCURRENCY, logger6)
336877
+ };
336878
+ }
336879
+
336880
+ class AgentDispatchLimiter {
336881
+ config;
336882
+ logger;
336883
+ queues = new Map;
336884
+ chatActiveCounts = new Map;
336885
+ constructor(config4, logger6) {
336886
+ this.config = config4;
336887
+ this.logger = logger6;
336888
+ }
336889
+ run(context20, run) {
336890
+ const queue = this.getQueue(context20.instanceId);
336891
+ if (this.canStart(queue, context20)) {
336892
+ return new Promise((resolve2, reject) => {
336893
+ this.startItem(queue, {
336894
+ context: context20,
336895
+ enqueuedAt: Date.now(),
336896
+ run,
336897
+ resolve: resolve2,
336898
+ reject,
336899
+ timeout: null
336900
+ });
336901
+ });
336902
+ }
336903
+ if (queue.pending.length >= this.config.maxQueueDepth) {
336904
+ const snapshot = this.snapshot(queue, context20);
336905
+ this.logger?.warn("agent_dispatch_queue_full", snapshot);
336906
+ return Promise.reject(new AgentDispatchQueueFullError(snapshot));
336907
+ }
336908
+ return new Promise((resolve2, reject) => {
336909
+ const item = {
336910
+ context: context20,
336911
+ enqueuedAt: Date.now(),
336912
+ run,
336913
+ resolve: resolve2,
336914
+ reject,
336915
+ timeout: null
336916
+ };
336917
+ item.timeout = setTimeout(() => {
336918
+ const idx = queue.pending.indexOf(item);
336919
+ if (idx < 0)
336920
+ return;
336921
+ queue.pending.splice(idx, 1);
336922
+ const snapshot = this.snapshot(queue, context20, Date.now() - item.enqueuedAt);
336923
+ this.logger?.warn("agent_dispatch_queue_timeout", snapshot);
336924
+ reject(new AgentDispatchQueueTimeoutError(snapshot));
336925
+ this.drain(queue);
336926
+ }, this.config.maxQueueWaitMs);
336927
+ if (typeof item.timeout === "object" && item.timeout && "unref" in item.timeout) {
336928
+ item.timeout.unref();
336929
+ }
336930
+ queue.pending.push(item);
336931
+ this.logger?.info("agent_dispatch_queue_enqueued", this.snapshot(queue, context20));
336932
+ this.drain(queue);
336933
+ });
336934
+ }
336935
+ getSnapshot(instanceId) {
336936
+ const queue = this.getQueue(instanceId);
336937
+ return {
336938
+ activeCount: queue.activeCount,
336939
+ queueDepth: queue.pending.length,
336940
+ maxConcurrency: this.config.defaultConcurrency,
336941
+ maxQueueDepth: this.config.maxQueueDepth
336942
+ };
336943
+ }
336944
+ getQueue(instanceId) {
336945
+ let queue = this.queues.get(instanceId);
336946
+ if (!queue) {
336947
+ queue = { instanceId, activeCount: 0, pending: [] };
336948
+ this.queues.set(instanceId, queue);
336949
+ }
336950
+ return queue;
336951
+ }
336952
+ canStart(queue, context20) {
336953
+ return queue.activeCount < this.config.defaultConcurrency && (this.chatActiveCounts.get(this.chatKey(context20)) ?? 0) < this.config.perChatConcurrency;
336954
+ }
336955
+ startItem(queue, item) {
336956
+ if (item.timeout) {
336957
+ clearTimeout(item.timeout);
336958
+ item.timeout = null;
336959
+ }
336960
+ const chatKey = this.chatKey(item.context);
336961
+ queue.activeCount += 1;
336962
+ this.chatActiveCounts.set(chatKey, (this.chatActiveCounts.get(chatKey) ?? 0) + 1);
336963
+ const queueWaitMs = Date.now() - item.enqueuedAt;
336964
+ this.logger?.info("agent_dispatch_queue_started", this.snapshot(queue, item.context, queueWaitMs));
336965
+ Promise.resolve().then(item.run).then(item.resolve, item.reject).finally(() => {
336966
+ queue.activeCount = Math.max(0, queue.activeCount - 1);
336967
+ const chatActive = (this.chatActiveCounts.get(chatKey) ?? 1) - 1;
336968
+ if (chatActive > 0) {
336969
+ this.chatActiveCounts.set(chatKey, chatActive);
336970
+ } else {
336971
+ this.chatActiveCounts.delete(chatKey);
336972
+ }
336973
+ this.logger?.info("agent_dispatch_queue_finished", this.snapshot(queue, item.context, Date.now() - item.enqueuedAt));
336974
+ this.drain(queue);
336975
+ });
336976
+ }
336977
+ drain(queue) {
336978
+ let started = true;
336979
+ while (started && queue.activeCount < this.config.defaultConcurrency) {
336980
+ started = false;
336981
+ for (let i = 0;i < queue.pending.length; i += 1) {
336982
+ const item = queue.pending[i];
336983
+ if (!item || !this.canStart(queue, item.context))
336984
+ continue;
336985
+ queue.pending.splice(i, 1);
336986
+ this.startItem(queue, item);
336987
+ started = true;
336988
+ break;
336989
+ }
336990
+ }
336991
+ }
336992
+ snapshot(queue, context20, waitMs) {
336993
+ return {
336994
+ instanceId: context20.instanceId,
336995
+ chatId: context20.chatId,
336996
+ traceId: context20.traceId,
336997
+ activeCount: queue.activeCount,
336998
+ queueDepth: queue.pending.length,
336999
+ maxConcurrency: this.config.defaultConcurrency,
337000
+ maxQueueDepth: this.config.maxQueueDepth,
337001
+ waitMs
337002
+ };
337003
+ }
337004
+ chatKey(context20) {
337005
+ return `${context20.instanceId}:${context20.chatId}`;
337006
+ }
337007
+ }
337008
+ var DEFAULT_AGENT_DISPATCH_CONCURRENCY = 8, DEFAULT_AGENT_DISPATCH_QUEUE_MAX_DEPTH = 100, DEFAULT_AGENT_DISPATCH_QUEUE_MAX_WAIT_MS = 60000, DEFAULT_AGENT_DISPATCH_PER_CHAT_CONCURRENCY = 1, AgentDispatchQueueFullError, AgentDispatchQueueTimeoutError;
337009
+ var init_agent_dispatch_limiter = __esm(() => {
337010
+ AgentDispatchQueueFullError = class AgentDispatchQueueFullError extends Error {
337011
+ snapshot;
337012
+ constructor(snapshot) {
337013
+ super(`Agent dispatch queue full for instance ${snapshot.instanceId}: ${snapshot.queueDepth}/${snapshot.maxQueueDepth} pending`);
337014
+ this.snapshot = snapshot;
337015
+ this.name = "AgentDispatchQueueFullError";
337016
+ }
337017
+ };
337018
+ AgentDispatchQueueTimeoutError = class AgentDispatchQueueTimeoutError extends Error {
337019
+ snapshot;
337020
+ constructor(snapshot) {
337021
+ super(`Agent dispatch queue timed out for instance ${snapshot.instanceId} chat ${snapshot.chatId} after ${snapshot.waitMs ?? 0}ms`);
337022
+ this.snapshot = snapshot;
337023
+ this.name = "AgentDispatchQueueTimeoutError";
337024
+ }
337025
+ };
337026
+ });
337027
+
336859
337028
  // ../api/src/plugins/logger.ts
336860
337029
  function createPluginLogger(module) {
336861
337030
  if (typeof module === "object") {
@@ -339810,17 +339979,23 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
339810
339979
  senderName,
339811
339980
  senderAgentId
339812
339981
  });
339813
- await sendTypingPresence(channel5, instance4.id, chatId, "composing");
339814
339982
  const inst = instance4;
339815
339983
  const agentAckMessage = inst.agentAckMessage ?? null;
339816
- if (agentAckMessage) {
339817
- sendTextMessage5(channel5, instance4.id, chatId, agentAckMessage).catch((err) => {
339818
- log99.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
339819
- });
339820
- }
339821
- const perThreadExtraContext = await resolvePerThreadExtraContext(db2, services, instance4, channel5, chatId, senderId, firstMessage);
339822
339984
  try {
339823
- await runWithTransientDispatchRetry(() => dispatchToAgent(services, instance4, messages4, triggerType, channel5, chatId, senderId, personId, senderName, traceId, senderAgentId, perThreadExtraContext, db2), { instanceId: instance4.id, chatId, traceId });
339985
+ await agentDispatchLimiter.run({ instanceId: instance4.id, chatId, traceId }, async () => {
339986
+ await sendTypingPresence(channel5, instance4.id, chatId, "composing");
339987
+ try {
339988
+ if (agentAckMessage) {
339989
+ sendTextMessage5(channel5, instance4.id, chatId, agentAckMessage).catch((err) => {
339990
+ log99.warn("Failed to send agent ack message", { instanceId: instance4.id, chatId, error: String(err) });
339991
+ });
339992
+ }
339993
+ const perThreadExtraContext = await resolvePerThreadExtraContext(db2, services, instance4, channel5, chatId, senderId, firstMessage);
339994
+ await runWithTransientDispatchRetry(() => dispatchToAgent(services, instance4, messages4, triggerType, channel5, chatId, senderId, personId, senderName, traceId, senderAgentId, perThreadExtraContext, db2), { instanceId: instance4.id, chatId, traceId });
339995
+ } finally {
339996
+ await sendTypingPresence(channel5, instance4.id, chatId, "paused");
339997
+ }
339998
+ });
339824
339999
  } catch (error3) {
339825
340000
  log99.error("agent_dispatch_failed_after_retries", {
339826
340001
  instanceId: instance4.id,
@@ -339831,7 +340006,6 @@ async function processAgentResponse(services, instance4, messages4, triggerType,
339831
340006
  sendErrorFeedback(channel5, instance4.id, chatId, error3).catch(() => {});
339832
340007
  } finally {
339833
340008
  ackHandle.remove();
339834
- await sendTypingPresence(channel5, instance4.id, chatId, "paused");
339835
340009
  }
339836
340010
  }
339837
340011
  function resolveRequiredAgentId(instance4, schemaConfig, providerId, fieldName = "agentId") {
@@ -340956,7 +341130,7 @@ async function setupAgentDispatcher(eventBus, services, db2) {
340956
341130
  log99.info("Agent dispatcher shutdown complete");
340957
341131
  };
340958
341132
  }
340959
- var import_api32, log99, _natsGenieProviderCtor, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, LIFECYCLE_PREVIEW_MAX_CHARS = 160, LIFECYCLE_SENSITIVE_KEY_PARTS, 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, nullFilterWarnedInstances, ACTIVE_OWNER_IDENTIFIER_CACHE_TTL_MS = 1e4, cachedActiveOwnerIdentifiers = null, cachedActiveOwnerIdentifiersAt = 0, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
341133
+ var import_api32, log99, agentDispatchLimiter, _natsGenieProviderCtor, QUOTED_MESSAGE_MAX_CHARS = 4000, DM_HISTORY_LIMIT = 20, LIFECYCLE_PREVIEW_MAX_CHARS = 160, LIFECYCLE_SENSITIVE_KEY_PARTS, 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, nullFilterWarnedInstances, ACTIVE_OWNER_IDENTIFIER_CACHE_TTL_MS = 1e4, cachedActiveOwnerIdentifiers = null, cachedActiveOwnerIdentifiersAt = 0, DEFAULT_GATE_MODEL = "gemini-3-flash-preview", GATE_TIMEOUT_MS = 3000, setupAgentResponder;
340960
341134
  var init_agent_dispatcher = __esm(() => {
340961
341135
  init_src2();
340962
341136
  init_src();
@@ -340968,6 +341142,7 @@ var init_agent_dispatcher = __esm(() => {
340968
341142
  init_sentry_scrub();
340969
341143
  init_agent_runner();
340970
341144
  init_turn_events();
341145
+ init_agent_dispatch_limiter();
340971
341146
  init_loader2();
340972
341147
  init_message_debouncer();
340973
341148
  init_message_persistence();
@@ -340975,6 +341150,7 @@ var init_agent_dispatcher = __esm(() => {
340975
341150
  init_src6();
340976
341151
  import_api32 = __toESM(require_src(), 1);
340977
341152
  log99 = createLogger("agent-dispatcher");
341153
+ agentDispatchLimiter = new AgentDispatchLimiter(loadAgentDispatchLimiterConfig(process.env, log99), log99);
340978
341154
  _natsGenieProviderCtor = NatsGenieProvider;
340979
341155
  LIFECYCLE_SENSITIVE_KEY_PARTS = ["authorization", "bearer", "password", "secret", "token", "api_key", "apikey"];
340980
341156
  TRANSIENT_DISPATCH_ERROR_PATTERNS = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260619.3",
3
+ "version": "2.260622.1",
4
4
  "description": "LLM-optimized CLI for Omni",
5
5
  "type": "module",
6
6
  "bin": {