@automagik/omni 2.260906.3 → 2.260906.4

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,24 @@
1
+ -- causationId in the persisted event journal (#957, RFC #925 G3 feature half).
2
+ --
3
+ -- `metadata->correlationId` groups a flow (the bag of events); `causation_id`
4
+ -- gives the tree — the id of the IMMEDIATE parent event whose consumption
5
+ -- caused this one to be published. NULL for root events (external ingress
6
+ -- mints a fresh correlation, no parent) and for every pre-existing row
7
+ -- (forward-only: the ~349k historical journal events have no derivable
8
+ -- parent, no backfill). Not an FK — the parent may never have been persisted
9
+ -- or may have been pruned.
10
+ --
11
+ -- The index serves the `omni events trace` descendants walk
12
+ -- (children = rows WHERE causation_id = :id).
13
+ --
14
+ -- Hand-written following the 0055_asc_flow_handoff_mode precedent (additive,
15
+ -- idempotent — the snapshot chain stops at 0026 so drizzle-kit generate is
16
+ -- not usable here). No explicit BEGIN/COMMIT — the boot migrator executes
17
+ -- this file on a pooled postgres-js connection, which rejects raw transaction
18
+ -- control. ADD COLUMN with no default does not rewrite the table.
19
+
20
+ ALTER TABLE "omni_events"
21
+ ADD COLUMN IF NOT EXISTS "causation_id" uuid;
22
+
23
+ CREATE INDEX IF NOT EXISTS "omni_events_causation_idx"
24
+ ON "omni_events" ("causation_id");
@@ -407,6 +407,13 @@
407
407
  "when": 1785700000000,
408
408
  "tag": "0057_connector_lifecycle_contract",
409
409
  "breakpoints": true
410
+ },
411
+ {
412
+ "idx": 58,
413
+ "version": "7",
414
+ "when": 1785800000000,
415
+ "tag": "0058_omni_events_causation_id",
416
+ "breakpoints": true
410
417
  }
411
418
  ]
412
419
  }
@@ -3,11 +3,25 @@
3
3
  *
4
4
  * omni events list --instance <id>
5
5
  * omni events stream [flags]
6
+ * omni events trace <id>
6
7
  * omni events search <query>
7
8
  * omni events timeline <person-id>
8
9
  */
9
10
  import type { Event } from '@omni/sdk';
10
11
  import { Command } from 'commander';
12
+ /** One journal row as returned inside a trace response. */
13
+ interface TraceEvent {
14
+ id: string;
15
+ eventType: string;
16
+ receivedAt: string;
17
+ causationId: string | null;
18
+ metadata?: {
19
+ correlationId?: string;
20
+ } | null;
21
+ textContent?: string | null;
22
+ }
23
+ /** One human-readable trace line: type, short id, time, correlation. */
24
+ export declare function formatTraceLine(event: TraceEvent, marker: string): string;
11
25
  /** A registered event schema as returned by the API. */
12
26
  interface EventSchemaData {
13
27
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsMpC,wDAAwD;AACxD,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,iBAAe,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAe1G;AAED,kFAAkF;AAClF,iBAAS,kBAAkB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUhG;AAED,iBAAS,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzE;AAyED,eAAO,MAAM,WAAW;;;;CAA+D,CAAC;AAoBxF,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAQvF;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAOpD;AA6HD,wBAAgB,mBAAmB,IAAI,OAAO,CAqP7C"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsMpC,2DAA2D;AAC3D,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AA+BD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKzE;AAyCD,wDAAwD;AACxD,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,iBAAe,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAe1G;AAED,kFAAkF;AAClF,iBAAS,kBAAkB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUhG;AAED,iBAAS,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzE;AAyED,eAAO,MAAM,WAAW;;;;CAA+D,CAAC;AAoBxF,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAQvF;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAOpD;AA6HD,wBAAgB,mBAAmB,IAAI,OAAO,CAmQ7C"}
package/dist/index.js CHANGED
@@ -12345,6 +12345,19 @@ var init_types3 = __esm(() => {
12345
12345
  "flow.data_exchange"
12346
12346
  ];
12347
12347
  });
