mcp-event-intelligence 0.5.0 → 0.6.0

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +31 -38
  3. package/SECURITY.md +4 -4
  4. package/bin/mcp-event-intelligence.mjs +2 -2
  5. package/dist/src/composite/engine.d.ts +11 -7
  6. package/dist/src/composite/engine.js +150 -414
  7. package/dist/src/composite/matching.d.ts +1 -5
  8. package/dist/src/composite/matching.js +0 -54
  9. package/dist/src/composite/runtimeSupport.js +10 -6
  10. package/dist/src/composite/store.d.ts +38 -4
  11. package/dist/src/composite/temporal.d.ts +0 -17
  12. package/dist/src/composite/temporal.js +0 -266
  13. package/dist/src/intelligenceProtocol/activationSchemas.d.ts +36 -3
  14. package/dist/src/intelligenceProtocol/activationSchemas.js +4 -3
  15. package/dist/src/intelligenceProtocol/index.d.ts +8 -12
  16. package/dist/src/intelligenceProtocol/index.js +4 -7
  17. package/dist/src/intelligenceProtocol/lifecycle.js +2 -10
  18. package/dist/src/intelligenceProtocol/operatorRegistry.d.ts +3 -270
  19. package/dist/src/intelligenceProtocol/operatorRegistry.js +5 -144
  20. package/dist/src/intelligenceProtocol/schemas.d.ts +0 -189
  21. package/dist/src/intelligenceProtocol/schemas.js +1 -97
  22. package/dist/src/intelligenceProtocol/triggerPlanSchemas.d.ts +5 -102
  23. package/dist/src/intelligenceProtocol/triggerPlanSchemas.js +2 -26
  24. package/dist/src/intelligenceProtocol/triggerSchemas.d.ts +14 -215
  25. package/dist/src/intelligenceProtocol/triggerSchemas.js +18 -191
  26. package/dist/src/intelligenceProtocol/version.d.ts +2 -2
  27. package/dist/src/intelligenceProtocol/version.js +2 -2
  28. package/dist/src/patternV2/evaluator.d.ts +9 -1
  29. package/dist/src/patternV2/evaluator.js +63 -4
  30. package/dist/src/semantic/types.d.ts +6 -0
  31. package/dist/src/semantic/typesafeJevEvaluator.d.ts +1 -0
  32. package/dist/src/semantic/typesafeJevEvaluator.js +6 -0
  33. package/package.json +5 -2
  34. package/scripts/host-integration.d.mts +48 -5
  35. package/scripts/host-integration.mjs +16 -4
  36. package/scripts/lib/activation-hydrator.mjs +12 -12
  37. package/scripts/lib/composite-event-consumer.mjs +8 -28
  38. package/scripts/lib/composite-wake-coordinator.mjs +19 -19
  39. package/scripts/lib/derived-contract-registry.mjs +4 -4
  40. package/scripts/lib/derived-event-coordinator.mjs +11 -22
  41. package/scripts/lib/local-event-intelligence-runtime.mjs +35 -3
  42. package/scripts/lib/mcp-events-client.mjs +36 -32
  43. package/scripts/lib/persistent-event-store.mjs +228 -61
  44. package/scripts/lib/store-capabilities.mjs +88 -0
  45. package/scripts/lib/store-conformance.mjs +127 -0
  46. package/scripts/lib/temporal-deadline-scheduler.mjs +3 -3
  47. package/scripts/lib/trigger-control-plane.mjs +52 -57
  48. package/scripts/lib/trigger-inspector.mjs +48 -160
  49. package/scripts/lib/trigger-planner.mjs +37 -126
  50. package/scripts/lib/wake-retry-scheduler.mjs +2 -19
  51. package/scripts/mcp-stdio-server.mjs +8 -8
  52. package/scripts/service.mjs +19 -138
  53. package/server.json +3 -3
  54. package/dist/src/intelligenceProtocol/invariants.d.ts +0 -3
  55. package/dist/src/intelligenceProtocol/invariants.js +0 -36
  56. package/dist/src/intelligenceProtocol/mapper.d.ts +0 -14
  57. package/dist/src/intelligenceProtocol/mapper.js +0 -28
  58. package/dist/src/patternV2/legacyCompiler.d.ts +0 -3
  59. package/dist/src/patternV2/legacyCompiler.js +0 -184
  60. package/scripts/lib/event-processor.mjs +0 -624
  61. package/scripts/lib/http-wake-deliverer.mjs +0 -31
@@ -2,9 +2,6 @@ import {
2
2
  parseDerivedEventRecord,
3
3
  sha256Hex,
4
4
  } from '../../dist/src/intelligenceProtocol/index.js';
