@automagik/omni 2.260914.9 → 2.260914.11

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.
@@ -0,0 +1,17 @@
1
+ -- Per-automation loop-guard opt-in (issue #1148).
2
+ --
3
+ -- `key.fromMe` is per-observer: with two instances in one WhatsApp group the
4
+ -- bot's own messages journal as fromMe:false on the other instance, so an
5
+ -- automation filtering on it answers itself. Channel events now carry an
6
+ -- observer-independent `senderInstanceId`, and the engine skips events sent
7
+ -- by a same-tenant instance unless the automation opts in:
8
+ --
9
+ -- automations.allow_instance_senders true = act on messages sent by the
10
+ -- tenant's own instances. Default false.
11
+ --
12
+ -- Hand-written following the 0043/0044/0052 precedent (additive, idempotent).
13
+ -- No explicit BEGIN/COMMIT — the boot migrator executes this file on a pooled
14
+ -- postgres-js connection, which rejects raw transaction control.
15
+
16
+ ALTER TABLE "automations"
17
+ ADD COLUMN IF NOT EXISTS "allow_instance_senders" boolean NOT NULL DEFAULT false;
@@ -484,6 +484,13 @@
484
484
  "when": 1786800000000,
485
485
  "tag": "0068_automation_enabled_at",
486
486
  "breakpoints": true
487
+ },
488
+ {
489
+ "idx": 69,
490
+ "version": "7",
491
+ "when": 1786900000000,
492
+ "tag": "0069_automation_allow_instance_senders",
493
+ "breakpoints": true
487
494
  }
488
495
  ]
489
496
  }