12348
+ // ../core/src/events/causality.ts
12349
+ import { AsyncLocalStorage } from "async_hooks";
12350
+ function runWithEventCausality(context, fn) {
12351
+ return storage.run(context, fn);
12352
+ }
12353
+ function currentEventCausality() {
12354
+ return storage.getStore();
12355
+ }
12356
+ var storage;
12357
+ var init_causality = __esm(() => {
12358
+ storage = new AsyncLocalStorage;
12359
+ });
12360
+
12348
12361
  // ../core/src/events/envelope.ts
12349
12362
  function classifyEnvelope(metadata) {
12350
12363
  if (metadata === null || metadata === undefined)
@@ -30370,6 +30383,38 @@ var init_logger = __esm(() => {
30370
30383
  rootLogger = createLogger("system");
30371
30384
  });
30372
30385
 
30386
+ // ../core/src/events/factory.ts
30387
+ function createOmniEvent(type, payload, metadata, serviceName) {
30388
+ const eventId = crypto.randomUUID();
30389
+ const timestamp = Date.now();
30390
+ const tenantId = resolvePublishTenantId(metadata?.tenantId, metadata?.instanceId);
30391
+ const ambient = currentEventCausality();
30392
+ const causationId = metadata?.causationId ?? ambient?.causationId;
30393
+ return {
30394
+ id: eventId,
30395
+ type,
30396
+ payload,
30397
+ timestamp,
30398
+ metadata: {
30399
+ correlationId: metadata?.correlationId ?? ambient?.correlationId ?? eventId,
30400
+ ...causationId ? { causationId } : {},
30401
+ instanceId: metadata?.instanceId,
30402
+ channelType: metadata?.channelType,
30403
+ personId: metadata?.personId,
30404
+ platformIdentityId: metadata?.platformIdentityId,
30405
+ traceId: metadata?.traceId ?? eventId,
30406
+ source: metadata?.source ?? serviceName,
30407
+ ingestMode: metadata?.ingestMode,
30408
+ timings: metadata?.timings,
30409
+ ...tenantId ? { envelopeVersion: CURRENT_ENVELOPE_VERSION, tenantId } : {}
30410
+ }
30411
+ };
30412
+ }
30413
+ var init_factory = __esm(() => {
30414
+ init_causality();
30415
+ init_envelope();
30416
+ });
30417
+
30373
30418
  // ../core/src/events/nats/streams.ts
30374
30419
  function getStreamForEventType(eventType) {
30375
30420
  const prefix = eventType.split(".")[0] ?? "";
@@ -31176,27 +31221,8 @@ class NatsEventBus {
31176
31221
  }
31177
31222
  async publishInternal(type, payload, metadata) {
31178
31223
  await this.ensureConnected();
31179
- const eventId = crypto.randomUUID();
31180
- const timestamp = Date.now();
31181
- const tenantId = resolvePublishTenantId(metadata?.tenantId, metadata?.instanceId);
31182
- const event = {
31183
- id: eventId,
31184
- type,
31185
- payload,
31186
- timestamp,
31187
- metadata: {
31188
- correlationId: metadata?.correlationId ?? eventId,
31189
- instanceId: metadata?.instanceId,
31190
- channelType: metadata?.channelType,
31191
- personId: metadata?.personId,
31192
- platformIdentityId: metadata?.platformIdentityId,
31193
- traceId: metadata?.traceId ?? eventId,
31194
- source: metadata?.source ?? this.config.serviceName,
31195
- ingestMode: metadata?.ingestMode,
31196
- timings: metadata?.timings,
31197
- ...tenantId ? { envelopeVersion: CURRENT_ENVELOPE_VERSION, tenantId } : {}
31198
- }
31199
- };
31224
+ const event = createOmniEvent(type, payload, metadata, this.config.serviceName);
31225
+ const eventId = event.id;
31200
31226
  let subject;
31201
31227
  if (metadata?.channelType && metadata?.instanceId) {
31202
31228
  subject = buildSubject(type, metadata.channelType, metadata.instanceId);
@@ -31472,7 +31498,7 @@ async function connectEventBus(config2) {
31472
31498
  var import_api2, import_nats, log4, DEFAULTS, ENSURE_CONNECTED_WAIT_MS = 5000;
31473
31499
  var init_client = __esm(() => {
31474
31500
  init_logger();
31475
- init_envelope();
31501
+ init_factory();
31476
31502
  init_consumer();
31477
31503
  init_registry();
31478
31504
  init_streams();
@@ -39465,6 +39491,7 @@ function estimateCompletion(progress) {
39465
39491
  // ../core/src/events/index.ts
39466
39492
  var init_events = __esm(() => {
39467
39493
  init_types3();
39494
+ init_causality();
39468
39495
  init_envelope();
39469
39496
  init_nats();
39470
39497
  init_dead_letter();
@@ -45144,13 +45171,7 @@ function resolveFollowUpValue(trimmed, followUp) {
45144
45171
  return;
45145
45172
  }
45146
45173
  }
45147
- function resolveTemplatePath(path, context) {
45148
- const trimmed = path.trim();
45149
- if (!trimmed)
45150
- return;
45151
- const parts = trimmed.split(".");
45152
- const root = parts[0] ?? "";
45153
- const rest = parts.slice(1).join(".");
45174
+ function resolveSpecialValue(trimmed, root, rest, context) {
45154
45175
  if (context.debounce) {
45155
45176
  const debounceValue = resolveDebounceValue(trimmed, rest, context.debounce);
45156
45177
  if (debounceValue !== undefined)
@@ -45161,6 +45182,21 @@ function resolveTemplatePath(path, context) {
45161
45182
  if (followUpValue !== undefined)
45162
45183
  return followUpValue;
45163
45184
  }
45185
+ if (root === "event" && context.event) {
45186
+ return rest ? getNestedValue(context.event, rest) : context.event;
45187
+ }
45188
+ return;
45189
+ }
45190
+ function resolveTemplatePath(path, context) {
45191
+ const trimmed = path.trim();
45192
+ if (!trimmed)
45193
+ return;
45194
+ const parts = trimmed.split(".");
45195
+ const root = parts[0] ?? "";
45196
+ const rest = parts.slice(1).join(".");
45197
+ const specialValue = resolveSpecialValue(trimmed, root, rest, context);
45198
+ if (specialValue !== undefined)
45199
+ return specialValue;
45164
45200
  if (root === "payload")
45165
45201
  return rest ? getNestedValue(context.payload, rest) : context.payload;
45166
45202
  if (root === "env")
@@ -45242,7 +45278,9 @@ function createTemplateContext(payload, options = {}) {
45242
45278
  variables: options.variables ?? {},
45243
45279
  env: process.env,
45244
45280
  debounce: options.debounce,
45245
- followUp
45281
+ followUp,
45282
+ event: options.event,
45283
+ automation: options.automation
45246
45284
  };
45247
45285
  }
45248
45286
  var TEMPLATE_REGEX;
@@ -45814,8 +45852,12 @@ var init_egress = __esm(() => {
45814
45852
  });
45815
45853
 
45816
45854
  // ../core/src/automations/actions.ts
45817
- function buildWebhookHeaders(config2, context) {
45855
+ function buildWebhookHeaders(config2, context, actionIndex) {
45818
45856
  const headers = { "Content-Type": "application/json" };
45857
+ if (context.event) {
45858
+ headers["X-Omni-Event-Id"] = context.event.id;
45859
+ headers["X-Omni-Delivery-Id"] = `${context.event.id}:${context.automation?.id ?? "manual"}:${actionIndex}`;
45860
+ }
45819
45861
  if (config2.headers) {
45820
45862
  for (const [key, value] of Object.entries(config2.headers)) {
45821
45863
  headers[key] = substituteTemplate(value, context);
@@ -45823,16 +45865,28 @@ function buildWebhookHeaders(config2, context) {
45823
45865
  }
45824
45866
  return headers;
45825
45867
  }
45868
+ function buildDefaultWebhookBody(config2, context) {
45869
+ if (context.event && config2.includeEnvelope !== false) {
45870
+ return JSON.stringify({
45871
+ id: context.event.id,
45872
+ type: context.event.type,
45873
+ payload: context.payload,
45874
+ metadata: context.event.metadata,
45875
+ timestamp: context.event.timestamp
45876
+ });
45877
+ }
45878
+ return JSON.stringify(context.payload);
45879
+ }
45826
45880
  async function parseWebhookResponse(response) {
45827
45881
  const contentType = response.headers.get("content-type") ?? "";
45828
45882
  return contentType.includes("application/json") ? response.json() : response.text();
45829
45883
  }
45830
- async function executeWebhookAction(config2, context, _deps, trustedTenantId) {
45884
+ async function executeWebhookAction(config2, context, _deps, trustedTenantId, actionIndex = 0) {
45831
45885
  try {
45832
45886
  const url = substituteTemplate(config2.url, context);
45833
45887
  const method = config2.method ?? "POST";
45834
- const headers = buildWebhookHeaders(config2, context);
45835
- const body = config2.bodyTemplate ? substituteTemplate(config2.bodyTemplate, context) : JSON.stringify(context.payload);
45888
+ const headers = buildWebhookHeaders(config2, context, actionIndex);
45889
+ const body = config2.bodyTemplate ? substituteTemplate(config2.bodyTemplate, context) : buildDefaultWebhookBody(config2, context);
45836
45890
  logger2.debug(`Webhook ${method} ${url}`, { method, url, waitForResponse: config2.waitForResponse });
45837
45891
  const response = await brokeredFetch(url, {
45838
45892
  method,
@@ -45922,8 +45976,10 @@ async function executeEmitEventAction(config2, context, deps, trustedTenantId) {
45922
45976
  }
45923
45977
  }
45924
45978
  logger2.debug("Emitting event", { eventType });
45979
+ const correlationId = context.event?.metadata.correlationId ?? context.payload.correlationId ?? undefined;
45925
45980
  const result = await deps.eventBus.publishGeneric(eventType, payload, {
45926
- correlationId: context.payload.correlationId ?? undefined,
45981
+ correlationId,
45982
+ causationId: context.event?.id,
45927
45983
  source: "automation",
45928
45984
  ...trustedTenantId ? { tenantId: trustedTenantId } : {}
45929
45985
  });
@@ -46016,7 +46072,12 @@ function extractAgentCallContext(config2, context) {
46016
46072
  threadId,
46017
46073
  senderId,
46018
46074
  senderName,
46019
- messages: messagesResult
46075
+ messages: messagesResult,
46076
+ event: context.event ? {
46077
+ id: context.event.id,
46078
+ type: context.event.type,
46079
+ correlationId: context.event.metadata.correlationId
46080
+ } : undefined
46020
46081
  }
46021
46082
  };
46022
46083
  }
@@ -46057,12 +46118,12 @@ async function executeCallAgentAction(config2, context, deps, trustedTenantId) {
46057
46118
  return { success: false, error: errorMessage };
46058
46119
  }
46059
46120
  }
46060
- async function executeAction(action, context, deps, trustedTenantId) {
46121
+ async function executeAction(action, context, deps, trustedTenantId, actionIndex = 0) {
46061
46122
  const start = Date.now();
46062
46123
  let result;
46063
46124
  switch (action.type) {
46064
46125
  case "webhook":
46065
- result = await executeWebhookAction(action.config, context, deps, trustedTenantId);
46126
+ result = await executeWebhookAction(action.config, context, deps, trustedTenantId, actionIndex);
46066
46127
  break;
46067
46128
  case "send_message":
46068
46129
  result = await executeSendMessageAction(action.config, context, deps, trustedTenantId);
@@ -46091,12 +46152,12 @@ async function executeAction(action, context, deps, trustedTenantId) {
46091
46152
  async function executeActions(actions, context, deps, trustedTenantId) {
46092
46153
  const results = [];
46093
46154
  const variables = { ...context.variables };
46094
- for (const action of actions) {
46155
+ for (const [actionIndex, action] of actions.entries()) {
46095
46156
  const actionContext = {
46096
46157
  ...context,
46097
46158
  variables
46098
46159
  };
46099
- const result = await executeAction(action, actionContext, deps, trustedTenantId);
46160
+ const result = await executeAction(action, actionContext, deps, trustedTenantId, actionIndex);
46100
46161
  results.push(result);
46101
46162
  if (action.type === "webhook" && action.config.responseAs && result.status === "success" && result.result) {
46102
46163
  variables[action.config.responseAs] = result.result;
@@ -46526,13 +46587,18 @@ class AutomationEngine {
46526
46587
  type: content?.type ?? "unknown",
46527
46588
  text: content?.text,
46528
46589
  timestamp: event.timestamp,
46529
- payload
46590
+ payload,
46591
+ eventId: event.id,
46592
+ correlationId: event.metadata.correlationId
46530
46593
  };
46531
46594
  manager.addMessage(key, message2, from, instanceId, stamp);
46532
46595
  }
46533
46596
  async handleImmediate(automation, event) {
46534
46597
  const instanceId = event.metadata.instanceId ?? "global";
46535
- const context = createTemplateContext(event.payload);
46598
+ const context = createTemplateContext(event.payload, {
46599
+ event: { id: event.id, type: event.type, timestamp: event.timestamp, metadata: event.metadata },
46600
+ automation: { id: automation.id }
46601
+ });
46536
46602
  await this.queueExecution(automation, event, context, instanceId);
46537
46603
  }
46538
46604
  setupDebounceManager(automation) {
@@ -46542,28 +46608,35 @@ class AutomationEngine {
46542
46608
  logger4.warn("Debounce callback fired with empty messages array", { key });
46543
46609
  return;
46544
46610
  }
46545
- const context = createTemplateContext(lastMessage.payload, {
46546
- debounce: {
46547
- messages: messages2.map((m2) => ({
46548
- type: m2.type,
46549
- text: m2.text,
46550
- timestamp: m2.timestamp
46551
- })),
46552
- from,
46553
- instanceId
46554
- }
46555
- });
46556
46611
  const syntheticEvent = {
46557
46612
  id: generateId(),
46558
46613
  type: automation.triggerEventType,
46559
46614
  payload: lastMessage.payload,
46560
46615
  metadata: {
46561
- correlationId: generateId(),
46616
+ correlationId: lastMessage.correlationId ?? generateId(),
46562
46617
  instanceId,
46563
46618
  ...stamp ? { envelopeVersion: stamp.envelopeVersion, tenantId: stamp.tenantId } : {}
46564
46619
  },
46565
46620
  timestamp: Date.now()
46566
46621
  };
46622
+ const context = createTemplateContext(lastMessage.payload, {
46623
+ debounce: {
46624
+ messages: messages2.map((m2) => ({
46625
+ type: m2.type,
46626
+ text: m2.text,
46627
+ timestamp: m2.timestamp
46628
+ })),
46629
+ from,
46630
+ instanceId
46631
+ },
46632
+ event: {
46633
+ id: lastMessage.eventId ?? syntheticEvent.id,
46634
+ type: syntheticEvent.type,
46635
+ timestamp: syntheticEvent.timestamp,
46636
+ metadata: syntheticEvent.metadata
46637
+ },
46638
+ automation: { id: automation.id }
46639
+ });
46567
46640
  await this.queueExecution(automation, syntheticEvent, context, instanceId);
46568
46641
  };
46569
46642
  const manager = new DebounceManager(automation.debounce, callback);
@@ -46651,7 +46724,10 @@ class AutomationEngine {
46651
46724
  await this.logExecution(result2, trustedTenantId);
46652
46725
  return result2;
46653
46726
  }
46654
- const actionsExecuted = await executeActions(automation.actions, context, this.deps, trustedTenantId);
46727
+ const actionsExecuted = await runWithEventCausality({
46728
+ correlationId: context.event?.metadata.correlationId ?? event.metadata.correlationId,
46729
+ causationId: context.event?.id ?? event.id
46730
+ }, () => executeActions(automation.actions, context, this.deps, trustedTenantId));
46655
46731
  const allSucceeded = actionsExecuted.every((a) => a.status === "success");
46656
46732
  const status = allSucceeded ? "success" : "failed";
46657
46733
  const result = {
@@ -46747,6 +46823,7 @@ function createAutomationEngine(config2) {
46747
46823
  }
46748
46824
  var logger4, QueueFullError;
46749
46825
  var init_engine = __esm(() => {
46826
+ init_causality();
46750
46827
  init_envelope();
46751
46828
  init_ids();
46752
46829
  init_logger();
@@ -74655,7 +74732,7 @@ function isProviderSchemaSupported(schema) {
74655
74732
  function getSupportedProviderSchemas() {
74656
74733
  return ["agno", "webhook", "openclaw", "claude-code", "ag-ui", "a2a", "nats-genie"];
74657
74734
  }
74658
- var init_factory = __esm(() => {
74735
+ var init_factory2 = __esm(() => {
74659
74736
  init_a2a_client();
74660
74737
  init_ag_ui_client();
74661
74738
  init_agno_client();
@@ -74675,7 +74752,7 @@ var init_providers = __esm(() => {
74675
74752
  init_ag_ui_provider();
74676
74753
  init_a2a_provider();
74677
74754
  init_nats_genie_provider();
74678
- init_factory();
74755
+ init_factory2();
74679
74756
  });
74680
74757
 
74681
74758
  // ../core/src/cache/types.ts
@@ -75359,6 +75436,7 @@ __export(exports_src, {
75359
75436
  scheduledJobRuns: () => scheduledJobRuns,
75360
75437
  scheduledJobNextRun: () => scheduledJobNextRun,
75361
75438
  scheduledJobDuration: () => scheduledJobDuration,
75439
+ runWithEventCausality: () => runWithEventCausality,
75362
75440
  rootLogger: () => rootLogger,
75363
75441
  resolveResetConfig: () => resolveResetConfig,
75364
75442
  resolvePublishTenantId: () => resolvePublishTenantId,
@@ -75471,6 +75549,7 @@ __export(exports_src, {
75471
75549
  dbQueries: () => dbQueries,
75472
75550
  dbPoolSize: () => dbPoolSize,
75473
75551
  dbErrors: () => dbErrors,
75552
+ currentEventCausality: () => currentEventCausality,
75474
75553
  createValidatedSubscription: () => createValidatedSubscription,
75475
75554
  createTemplateContext: () => createTemplateContext,
75476
75555
  createSubscription: () => createSubscription,
@@ -81878,9 +81957,11 @@ var init_schema2 = __esm(() => {
81878
81957
  agentRequest: jsonb("agent_request").$type(),
81879
81958
  agentResponse: jsonb("agent_response").$type(),
81880
81959
  metadata: jsonb("metadata").$type(),
81960
+ causationId: uuid("causation_id"),
81881
81961
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
81882
81962
  tenantId: uuid("tenant_id").references(() => tenants.id, { onDelete: "restrict" })
81883
81963
  }, (table3) => ({
81964
+ causationIdx: index("omni_events_causation_idx").on(table3.causationId),
81884
81965
  tenantIdx: index("omni_events_tenant_idx").on(table3.tenantId),
81885
81966
  tenantIdUq: uniqueIndex("omni_events_tenant_id_uq").on(table3.tenantId, table3.id),
81886
81967
  externalIdIdx: index("omni_events_external_id_idx").on(table3.externalId),
@@ -136258,7 +136339,7 @@ import { fileURLToPath } from "url";
136258
136339
  // package.json
136259
136340
  var package_default = {
136260
136341
  name: "@automagik/omni",
136261
- version: "2.260906.3",
136342
+ version: "2.260906.4",
136262
136343
  repository: {
136263
136344
  type: "git",
136264
136345
  url: "git+https://github.com/automagik-dev/omni.git",
@@ -142883,6 +142964,46 @@ ${title}:`);
142883
142964
  const items = Object.entries(record).sort(([, a], [, b2]) => b2 - a).map(([key, count]) => ({ [keyName]: key, count }));
142884
142965
  list(items);
142885
142966
  }
142967
+ async function fetchTrace(id) {
142968
+ const config = loadConfig();
142969
+ const baseUrl = config.apiUrl ?? "http://localhost:8882";
142970
+ const resp = await fetch(`${baseUrl}/api/v2/events/${encodeURIComponent(id)}/trace`, {
142971
+ headers: { "x-api-key": config.apiKey ?? "" }
142972
+ });
142973
+ if (!resp.ok) {
142974
+ throw new Error(`API returned ${resp.status}: ${await resp.text()}`);
142975
+ }
142976
+ return (await resp.json()).data;
142977
+ }
142978
+ function formatTraceLine(event, marker) {
142979
+ const time = new Date(event.receivedAt).toISOString().replace("T", " ").slice(0, 19);
142980
+ const corr = event.metadata?.correlationId?.slice(0, 8) ?? "--------";
142981
+ const text = event.textContent ? ` "${event.textContent.slice(0, 40)}"` : "";
142982
+ return `${marker}${event.eventType} ${event.id.slice(0, 8)} ${time} corr=${corr}${text}`;
142983
+ }
142984
+ function displayTrace(data2) {
142985
+ if (getOutputFormat() === "json") {
142986
+ data(data2);
142987
+ return;
142988
+ }
142989
+ let indent = 0;
142990
+ for (const ancestor of data2.ancestors) {
142991
+ const label = indent === 0 && !ancestor.causationId ? " (root)" : "";
142992
+ raw(`${" ".repeat(indent)}${formatTraceLine(ancestor, indent === 0 ? "\u25CF " : "\u2514\u2500 ")}${label}`);
142993
+ indent++;
142994
+ }
142995
+ const focusIsRoot = data2.ancestors.length === 0 && !data2.event.causationId;
142996
+ raw(`${" ".repeat(indent)}${formatTraceLine(data2.event, indent === 0 ? "\u25CF " : "\u2514\u2500 ")}${focusIsRoot ? " (root)" : ""} \u2190 trace target`);
142997
+ for (const { event, depth } of data2.descendants) {
142998
+ raw(`${" ".repeat(indent + depth)}${formatTraceLine(event, "\u2514\u2500 ")}`);
142999
+ }
143000
+ if (data2.descendants.length === 0) {
143001
+ dim("(no descendants \u2014 nothing was caused by this event)");
143002
+ }
143003
+ if (data2.truncated) {
143004
+ warn("Trace truncated (depth/node cap reached)");
143005
+ }
143006
+ }
142886
143007
  async function schemaApiRequest(path, init = {}) {
142887
143008
  const config = loadConfig();
142888
143009
  const baseUrl = config.apiUrl ?? "http://localhost:8882";
@@ -143129,6 +143250,15 @@ function createEventsCommand() {
143129
143250
  error(`Failed to get event: ${message}`);
143130
143251
  }
143131
143252
  });
143253
+ events.command("trace <id>").description("Walk the causality chain around an event: root \u2192 parents \u2192 this event \u2192 everything it caused").action(async (id) => {
143254
+ try {
143255
+ const data2 = await fetchTrace(id);
143256
+ displayTrace(data2);
143257
+ } catch (err) {
143258
+ const message = err instanceof Error ? err.message : "Unknown error";
143259
+ error(`Failed to trace event: ${message}`);
143260
+ }
143261
+ });
143132
143262
  events.command("search <query>").description("Search events by content").option("--since <time>", "Events since (e.g., 24h, 7d)").option("--limit <n>", "Limit results", (v) => Number.parseInt(v, 10), 50).action(async (query, options) => {
143133
143263
  const client = getClient();
143134
143264
  try {