5
- import {
6
- evaluateTemporalConditions,
7
- } from '../../dist/src/composite/temporal.js';
8
5
  import {
9
6
  evaluatePatternMeasure,
10
7
  } from '../../dist/src/patternV2/evaluator.js';
@@ -92,22 +89,14 @@ function patternCandidateForMatch(match) {
92
89
  };
93
90
  }
94
91
 
95
- function derivedOccurredAt(match, definition) {
92
+ function derivedOccurredAt(match) {
93
+ if (match.patternState?.completedAt) {
94
+ return match.patternState.completedAt;
95
+ }
96
+
96
97
  const candidates = match.sourceEvents
97
98
  .map((event) => Date.parse(event.occurredAt))
98
99
  .filter(Number.isFinite);
99
-
100
- const temporal = evaluateTemporalConditions(
101
- definition,
102
- match,
103
- new Date(match.updatedAt),
104
- );
105
- for (const state of temporal.conditionStates) {
106
- if (state.status !== 'satisfied' || !state.dueAt) continue;
107
- const dueAt = Date.parse(state.dueAt);
108
- if (Number.isFinite(dueAt)) candidates.push(dueAt);
109
- }
110
-
111
100
  if (!candidates.length) return match.updatedAt;
112
101
  return new Date(Math.max(...candidates)).toISOString();
113
102
  }
@@ -141,7 +130,7 @@ export class DerivedEventCoordinator {
141
130
  })
142
131
  ).slice(0, 24)}`;
143
132
 
144
- const existing = this.store.getDerivedEvent(
133
+ const existing = await this.store.getDerivedEvent(
145
134
  eventId,
146
135
  DERIVED_EVENT_SERVER_ID,
147
136
  );
@@ -162,7 +151,7 @@ export class DerivedEventCoordinator {
162
151
  const rootEvidence = [];
163
152
  for (const source of match.sourceEvents) {
164
153
  if (source.serverId === DERIVED_EVENT_SERVER_ID) {
165
- const parent = this.store.getDerivedEvent(
154
+ const parent = await this.store.getDerivedEvent(
166
155
  source.sourceEventId,
167
156
  DERIVED_EVENT_SERVER_ID,
168
157
  );
@@ -219,7 +208,7 @@ export class DerivedEventCoordinator {
219
208
  }
220
209
  }
221
210
 
222
- const contract = this.store.getDerivedContract(
211
+ const contract = await this.store.getDerivedContract(
223
212
  spec.name,
224
213
  spec.contractVersion,
225
214
  );
@@ -239,7 +228,7 @@ export class DerivedEventCoordinator {
239
228
  triggerId: definition.triggerId,
240
229
  triggerVersion: definition.version,
241
230
  matchId: match.matchId,
242
- correlationKey: match.correlationKey,
231
+ partitionKey: match.partitionKey,
243
232
  contractVersion: spec.contractVersion,
244
233
  schemaFingerprint: contract.schemaFingerprint,
245
234
  },
@@ -249,7 +238,7 @@ export class DerivedEventCoordinator {
249
238
  traceId: `derived:${eventId}`,
250
239
  sourceEventId: eventId,
251
240
  name: spec.name,
252
- occurredAt: derivedOccurredAt(match, definition),
241
+ occurredAt: derivedOccurredAt(match),
253
242
  receivedAt: this.now().toISOString(),
254
243
  provider: 'event-intelligence',
255
244
  serverId: DERIVED_EVENT_SERVER_ID,
@@ -296,7 +285,7 @@ export class DerivedEventCoordinator {
296
285
  await sha256Hex({
297
286
  kind,
298
287
  sourceEventId: record.event.sourceEventId,
299
- sequence: this.store.auditLength(),
288
+ sequence: await this.store.auditLength(),
300
289
  })
301
290
  ).slice(0, 24)}`,
302
291
  traceId: record.event.traceId,
@@ -26,6 +26,10 @@ import {
26
26
  PersistentEventStore,
27
27
  normalizeEventScopeId,
28
28
  } from './persistent-event-store.mjs';
29
+ import {
30
+ assertSharedStoreCapabilities,
31
+ describeStoreCapabilities,
32
+ } from './store-capabilities.mjs';
29
33
  import {
30
34
  TriggerInspector,
31
35
  } from './trigger-inspector.mjs';