package/dist/index.js CHANGED
@@ -41764,6 +41764,8 @@ class AutomationEngine {
41764
41764
  const sortedAutomations = [...matchingAutomations].sort((a, b2) => b2.priority - a.priority);
41765
41765
  try {
41766
41766
  for (const automation of sortedAutomations) {
41767
+ if (this.isInstanceSenderLoop(automation, event))
41768
+ continue;
41767
41769
  if (automation.debounce && automation.debounce.mode !== "none") {
41768
41770
  await this.handleDebounced(automation, event);
41769
41771
  } else {
@@ -41776,6 +41778,17 @@ class AutomationEngine {
41776
41778
  throw err2;
41777
41779
  }
41778
41780
  }
41781
+ isInstanceSenderLoop(automation, event) {
41782
+ const senderInstanceId = event.payload.senderInstanceId;
41783
+ if (typeof senderInstanceId !== "string" || !senderInstanceId || automation.allowInstanceSenders)
41784
+ return false;
41785
+ logger4.debug("Skipping event sent by a same-tenant instance", {
41786
+ automationId: automation.id,
41787
+ eventId: event.id,
41788
+ senderInstanceId
41789
+ });
41790
+ return true;
41791
+ }
41779
41792
  resolveDebounceKey(automation, event, instanceId) {
41780
41793
  const payload = event.payload;
41781
41794
  const template = automation.debounce?.key;
@@ -83210,6 +83223,7 @@ var init_schema2 = __esm(() => {
83210
83223
  enabled: boolean2("enabled").notNull().default(true),
83211
83224
  priority: integer("priority").notNull().default(0),
83212
83225
  transactionalEmissions: boolean2("transactional_emissions").notNull().default(false),
83226
+ allowInstanceSenders: boolean2("allow_instance_senders").notNull().default(false),
83213
83227
  maxConcurrency: integer("max_concurrency"),
83214
83228
  concurrencyKey: text("concurrency_key"),
83215
83229
  enabledAt: timestamp("enabled_at", { withTimezone: true }),
@@ -137252,7 +137266,7 @@ import { fileURLToPath } from "url";
137252
137266
  // package.json
137253
137267
  var package_default = {
137254
137268
  name: "@automagik/omni",
137255
- version: "2.260914.9",
137269
+ version: "2.260914.11",
137256
137270
  repository: {
137257
137271
  type: "git",
137258
137272
  url: "git+https://github.com/automagik-dev/omni.git",
@@ -38668,6 +38668,8 @@ class AutomationEngine {
38668
38668
  const sortedAutomations = [...matchingAutomations].sort((a, b2) => b2.priority - a.priority);
38669
38669
  try {
38670
38670
  for (const automation of sortedAutomations) {
38671
+ if (this.isInstanceSenderLoop(automation, event))
38672
+ continue;
38671
38673
  if (automation.debounce && automation.debounce.mode !== "none") {
38672
38674
  await this.handleDebounced(automation, event);
38673
38675
  } else {
@@ -38680,6 +38682,17 @@ class AutomationEngine {
38680
38682
  throw err2;
38681
38683
  }
38682
38684
  }
38685
+ isInstanceSenderLoop(automation, event) {
38686
+ const senderInstanceId = event.payload.senderInstanceId;
38687
+ if (typeof senderInstanceId !== "string" || !senderInstanceId || automation.allowInstanceSenders)
38688
+ return false;
38689
+ logger4.debug("Skipping event sent by a same-tenant instance", {
38690
+ automationId: automation.id,
38691
+ eventId: event.id,
38692
+ senderInstanceId
38693
+ });
38694
+ return true;
38695
+ }
38683
38696
  resolveDebounceKey(automation, event, instanceId) {
38684
38697
  const payload = event.payload;
38685
38698
  const template = automation.debounce?.key;
@@ -173697,6 +173710,7 @@ var init_schema2 = __esm(() => {
173697
173710
  enabled: boolean2("enabled").notNull().default(true),
173698
173711
  priority: integer("priority").notNull().default(0),
173699
173712
  transactionalEmissions: boolean2("transactional_emissions").notNull().default(false),
173713
+ allowInstanceSenders: boolean2("allow_instance_senders").notNull().default(false),
173700
173714
  maxConcurrency: integer("max_concurrency"),
173701
173715
  concurrencyKey: text("concurrency_key"),
173702
173716
  enabledAt: timestamp("enabled_at", { withTimezone: true }),
@@ -196158,7 +196172,7 @@ function shouldIgnoreSpansForIncomingRequest(request, {
196158
196172
  ignoreStaticAssets,
196159
196173
  ignoreIncomingRequests
196160
196174
  }) {
196161
- if (import_core68.isTracingSuppressed(import_api7.context.active())) {
196175
+ if (import_core69.isTracingSuppressed(import_api7.context.active())) {
196162
196176
  return true;
196163
196177
  }
196164
196178
  const urlPath = request.url;
@@ -196210,7 +196224,7 @@ function getIncomingRequestAttributesOnResponse(request, response) {
196210
196224
  [import_semantic_conventions.SEMATTRS_HTTP_STATUS_CODE]: statusCode,
196211
196225
  "http.status_text": statusMessage?.toUpperCase()
196212
196226
  };
196213
- const rpcMetadata = import_core68.getRPCMetadata(import_api7.context.active());
196227
+ const rpcMetadata = import_core69.getRPCMetadata(import_api7.context.active());
196214
196228
  if (socket) {
196215
196229
  const { localAddress, localPort, remoteAddress, remotePort } = socket;
196216
196230
  newAttributes[import_semantic_conventions.SEMATTRS_NET_HOST_IP] = localAddress;
@@ -196220,7 +196234,7 @@ function getIncomingRequestAttributesOnResponse(request, response) {
196220
196234
  }
196221
196235
  newAttributes[import_semantic_conventions.SEMATTRS_HTTP_STATUS_CODE] = statusCode;
196222
196236
  newAttributes["http.status_text"] = (statusMessage || "").toUpperCase();
196223
- if (rpcMetadata?.type === import_core68.RPCType.HTTP && rpcMetadata.route !== undefined) {
196237
+ if (rpcMetadata?.type === import_core69.RPCType.HTTP && rpcMetadata.route !== undefined) {
196224
196238
  const routeName = rpcMetadata.route;
196225
196239
  newAttributes[import_semantic_conventions.ATTR_HTTP_ROUTE] = routeName;
196226
196240
  }
@@ -196235,7 +196249,7 @@ function shouldFilterStatusCode(statusCode, dropForStatusCodes) {
196235
196249
  return statusCode >= min && statusCode <= max;
196236
196250
  });
196237
196251
  }
196238
- var import_api7, import_core68, import_semantic_conventions, INTEGRATION_NAME8 = "Http.ServerSpans", _httpServerSpansIntegration = (options = {}) => {
196252
+ var import_api7, import_core69, import_semantic_conventions, INTEGRATION_NAME8 = "Http.ServerSpans", _httpServerSpansIntegration = (options = {}) => {
196239
196253
  const ignoreStaticAssets = options.ignoreStaticAssets ?? true;
196240
196254
  const ignoreIncomingRequests = options.ignoreIncomingRequests;
196241
196255
  const ignoreStatusCodes = options.ignoreStatusCodes ?? [
@@ -196300,10 +196314,10 @@ var import_api7, import_core68, import_semantic_conventions, INTEGRATION_NAME8 =
196300
196314
  applyCustomAttributesOnSpan?.(span, request, response);
196301
196315
  onSpanCreated?.(span, request, response);
196302
196316
  const rpcMetadata = {
196303
- type: import_core68.RPCType.HTTP,
196317
+ type: import_core69.RPCType.HTTP,
196304
196318
  span
196305
196319
  };
196306
- return import_api7.context.with(import_core68.setRPCMetadata(import_api7.trace.setSpan(import_api7.context.active(), span), rpcMetadata), () => {
196320
+ return import_api7.context.with(import_core69.setRPCMetadata(import_api7.trace.setSpan(import_api7.context.active(), span), rpcMetadata), () => {
196307
196321
  import_api7.context.bind(import_api7.context.active(), request);
196308
196322
  import_api7.context.bind(import_api7.context.active(), response);
196309
196323
  let isEnded = false;
@@ -196365,7 +196379,7 @@ var init_httpServerSpansIntegration = __esm(() => {
196365
196379
  init_debug_build2();
196366
196380
  init_httpServerIntegration();
196367
196381
  import_api7 = __toESM(require_src(), 1);
196368
- import_core68 = __toESM(require_src6(), 1);
196382
+ import_core69 = __toESM(require_src6(), 1);
196369
196383
  import_semantic_conventions = __toESM(require_src5(), 1);
196370
196384
  httpServerSpansIntegration = _httpServerSpansIntegration;
196371
196385
  });
@@ -198199,13 +198213,13 @@ import { subscribe as subscribe2 } from "diagnostics_channel";
198199
198213
  import { errorMonitor as errorMonitor2 } from "events";
198200
198214
  import * as http from "http";
198201
198215
  import * as https from "https";
198202
- var import_api8, import_core71, import_instrumentation, FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL, SentryHttpInstrumentation;
198216
+ var import_api8, import_core72, import_instrumentation, FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL, SentryHttpInstrumentation;
198203
198217
  var init_SentryHttpInstrumentation = __esm(() => {
198204
198218
  init_esm2();
198205
198219
  init_constants10();
198206
198220
  init_nodeVersion();
198207
198221
  import_api8 = __toESM(require_src(), 1);
198208
- import_core71 = __toESM(require_src6(), 1);
198222
+ import_core72 = __toESM(require_src6(), 1);
198209
198223
  import_instrumentation = __toESM(require_src8(), 1);
198210
198224
  FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL = NODE_VERSION.major === 22 && NODE_VERSION.minor >= 12 || NODE_VERSION.major === 23 && NODE_VERSION.minor >= 2 || NODE_VERSION.major >= 24;
198211
198225
  SentryHttpInstrumentation = class SentryHttpInstrumentation extends import_instrumentation.InstrumentationBase {
@@ -198220,7 +198234,7 @@ var init_SentryHttpInstrumentation = __esm(() => {
198220
198234
  ...options,
198221
198235
  spans: options.createSpansForOutgoingRequests && (options.spans ?? true),
198222
198236
  ignoreOutgoingRequests(url, request) {
198223
- return import_core71.isTracingSuppressed(import_api8.context.active()) || !!options.ignoreOutgoingRequests?.(url, getRequestOptions(request));
198237
+ return import_core72.isTracingSuppressed(import_api8.context.active()) || !!options.ignoreOutgoingRequests?.(url, getRequestOptions(request));
198224
198238
  },
198225
198239
  outgoingRequestHook(span, request) {
198226
198240
  options.outgoingRequestHook?.(span, request);
@@ -198440,13 +198454,13 @@ var init_outgoingFetchRequest = __esm(() => {
198440
198454
 
198441
198455
  // ../../node_modules/.bun/@sentry+node-core@10.52.0+2c50d7e904f6cfd7/node_modules/@sentry/node-core/build/esm/integrations/node-fetch/SentryNodeFetchInstrumentation.js
198442
198456
  import * as diagch from "diagnostics_channel";
198443
- var import_api9, import_core74, import_instrumentation2, SentryNodeFetchInstrumentation;
198457
+ var import_api9, import_core75, import_instrumentation2, SentryNodeFetchInstrumentation;
198444
198458
  var init_SentryNodeFetchInstrumentation = __esm(() => {
198445
198459
  init_esm2();
198446
198460
  init_nodeVersion();
198447
198461
  init_outgoingFetchRequest();
198448
198462
  import_api9 = __toESM(require_src(), 1);
198449
- import_core74 = __toESM(require_src6(), 1);
198463
+ import_core75 = __toESM(require_src6(), 1);
198450
198464
  import_instrumentation2 = __toESM(require_src8(), 1);
198451
198465
  SentryNodeFetchInstrumentation = class SentryNodeFetchInstrumentation extends import_instrumentation2.InstrumentationBase {
198452
198466
  constructor(config2 = {}) {
@@ -198517,7 +198531,7 @@ var init_SentryNodeFetchInstrumentation = __esm(() => {
198517
198531
  });
198518
198532
  }
198519
198533
  _shouldIgnoreOutgoingRequest(request) {
198520
- if (import_core74.isTracingSuppressed(import_api9.context.active())) {
198534
+ if (import_core75.isTracingSuppressed(import_api9.context.active())) {
198521
198535
  return true;
198522
198536
  }
198523
198537
  const url = getAbsoluteUrl2(request.origin, request.path);
@@ -200877,7 +200891,7 @@ function makeTraceState({
200877
200891
  sampled
200878
200892
  }) {
200879
200893
  const dscString = dsc ? dynamicSamplingContextToSentryBaggageHeader(dsc) : undefined;
200880
- const traceStateBase = new import_core77.TraceState;
200894
+ const traceStateBase = new import_core78.TraceState;
200881
200895
  const traceStateWithDsc = dscString ? traceStateBase.set(SENTRY_TRACE_STATE_DSC, dscString) : traceStateBase;
200882
200896
  return sampled === false ? traceStateWithDsc.set(SENTRY_TRACE_STATE_SAMPLED_NOT_RECORDING, "1") : traceStateWithDsc;
200883
200897
  }
@@ -201001,13 +201015,13 @@ function _startSpan(options, callback, autoEnd) {
201001
201015
  return wrapper(() => {
201002
201016
  const activeCtx = getContext(options.scope, options.forceTransaction);
201003
201017
  const missingRequiredParent = options.onlyIfParent && !import_api10.trace.getSpan(activeCtx);
201004
- const ctx = missingRequiredParent ? import_core77.suppressTracing(activeCtx) : activeCtx;
201018
+ const ctx = missingRequiredParent ? import_core78.suppressTracing(activeCtx) : activeCtx;
201005
201019
  if (missingRequiredParent) {
201006
201020
  getClient()?.recordDroppedEvent("no_parent_span", "span");
201007
201021
  }
201008
201022
  const spanOptions = getSpanOptions(options);
201009
201023
  if (!hasSpansEnabled()) {
201010
- const suppressedCtx = import_core77.isTracingSuppressed(ctx) ? ctx : import_core77.suppressTracing(ctx);
201024
+ const suppressedCtx = import_core78.isTracingSuppressed(ctx) ? ctx : import_core78.suppressTracing(ctx);
201011
201025
  return import_api10.context.with(suppressedCtx, () => {
201012
201026
  return tracer2.startActiveSpan(name, spanOptions, suppressedCtx, (span) => {
201013
201027
  patchSpanEnd(span);
@@ -201044,13 +201058,13 @@ function startInactiveSpan2(options) {
201044
201058
  return wrapper(() => {
201045
201059
  const activeCtx = getContext(options.scope, options.forceTransaction);
201046
201060
  const missingRequiredParent = options.onlyIfParent && !import_api10.trace.getSpan(activeCtx);
201047
- let ctx = missingRequiredParent ? import_core77.suppressTracing(activeCtx) : activeCtx;
201061
+ let ctx = missingRequiredParent ? import_core78.suppressTracing(activeCtx) : activeCtx;
201048
201062
  if (missingRequiredParent) {
201049
201063
  getClient()?.recordDroppedEvent("no_parent_span", "span");
201050
201064
  }
201051
201065
  const spanOptions = getSpanOptions(options);
201052
201066
  if (!hasSpansEnabled()) {
201053
- ctx = import_core77.isTracingSuppressed(ctx) ? ctx : import_core77.suppressTracing(ctx);
201067
+ ctx = import_core78.isTracingSuppressed(ctx) ? ctx : import_core78.suppressTracing(ctx);
201054
201068
  }
201055
201069
  const span = tracer2.startSpan(name, spanOptions, ctx);
201056
201070
  patchSpanEnd(span);
@@ -201159,7 +201173,7 @@ function getActiveSpanWrapper2(parentSpan) {
201159
201173
  } : (callback) => callback();
201160
201174
  }
201161
201175
  function suppressTracing2(callback) {
201162
- const ctx = import_core77.suppressTracing(import_api10.context.active());
201176
+ const ctx = import_core78.suppressTracing(import_api10.context.active());
201163
201177
  return import_api10.context.with(ctx, callback);
201164
201178
  }
201165
201179
  function setupEventContextTrace(client) {
@@ -201846,7 +201860,7 @@ function wrapSamplingDecision({
201846
201860
  function getBaseTraceState(context8, spanAttributes) {
201847
201861
  const parentSpan = import_api10.trace.getSpan(context8);
201848
201862
  const parentContext = parentSpan?.spanContext();
201849
- let traceState = parentContext?.traceState || new import_core77.TraceState;
201863
+ let traceState = parentContext?.traceState || new import_core78.TraceState;
201850
201864
  const url = spanAttributes[import_semantic_conventions2.SEMATTRS_HTTP_URL] || spanAttributes[import_semantic_conventions2.ATTR_URL_FULL];
201851
201865
  if (url && typeof url === "string") {
201852
201866
  traceState = traceState.set(SENTRY_TRACE_STATE_URL, url);
@@ -201907,12 +201921,12 @@ function getSentryResource(serviceNameFallback) {
201907
201921
  ...otelResourceAttrs,
201908
201922
  ...otelServiceName ? { [import_semantic_conventions2.ATTR_SERVICE_NAME]: otelServiceName } : {},
201909
201923
  [import_semantic_conventions2.ATTR_SERVICE_VERSION]: SDK_VERSION,
201910
- [import_semantic_conventions2.ATTR_TELEMETRY_SDK_LANGUAGE]: import_core77.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_LANGUAGE],
201911
- [import_semantic_conventions2.ATTR_TELEMETRY_SDK_NAME]: import_core77.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_NAME],
201912
- [import_semantic_conventions2.ATTR_TELEMETRY_SDK_VERSION]: import_core77.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_VERSION]
201924
+ [import_semantic_conventions2.ATTR_TELEMETRY_SDK_LANGUAGE]: import_core78.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_LANGUAGE],
201925
+ [import_semantic_conventions2.ATTR_TELEMETRY_SDK_NAME]: import_core78.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_NAME],
201926
+ [import_semantic_conventions2.ATTR_TELEMETRY_SDK_VERSION]: import_core78.SDK_INFO[import_semantic_conventions2.ATTR_TELEMETRY_SDK_VERSION]
201913
201927
  });
201914
201928
  }
201915
- var api, import_api10, import_semantic_conventions2, import_core77, import_sdk_trace_base, SEMANTIC_ATTRIBUTE_SENTRY_PARENT_IS_REMOTE = "sentry.parentIsRemote", SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION = "sentry.graphql.operation", SENTRY_TRACE_HEADER2 = "sentry-trace", SENTRY_BAGGAGE_HEADER2 = "baggage", SENTRY_TRACE_STATE_DSC = "sentry.dsc", SENTRY_TRACE_STATE_SAMPLED_NOT_RECORDING = "sentry.sampled_not_recording", SENTRY_TRACE_STATE_URL = "sentry.url", SENTRY_TRACE_STATE_SAMPLE_RAND = "sentry.sample_rand", SENTRY_TRACE_STATE_SAMPLE_RATE = "sentry.sample_rate", SENTRY_TRACE_STATE_CHILD_IGNORED = "sentry.ignored", SENTRY_TRACE_STATE_SEGMENT_IGNORED = "sentry.segment_ignored", SENTRY_SCOPES_CONTEXT_KEY, SENTRY_FORK_ISOLATION_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_ISOLATION_SCOPE_CONTEXT_KEY, SCOPE_CONTEXT_FIELD = "_scopeContext", setupElements, SentryPropagator, canonicalGrpcErrorCodesMap, isStatusErrorMessageValid = (message2) => {
201929
+ var api, import_api10, import_semantic_conventions2, import_core78, import_sdk_trace_base, SEMANTIC_ATTRIBUTE_SENTRY_PARENT_IS_REMOTE = "sentry.parentIsRemote", SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION = "sentry.graphql.operation", SENTRY_TRACE_HEADER2 = "sentry-trace", SENTRY_BAGGAGE_HEADER2 = "baggage", SENTRY_TRACE_STATE_DSC = "sentry.dsc", SENTRY_TRACE_STATE_SAMPLED_NOT_RECORDING = "sentry.sampled_not_recording", SENTRY_TRACE_STATE_URL = "sentry.url", SENTRY_TRACE_STATE_SAMPLE_RAND = "sentry.sample_rand", SENTRY_TRACE_STATE_SAMPLE_RATE = "sentry.sample_rate", SENTRY_TRACE_STATE_CHILD_IGNORED = "sentry.ignored", SENTRY_TRACE_STATE_SEGMENT_IGNORED = "sentry.segment_ignored", SENTRY_SCOPES_CONTEXT_KEY, SENTRY_FORK_ISOLATION_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_ISOLATION_SCOPE_CONTEXT_KEY, SCOPE_CONTEXT_FIELD = "_scopeContext", setupElements, SentryPropagator, canonicalGrpcErrorCodesMap, isStatusErrorMessageValid = (message2) => {
201916
201930
  return Object.values(canonicalGrpcErrorCodesMap).includes(message2);
201917
201931
  }, MAX_SPAN_COUNT2 = 1000, DEFAULT_TIMEOUT = 300;
201918
201932
  var init_resource_Bhpm2sLf = __esm(() => {
@@ -201921,21 +201935,21 @@ var init_resource_Bhpm2sLf = __esm(() => {
201921
201935
  api = __toESM(require_src(), 1);
201922
201936
  import_api10 = __toESM(require_src(), 1);
201923
201937
  import_semantic_conventions2 = __toESM(require_src5(), 1);
201924
- import_core77 = __toESM(require_src6(), 1);
201938
+ import_core78 = __toESM(require_src6(), 1);
201925
201939
  import_sdk_trace_base = __toESM(require_src10(), 1);
201926
201940
  SENTRY_SCOPES_CONTEXT_KEY = import_api10.createContextKey("sentry_scopes");
201927
201941
  SENTRY_FORK_ISOLATION_SCOPE_CONTEXT_KEY = import_api10.createContextKey("sentry_fork_isolation_scope");
201928
201942
  SENTRY_FORK_SET_SCOPE_CONTEXT_KEY = import_api10.createContextKey("sentry_fork_set_scope");
201929
201943
  SENTRY_FORK_SET_ISOLATION_SCOPE_CONTEXT_KEY = import_api10.createContextKey("sentry_fork_set_isolation_scope");
201930
201944
  setupElements = new Set;
201931
- SentryPropagator = class SentryPropagator extends import_core77.W3CBaggagePropagator {
201945
+ SentryPropagator = class SentryPropagator extends import_core78.W3CBaggagePropagator {
201932
201946
  constructor() {
201933
201947
  super();
201934
201948
  setIsSetup("SentryPropagator");
201935
201949
  this._urlMatchesTargetsMap = new LRUMap(100);
201936
201950
  }
201937
201951
  inject(context8, carrier, setter) {
201938
- if (import_core77.isTracingSuppressed(context8)) {
201952
+ if (import_core78.isTracingSuppressed(context8)) {
201939
201953
  DEBUG_BUILD3 && debug32.log("[Tracing] Not injecting trace data for url because tracing is suppressed.");
201940
201954
  return;
201941
201955
  }
@@ -204784,12 +204798,12 @@ var init_http3 = __esm(() => {
204784
204798
  // ../../node_modules/.bun/@sentry+node@10.52.0+779e4caf6ead3695/node_modules/@sentry/node/build/esm/integrations/node-fetch/vendored/undici.js
204785
204799
  import * as diagch2 from "diagnostics_channel";
204786
204800
  import { URL as URL4 } from "url";
204787
- var import_instrumentation5, import_api15, import_core106, import_semantic_conventions3, PACKAGE_NAME = "@sentry/instrumentation-undici", UndiciInstrumentation;
204801
+ var import_instrumentation5, import_api15, import_core107, import_semantic_conventions3, PACKAGE_NAME = "@sentry/instrumentation-undici", UndiciInstrumentation;
204788
204802
  var init_undici = __esm(() => {
204789
204803
  init_esm2();
204790
204804
  import_instrumentation5 = __toESM(require_src8(), 1);
204791
204805
  import_api15 = __toESM(require_src(), 1);
204792
- import_core106 = __toESM(require_src6(), 1);
204806
+ import_core107 = __toESM(require_src6(), 1);
204793
204807
  import_semantic_conventions3 = __toESM(require_src5(), 1);
204794
204808
  UndiciInstrumentation = class UndiciInstrumentation extends import_instrumentation5.InstrumentationBase {
204795
204809
  __init() {
@@ -204888,7 +204902,7 @@ var init_undici = __esm(() => {
204888
204902
  if (shouldIgnoreReq) {
204889
204903
  return;
204890
204904
  }
204891
- const startTime = import_core106.hrTime();
204905
+ const startTime = import_core107.hrTime();
204892
204906
  let requestUrl;
204893
204907
  try {
204894
204908
  requestUrl = new URL4(request2.path, request2.origin);
@@ -205061,7 +205075,7 @@ var init_undici = __esm(() => {
205061
205075
  metricsAttributes[key] = attributes[key];
205062
205076
  }
205063
205077
  });
205064
- const durationSeconds = import_core106.hrTimeToMilliseconds(import_core106.hrTimeDuration(startTime, import_core106.hrTime())) / 1000;
205078
+ const durationSeconds = import_core107.hrTimeToMilliseconds(import_core107.hrTimeDuration(startTime, import_core107.hrTime())) / 1000;
205065
205079
  this._httpClientDurationHistogram.record(durationSeconds, metricsAttributes);
205066
205080
  }
205067
205081
  getRequestMethod(original) {
@@ -205606,7 +205620,7 @@ var init_debug_build3 = __esm(() => {
205606
205620
  });
205607
205621
 
205608
205622
  // ../../node_modules/.bun/@sentry+node@10.52.0+779e4caf6ead3695/node_modules/@sentry/node/build/esm/integrations/tracing/express.js
205609
- var import_instrumentation6, import_api16, import_core109, INTEGRATION_NAME23 = "Express", SUPPORTED_VERSIONS, instrumentExpress, ExpressInstrumentation, _expressIntegration = (options) => {
205623
+ var import_instrumentation6, import_api16, import_core110, INTEGRATION_NAME23 = "Express", SUPPORTED_VERSIONS, instrumentExpress, ExpressInstrumentation, _expressIntegration = (options) => {
205610
205624
  return {
205611
205625
  name: INTEGRATION_NAME23,
205612
205626
  setupOnce() {
@@ -205620,7 +205634,7 @@ var init_express2 = __esm(() => {
205620
205634
  init_debug_build3();
205621
205635
  import_instrumentation6 = __toESM(require_src8(), 1);
205622
205636
  import_api16 = __toESM(require_src(), 1);
205623
- import_core109 = __toESM(require_src6(), 1);
205637
+ import_core110 = __toESM(require_src6(), 1);
205624
205638
  SUPPORTED_VERSIONS = [">=4.0.0 <6"];
205625
205639
  instrumentExpress = generateInstrumentOnce(INTEGRATION_NAME23, (options) => new ExpressInstrumentation(options));
205626
205640
  ExpressInstrumentation = class ExpressInstrumentation extends import_instrumentation6.InstrumentationBase {
@@ -205633,8 +205647,8 @@ var init_express2 = __esm(() => {
205633
205647
  patchExpressModule(express, () => ({
205634
205648
  ...this.getConfig(),
205635
205649
  onRouteResolved(route) {
205636
- const rpcMetadata = import_core109.getRPCMetadata(import_api16.context.active());
205637
- if (route && rpcMetadata?.type === import_core109.RPCType.HTTP) {
205650
+ const rpcMetadata = import_core110.getRPCMetadata(import_api16.context.active());
205651
+ if (route && rpcMetadata?.type === import_core110.RPCType.HTTP) {
205638
205652
  rpcMetadata.route = route;
205639
205653
  }
205640
205654
  }
@@ -209530,13 +209544,13 @@ function addFastifyV3SpanAttributes(span) {
209530
209544
  span.updateName(updatedName);
209531
209545
  }
209532
209546
  }
209533
- var import_api18, import_core111, import_instrumentation7, import_semantic_conventions4, PACKAGE_VERSION = "0.1.0", PACKAGE_NAME2 = "@sentry/instrumentation-fastify-v3", ANONYMOUS_NAME = "anonymous", hooksNamesToWrap, FastifyInstrumentationV3;
209547
+ var import_api18, import_core112, import_instrumentation7, import_semantic_conventions4, PACKAGE_VERSION = "0.1.0", PACKAGE_NAME2 = "@sentry/instrumentation-fastify-v3", ANONYMOUS_NAME = "anonymous", hooksNamesToWrap, FastifyInstrumentationV3;
209534
209548
  var init_instrumentation = __esm(() => {
209535
209549
  init_esm2();
209536
209550
  init_AttributeNames();
209537
209551
  init_utils14();
209538
209552
  import_api18 = __toESM(require_src(), 1);
209539
- import_core111 = __toESM(require_src6(), 1);
209553
+ import_core112 = __toESM(require_src6(), 1);
209540
209554
  import_instrumentation7 = __toESM(require_src8(), 1);
209541
209555
  import_semantic_conventions4 = __toESM(require_src5(), 1);
209542
209556
  hooksNamesToWrap = new Set([
@@ -209569,9 +209583,9 @@ var init_instrumentation = __esm(() => {
209569
209583
  }
209570
209584
  instrumentation._wrap(reply, "send", instrumentation._patchSend());
209571
209585
  const anyRequest = request2;
209572
- const rpcMetadata = import_core111.getRPCMetadata(import_api18.context.active());
209586
+ const rpcMetadata = import_core112.getRPCMetadata(import_api18.context.active());
209573
209587
  const routeName = anyRequest.routeOptions ? anyRequest.routeOptions.url : request2.routerPath;
209574
- if (routeName && rpcMetadata?.type === import_core111.RPCType.HTTP) {
209588
+ if (routeName && rpcMetadata?.type === import_core112.RPCType.HTTP) {
209575
209589
  rpcMetadata.route = routeName;
209576
209590
  }
209577
209591
  const method = request2.method || "GET";
@@ -250946,7 +250960,7 @@ var init_sentry_scrub = __esm(() => {
250946
250960
  var require_package7 = __commonJS((exports, module) => {
250947
250961
  module.exports = {
250948
250962
  name: "@omni/api",
250949
- version: "2.260914.9",
250963
+ version: "2.260914.11",
250950
250964
  private: true,
250951
250965
  type: "module",
250952
250966
  exports: {
@@ -378778,6 +378792,9 @@ var init_automations3 = __esm(() => {
378778
378792
  transactionalEmissions: exports_external.boolean().openapi({
378779
378793
  description: "Transactional publication (G5, #988): buffer the run's emit_event publishes and flush them in order " + "only when every action succeeded; a failed run publishes zero"
378780
378794
  }),
378795
+ allowInstanceSenders: exports_external.boolean().openapi({
378796
+ description: "Loop guard opt-in (#1148): act on events sent by one of the tenant\u2019s own instances"
378797
+ }),
378781
378798
  maxConcurrency: exports_external.number().int().nullable().openapi({
378782
378799
  description: "Per-automation concurrency limit (#1108). null = queued per instance with the engine default; " + "set = a queue private to this automation, 1 being strict single-flight"
378783
378800
  }),
@@ -378803,6 +378820,9 @@ var init_automations3 = __esm(() => {
378803
378820
  transactionalEmissions: exports_external.boolean().default(false).openapi({
378804
378821
  description: "Transactional publication (G5, #988): buffer the run's emit_event publishes and flush them in order " + "only when every action succeeded; a failed run publishes zero. Default false = immediate publishing"
378805
378822
  }),
378823
+ allowInstanceSenders: exports_external.boolean().default(false).openapi({
378824
+ description: "Loop guard opt-in (#1148): by default events sent by one of the tenant\u2019s own instances " + "(payload.senderInstanceId) are skipped. True = act on them anyway"
378825
+ }),
378806
378826
  maxConcurrency: exports_external.number().int().min(1).nullable().optional().openapi({
378807
378827
  description: "Per-automation concurrency limit (#1108). Omit/null = today\u2019s per-instance queueing with the engine " + "default; 1 = strict single-flight, which is what a read-before-write action needs"
378808
378828
  }),
@@ -384671,6 +384691,7 @@ var init_automations4 = __esm(() => {
384671
384691
  enabled: exports_external.boolean().default(true).describe("Whether automation is enabled"),
384672
384692
  priority: exports_external.number().int().default(0).describe("Priority (higher runs first)"),
384673
384693
  transactionalEmissions: exports_external.boolean().default(false).describe("Transactional publication (G5, #988): buffer the run's emit_event publishes and flush them in order " + "only when every action succeeded; a failed run publishes zero. Default false = immediate publishing"),
384694
+ allowInstanceSenders: exports_external.boolean().default(false).describe("Loop guard opt-in (#1148): by default events sent by one of the tenant\u2019s own instances " + "(payload.senderInstanceId) are skipped. True = act on them anyway"),
384674
384695
  maxConcurrency: exports_external.number().int().min(1).nullable().optional().describe("Per-automation concurrency limit (#1108). Omit/null = today\u2019s per-instance queueing with the engine " + "default; 1 = strict single-flight, which is what a read-before-write action needs"),
384675
384696
  concurrencyKey: exports_external.string().min(1).nullable().optional().describe("Template over the event payload partitioning this automation\u2019s queue (#1108), e.g. " + '"{{payload.from.id}}" to serialize per chat; omit/null = one queue for the whole automation')
384676
384697
  });
@@ -415552,6 +415573,7 @@ var src_default8 = plugin9;
415552
415573
 
415553
415574
  // ../channel-whatsapp/src/plugin.ts
415554
415575
  init_src2();
415576
+ init_src();
415555
415577
 
415556
415578
  // ../channel-whatsapp/src/auth.ts
415557
415579
  init_src();
@@ -530001,6 +530023,23 @@ class WhatsAppPlugin extends BaseChannelPlugin {
530001
530023
  getLidMappingCache(instanceId) {
530002
530024
  return this.lidMappingCache.get(instanceId) ?? new Map;
530003
530025
  }
530026
+ resolveSenderInstanceId(instanceId, from, isFromMe2) {
530027
+ if (isFromMe2)
530028
+ return instanceId;
530029
+ const bare = (jid) => jid?.replace(/:.*$/, "").replace(/@.*$/, "") || undefined;
530030
+ const lidCache = this.getLidMappingCache(instanceId);
530031
+ const fromJid2 = from.includes("@") ? from : undefined;
530032
+ const candidates = new Set([bare(from), bare(fromJid2 && lidCache.get(fromJid2))].filter(Boolean));
530033
+ const tenantId = resolveInstanceOwnerTenantId(instanceId);
530034
+ for (const [otherId, sock] of this.sockets) {
530035
+ const user = sock.user;
530036
+ if (!user || resolveInstanceOwnerTenantId(otherId) !== tenantId)
530037
+ continue;
530038
+ if (candidates.has(bare(user.id)) || candidates.has(bare(user.lid)))
530039
+ return otherId;
530040
+ }
530041
+ return;
530042
+ }
530004
530043
  isMentioningOwner(mentionedJids, ownerJid, lidCache) {
530005
530044
  const ownerPhone = ownerJid.replace(/:.*$/, "").replace(/@.*$/, "");
530006
530045
  return mentionedJids.some((jid) => {
@@ -531674,6 +531713,7 @@ class WhatsAppPlugin extends BaseChannelPlugin {
531674
531713
  mimeType: content.mimeType
531675
531714
  },
531676
531715
  replyToId,
531716
+ senderInstanceId: this.resolveSenderInstanceId(instanceId, from, isFromMe2),
531677
531717
  rawPayload: extendedPayload,
531678
531718
  timings
531679
531719
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260914.9",
3
+ "version": "2.260914.11",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/automagik-dev/omni.git",