@@ -114,6 +118,23 @@ export async function createLocalEventIntelligenceRuntime({
114
118
  const dataDir = env.DATA_DIR ?? './data';
115
119
  const rootStore = providedStore ?? new PersistentEventStore(dataDir);
116
120
  const restored = await initializeStore(rootStore);
121
+ const storeCapabilities = describeStoreCapabilities(rootStore);
122
+ const requireSharedStore =
123
+ env.EVENT_INTELLIGENCE_REQUIRE_SHARED_STORE === 'true';
124
+ if (requireSharedStore) {
125
+ assertSharedStoreCapabilities(rootStore);
126
+ if (!String(env.EVENT_INTELLIGENCE_WORKER_ID || '').trim()) {
127
+ const error = new Error(
128
+ 'EVENT_INTELLIGENCE_WORKER_ID is required in shared-store mode',
129
+ );
130
+ error.code = 'EVENT_INTELLIGENCE_WORKER_ID_REQUIRED';
131
+ throw error;
132
+ }
133
+ }
134
+ const rootWorkerId = String(
135
+ env.EVENT_INTELLIGENCE_WORKER_ID ||
136
+ `ei-${process.pid}`,
137
+ ).trim();
117
138
 
118
139
  const evaluator =
119
140
  semanticEvaluator !== undefined
@@ -161,7 +182,17 @@ export async function createLocalEventIntelligenceRuntime({
161
182
  assertStoreContract(store);
162
183
  }
163
184
 
164
- const triggerEngine = new CompositeTriggerEngine(store, evaluator);
185
+ const triggerEngine = new CompositeTriggerEngine(
186
+ store,
187
+ evaluator,
188
+ undefined,
189
+ {
190
+ workerId: `${rootWorkerId}:${scopeId}`,
191
+ partitionLeaseMs: Number(
192
+ env.EVENT_INTELLIGENCE_PARTITION_LEASE_MS ?? 300000,
193
+ ),
194
+ },
195
+ );
165
196
  const triggerPlanner = new TriggerPlanner({ store });
166
197
  const activationHydrator = new ActivationHydrator({ store });
167
198
  const wakeCoordinators = new Map();
@@ -195,7 +226,7 @@ export async function createLocalEventIntelligenceRuntime({
195
226
  packetBuilder,
196
227
  ...deliveryOptions,
197
228
  deliverer: async (packet) => {
198
- const activation = activationHydrator.hydrateWake(packet.wake_id);
229
+ const activation = await activationHydrator.hydrateWake(packet.wake_id);
199
230
  const result = await handler(packet, activation);
200
231
  if (typeof result === 'string' && result) {
201
232
  return { runtimeReceiptId: result };
@@ -224,7 +255,7 @@ export async function createLocalEventIntelligenceRuntime({
224
255
  packetBuilder,
225
256
  ...deliveryOptions,
226
257
  deliverer: async (packet) => {
227
- const activation = activationHydrator.hydrateWake(packet.wake_id);
258
+ const activation = await activationHydrator.hydrateWake(packet.wake_id);
228
259
  const result = await wake(packet, activation);
229
260
  if (typeof result === 'string' && result) {
230
261
  return { runtimeReceiptId: result };
@@ -330,6 +361,7 @@ export async function createLocalEventIntelligenceRuntime({
330
361
 
331
362
  return {
332
363
  restored,
364
+ storeCapabilities,
333
365
  store: defaultContext.store,
334
366
  evaluator,
335
367
  triggerEngine: defaultContext.triggerEngine,
@@ -394,7 +394,7 @@ export class McpEventsClientManager {
394
394
  }
395
395
  const removed = this.connections.delete(connectionId);
396
396
  if (removed && context) {
397
- const sources = context.store.listEventSources({
397
+ const sources = await context.store.listEventSources({
398
398
  connectionIds: [connectionId],
399
399
  });
400
400
  for (const source of sources) {
@@ -486,9 +486,9 @@ export class McpEventsClientManager {
486
486
  for (const normalized of descriptors) {
487
487
  const sourceId =
488
488
  `mcp:${connection.connectionId}:${normalized.name}`;
489
- const existing = context.store
490
- .listEventSources()
491
- .find((source) => source.sourceId === sourceId);
489
+ const existing = (
490
+ await context.store.listEventSources()
491
+ ).find((source) => source.sourceId === sourceId);
492
492
  const same =
493
493
  existing &&
494
494
  existing.enabled !== false &&
@@ -571,25 +571,26 @@ export class McpEventsClientManager {
571
571
  return results;
572
572
  }
573
573
 
574
- desiredSubscriptions(connection, context) {
574
+ async desiredSubscriptions(connection, context) {
575
575
  const descriptors = this.descriptors.get(connection.connectionId) || [];
576
576
  const byName = new Map(descriptors.map((item) => [item.name, item]));
577
577
  const desired = new Map();
578
- const triggers =
579
- typeof context.triggerControl?.listTriggers === 'function'
580
- ? context.triggerControl.listTriggers()
581
- : typeof context.store?.listTriggers === 'function'
582
- ? context.store.listTriggers().map((definition) => ({
583
- definition,
584
- state:
585
- typeof context.store.getTriggerState === 'function'
586
- ? context.store.getTriggerState(
587
- definition.triggerId,
588
- definition.version,
589
- )
590
- : null,
591
- }))
592
- : [];
578
+ let triggers = [];
579
+ if (typeof context.triggerControl?.listTriggers === 'function') {
580
+ triggers = await context.triggerControl.listTriggers();
581
+ } else if (typeof context.store?.listTriggers === 'function') {
582
+ const definitions = await context.store.listTriggers();
583
+ triggers = await Promise.all(definitions.map(async (definition) => ({
584
+ definition,
585
+ state:
586
+ typeof context.store.getTriggerState === 'function'
587
+ ? await context.store.getTriggerState(
588
+ definition.triggerId,
589
+ definition.version,
590
+ )
591
+ : null,
592
+ })));
593
+ }
593
594
 
594
595
  for (const { definition, state } of triggers) {
595
596
  if (state?.status !== 'active') continue;
@@ -664,7 +665,7 @@ export class McpEventsClientManager {
664
665
  subscription,
665
666
  patch = {},
666
667
  ) {
667
- const previous = context.store.getMcpClientState(
668
+ const previous = await context.store.getMcpClientState(
668
669
  connection.connectionId,
669
670
  subscription.eventName,
670
671
  subscription.arguments,
@@ -687,7 +688,7 @@ export class McpEventsClientManager {
687
688
  { respectSchedule = false } = {},
688
689
  ) {
689
690
  const store = context.store;
690
- const current = store.getMcpClientState(
691
+ const current = await store.getMcpClientState(
691
692
  connection.connectionId,
692
693
  subscription.eventName,
693
694
  subscription.arguments,
@@ -810,7 +811,7 @@ export class McpEventsClientManager {
810
811
  }
811
812
  if (existing) await this.closeSession(subscription.subscriptionId);
812
813
 
813
- const current = context.store.getMcpClientState(
814
+ const current = await context.store.getMcpClientState(
814
815
  connection.connectionId,
815
816
  subscription.eventName,
816
817
  subscription.arguments,
@@ -995,7 +996,7 @@ export class McpEventsClientManager {
995
996
  descriptors = await this.discoverConnection(connectionId);
996
997
  }
997
998
 
998
- const desired = this.desiredSubscriptions(connection, context);
999
+ const desired = await this.desiredSubscriptions(connection, context);
999
1000
  const desiredIds = new Set(desired.keys());
1000
1001
  const results = [];
1001
1002
 
@@ -1062,12 +1063,12 @@ export class McpEventsClientManager {
1062
1063
  return results;
1063
1064
  }
1064
1065
 
1065
- nextDelay(connection) {
1066
+ async nextDelay(connection) {
1066
1067
  const context = this.scopeContexts.get(
1067
1068
  `${connection.connectionId}::${connection.scopeId}`,
1068
1069
  );
1069
1070
  if (!context) return connection.pollIntervalMs;
1070
- const states = context.store.listMcpClientStates(
1071
+ const states = await context.store.listMcpClientStates(
1071
1072
  connection.connectionId,
1072
1073
  );
1073
1074
  const now = this.now().getTime();
@@ -1101,7 +1102,10 @@ export class McpEventsClientManager {
1101
1102
  this.started &&
1102
1103
  this.connections.get(connection.connectionId) === connection
1103
1104
  ) {
1104
- this.scheduleConnection(connection, this.nextDelay(connection));
1105
+ this.scheduleConnection(
1106
+ connection,
1107
+ await this.nextDelay(connection),
1108
+ );
1105
1109
  }
1106
1110
  }
1107
1111
  }, Math.max(0, delay));
@@ -1136,15 +1140,15 @@ export class McpEventsClientManager {
1136
1140
  await this.drain();
1137
1141
  }
1138
1142
 
1139
- status() {
1140
- return [...this.connections.values()].map((connection) => {
1143
+ async status() {
1144
+ return Promise.all([...this.connections.values()].map(async (connection) => {
1141
1145
  const context = this.scopeContexts.get(
1142
1146
  `${connection.connectionId}::${connection.scopeId}`,
1143
1147
  );
1144
1148
  const store = context?.store ?? this.store;
1145
- const states = store.listMcpClientStates(connection.connectionId);
1149
+ const states = await store.listMcpClientStates(connection.connectionId);
1146
1150
  const desired = context
1147
- ? this.desiredSubscriptions(connection, context)
1151
+ ? await this.desiredSubscriptions(connection, context)
1148
1152
  : new Map();
1149
1153
  return {
1150
1154
  connectionId: connection.connectionId,
@@ -1177,6 +1181,6 @@ export class McpEventsClientManager {
1177
1181
  ),
1178
1182
  error: this.lastErrors.get(connection.connectionId) ?? null,
1179
1183
  };
1180
- });
1184
+ }));
1181
1185
  }
1182
1186
  }