mcp-event-intelligence 0.4.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.
- package/CHANGELOG.md +100 -0
- package/README.md +107 -26
- package/SECURITY.md +4 -4
- package/bin/mcp-event-intelligence.mjs +3 -3
- package/dist/src/composite/engine.d.ts +14 -4
- package/dist/src/composite/engine.js +533 -208
- package/dist/src/composite/matching.d.ts +1 -5
- package/dist/src/composite/matching.js +45 -54
- package/dist/src/composite/runtimeSupport.js +10 -6
- package/dist/src/composite/store.d.ts +38 -4
- package/dist/src/composite/temporal.d.ts +0 -17
- package/dist/src/composite/temporal.js +0 -266
- package/dist/src/intelligenceProtocol/activationSchemas.d.ts +38 -3
- package/dist/src/intelligenceProtocol/activationSchemas.js +5 -3
- package/dist/src/intelligenceProtocol/index.d.ts +12 -9
- package/dist/src/intelligenceProtocol/index.js +6 -5
- package/dist/src/intelligenceProtocol/lifecycle.js +2 -10
- package/dist/src/intelligenceProtocol/operatorRegistry.d.ts +300 -0
- package/dist/src/intelligenceProtocol/operatorRegistry.js +338 -0
- package/dist/src/intelligenceProtocol/patternV2Schemas.d.ts +188 -0
- package/dist/src/intelligenceProtocol/patternV2Schemas.js +801 -0
- package/dist/src/intelligenceProtocol/schemas.d.ts +4 -189
- package/dist/src/intelligenceProtocol/schemas.js +3 -97
- package/dist/src/intelligenceProtocol/triggerPlanSchemas.d.ts +114 -38
- package/dist/src/intelligenceProtocol/triggerPlanSchemas.js +27 -18
- package/dist/src/intelligenceProtocol/triggerSchemas.d.ts +268 -213
- package/dist/src/intelligenceProtocol/triggerSchemas.js +155 -169
- package/dist/src/intelligenceProtocol/version.d.ts +2 -2
- package/dist/src/intelligenceProtocol/version.js +2 -2
- package/dist/src/mcpEvents/consumer.d.ts +1 -0
- package/dist/src/mcpEvents/consumer.js +1 -0
- package/dist/src/patternV2/evaluator.d.ts +51 -0
- package/dist/src/patternV2/evaluator.js +986 -0
- package/dist/src/semantic/types.d.ts +6 -0
- package/dist/src/semantic/typesafeJevEvaluator.d.ts +1 -0
- package/dist/src/semantic/typesafeJevEvaluator.js +6 -0
- package/package.json +9 -3
- package/scripts/host-integration.d.mts +54 -4
- package/scripts/host-integration.mjs +25 -4
- package/scripts/lib/activation-hydrator.mjs +13 -12
- package/scripts/lib/composite-event-consumer.mjs +10 -28
- package/scripts/lib/composite-wake-coordinator.mjs +19 -19
- package/scripts/lib/derived-contract-registry.mjs +4 -4
- package/scripts/lib/derived-event-coordinator.mjs +69 -6
- package/scripts/lib/local-event-intelligence-runtime.mjs +35 -3
- package/scripts/lib/mcp-events-client.mjs +97 -55
- package/scripts/lib/mcp-events-compatibility.mjs +54 -0
- package/scripts/lib/persistent-event-store.mjs +228 -61
- package/scripts/lib/store-capabilities.mjs +88 -0
- package/scripts/lib/store-conformance.mjs +127 -0
- package/scripts/lib/temporal-deadline-scheduler.mjs +3 -3
- package/scripts/lib/trigger-control-plane.mjs +202 -53
- package/scripts/lib/trigger-inspector.mjs +50 -147
- package/scripts/lib/trigger-planner.mjs +141 -52
- package/scripts/lib/wake-retry-scheduler.mjs +2 -19
- package/scripts/mcp-stdio-server.mjs +46 -61
- package/scripts/service.mjs +19 -138
- package/server.json +4 -4
- package/dist/src/intelligenceProtocol/invariants.d.ts +0 -3
- package/dist/src/intelligenceProtocol/invariants.js +0 -36
- package/dist/src/intelligenceProtocol/mapper.d.ts +0 -14
- package/dist/src/intelligenceProtocol/mapper.js +0 -28
- package/scripts/lib/event-processor.mjs +0 -624
- package/scripts/lib/http-wake-deliverer.mjs +0 -31
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { RuntimeTargetSchema } from './schemas.js';
|
|
3
|
-
|
|
4
|
-
export const
|
|
3
|
+
import { PatternAstV2DefinitionSchema, PatternMeasureSchema, collectPatternDurationsMs, collectGuaranteedPatternBindings, collectPatternMeasureRefs, collectPatternRefs, } from './patternV2Schemas.js';
|
|
4
|
+
export const COMPOSITE_TRIGGER_PROTOCOL_VERSION = '0.2.0';
|
|
5
|
+
export const COMPOSITE_TRIGGER_SCHEMA_VERSION = 'trigger.v0.2';
|
|
5
6
|
const Id = z.string().min(1).max(200);
|
|
6
7
|
const Timestamp = z.string().datetime({ offset: true });
|
|
7
8
|
const Scalar = z.union([z.string(), z.number(), z.boolean()]);
|
|
8
|
-
const ClockTime = z.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
|
|
9
|
-
const CalendarDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
10
9
|
export const StructuredPredicateSchema = z.discriminatedUnion('op', [
|
|
11
10
|
z.object({ path: z.string().min(1), op: z.literal('eq'), value: Scalar }),
|
|
12
11
|
z.object({ path: z.string().min(1), op: z.literal('neq'), value: Scalar }),
|
|
13
12
|
z.object({ path: z.string().min(1), op: z.literal('contains'), value: Scalar }),
|
|
13
|
+
z.object({ path: z.string().min(1), op: z.literal('startsWith'), value: z.string() }),
|
|
14
|
+
z.object({ path: z.string().min(1), op: z.literal('endsWith'), value: z.string() }),
|
|
15
|
+
z.object({
|
|
16
|
+
path: z.string().min(1),
|
|
17
|
+
op: z.literal('regex'),
|
|
18
|
+
value: z.string(),
|
|
19
|
+
flags: z.string().max(10).optional(),
|
|
20
|
+
}),
|
|
14
21
|
z.object({ path: z.string().min(1), op: z.literal('in'), value: z.array(Scalar).min(1) }),
|
|
22
|
+
z.object({ path: z.string().min(1), op: z.literal('notIn'), value: z.array(Scalar).min(1) }),
|
|
23
|
+
z.object({
|
|
24
|
+
path: z.string().min(1),
|
|
25
|
+
op: z.literal('between'),
|
|
26
|
+
value: z.tuple([Scalar, Scalar]),
|
|
27
|
+
}),
|
|
15
28
|
z.object({ path: z.string().min(1), op: z.literal('exists'), value: z.boolean().default(true) }),
|
|
29
|
+
z.object({ path: z.string().min(1), op: z.literal('isNull'), value: z.boolean().default(true) }),
|
|
30
|
+
z.object({
|
|
31
|
+
path: z.string().min(1),
|
|
32
|
+
op: z.literal('type'),
|
|
33
|
+
value: z.enum(['string', 'number', 'boolean', 'null', 'object', 'array']),
|
|
34
|
+
}),
|
|
16
35
|
z.object({ path: z.string().min(1), op: z.literal('gt'), value: z.number() }),
|
|
17
36
|
z.object({ path: z.string().min(1), op: z.literal('gte'), value: z.number() }),
|
|
18
37
|
z.object({ path: z.string().min(1), op: z.literal('lt'), value: z.number() }),
|
|
@@ -26,83 +45,6 @@ export const TriggerClauseSchema = z.object({
|
|
|
26
45
|
arguments: z.record(z.string(), z.unknown()).default({}),
|
|
27
46
|
where: z.array(StructuredPredicateSchema).default([]),
|
|
28
47
|
});
|
|
29
|
-
const TriggerExpressionSchema = z.discriminatedUnion('kind', [
|
|
30
|
-
z.object({ kind: z.literal('allOf'), refs: z.array(Id).min(2) }),
|
|
31
|
-
z.object({ kind: z.literal('anyOf'), refs: z.array(Id).min(1) }),
|
|
32
|
-
z.object({ kind: z.literal('sequence'), refs: z.array(Id).min(2) }),
|
|
33
|
-
z.object({ kind: z.literal('count'), ref: Id, atLeast: z.number().int().min(1) }),
|
|
34
|
-
]);
|
|
35
|
-
export const CalendarTemporalConditionSchema = z.object({
|
|
36
|
-
id: Id,
|
|
37
|
-
kind: z.literal('calendar'),
|
|
38
|
-
ref: Id,
|
|
39
|
-
timezone: z.string().min(1),
|
|
40
|
-
before: ClockTime.optional(),
|
|
41
|
-
after: ClockTime.optional(),
|
|
42
|
-
weekdays: z.array(z.number().int().min(1).max(7)).min(1).optional(),
|
|
43
|
-
dates: z.array(CalendarDate).min(1).optional(),
|
|
44
|
-
dateRange: z.object({
|
|
45
|
-
start: CalendarDate,
|
|
46
|
-
end: CalendarDate,
|
|
47
|
-
}).optional(),
|
|
48
|
-
dayOfMonth: z.array(z.number().int().min(1).max(31)).min(1).optional(),
|
|
49
|
-
}).strict();
|
|
50
|
-
export const AbsenceTemporalConditionSchema = z.object({
|
|
51
|
-
id: Id,
|
|
52
|
-
kind: z.literal('absence'),
|
|
53
|
-
ref: Id,
|
|
54
|
-
afterRef: Id,
|
|
55
|
-
forMs: z.number().int().positive().optional(),
|
|
56
|
-
untilLocalTime: ClockTime.optional(),
|
|
57
|
-
timezone: z.string().min(1).optional(),
|
|
58
|
-
}).superRefine((value, ctx) => {
|
|
59
|
-
if (!value.forMs && !value.untilLocalTime) {
|
|
60
|
-
ctx.addIssue({
|
|
61
|
-
code: 'custom',
|
|
62
|
-
message: 'absence requires forMs or untilLocalTime',
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
if (value.untilLocalTime && !value.timezone) {
|
|
66
|
-
ctx.addIssue({
|
|
67
|
-
code: 'custom',
|
|
68
|
-
message: 'absence untilLocalTime requires timezone',
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
export const TemporalConditionSchema = z.discriminatedUnion('kind', [
|
|
73
|
-
CalendarTemporalConditionSchema,
|
|
74
|
-
AbsenceTemporalConditionSchema,
|
|
75
|
-
z.object({ id: Id, kind: z.literal('not'), ref: Id }),
|
|
76
|
-
z.object({ id: Id, kind: z.literal('unless'), ref: Id }),
|
|
77
|
-
z.object({ id: Id, kind: z.literal('after'), ref: Id, afterRef: Id }),
|
|
78
|
-
z.object({ id: Id, kind: z.literal('until'), ref: Id, beforeRef: Id }),
|
|
79
|
-
z.object({
|
|
80
|
-
id: Id,
|
|
81
|
-
kind: z.literal('debounce'),
|
|
82
|
-
ref: Id,
|
|
83
|
-
forMs: z.number().int().positive(),
|
|
84
|
-
}),
|
|
85
|
-
z.object({
|
|
86
|
-
id: Id,
|
|
87
|
-
kind: z.literal('threshold'),
|
|
88
|
-
ref: Id,
|
|
89
|
-
atLeast: z.number().int().min(1),
|
|
90
|
-
}),
|
|
91
|
-
z.object({
|
|
92
|
-
id: Id,
|
|
93
|
-
kind: z.literal('rate'),
|
|
94
|
-
ref: Id,
|
|
95
|
-
atLeast: z.number().int().min(1),
|
|
96
|
-
perMs: z.number().int().positive(),
|
|
97
|
-
}),
|
|
98
|
-
z.object({
|
|
99
|
-
id: Id,
|
|
100
|
-
kind: z.literal('distinct'),
|
|
101
|
-
ref: Id,
|
|
102
|
-
path: z.string().min(1),
|
|
103
|
-
atLeast: z.number().int().min(1),
|
|
104
|
-
}),
|
|
105
|
-
]);
|
|
106
48
|
export const DerivedEventProjectionSchema = z.object({
|
|
107
49
|
key: z.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,63}$/),
|
|
108
50
|
ref: Id,
|
|
@@ -113,6 +55,7 @@ export const DerivedEventDefinitionSchema = z.object({
|
|
|
113
55
|
contractVersion: z.string().min(1).max(50),
|
|
114
56
|
projections: z.array(DerivedEventProjectionSchema).max(32).default([]),
|
|
115
57
|
constants: z.record(z.string(), Scalar).default({}),
|
|
58
|
+
measures: z.array(PatternMeasureSchema).max(32).default([]),
|
|
116
59
|
}).strict();
|
|
117
60
|
export const DerivedEventEvidenceRefSchema = z.object({
|
|
118
61
|
serverId: Id.nullable(),
|
|
@@ -120,10 +63,15 @@ export const DerivedEventEvidenceRefSchema = z.object({
|
|
|
120
63
|
sourceEventId: Id,
|
|
121
64
|
traceId: Id,
|
|
122
65
|
occurredAt: Timestamp,
|
|
66
|
+
receivedAt: Timestamp.optional(),
|
|
123
67
|
payloadHash: z.string().regex(/^[a-f0-9]{64}$/).nullable(),
|
|
124
68
|
contractVersion: z.string().min(1).nullable().optional(),
|
|
125
69
|
schemaFingerprint: z.string().regex(/^[a-f0-9]{64}$/).nullable().optional(),
|
|
126
70
|
}).strict();
|
|
71
|
+
export const EventTimePolicySchema = z.object({
|
|
72
|
+
allowedLatenessMs: z.number().int().nonnegative()
|
|
73
|
+
.max(1000 * 60 * 60 * 24 * 30),
|
|
74
|
+
}).strict();
|
|
127
75
|
export const TriggerLifecyclePolicySchema = z.object({
|
|
128
76
|
oneShot: z.boolean().default(false),
|
|
129
77
|
maxFirings: z.number().int().min(1).optional(),
|
|
@@ -160,20 +108,6 @@ export const ContinuationContractSchema = z.object({
|
|
|
160
108
|
includeData: true,
|
|
161
109
|
}),
|
|
162
110
|
}).strict();
|
|
163
|
-
export const DeterministicCorrelationSchema = z.object({
|
|
164
|
-
kind: z.literal('same_value'),
|
|
165
|
-
fields: z.array(z.object({
|
|
166
|
-
ref: Id,
|
|
167
|
-
path: z.string().min(1),
|
|
168
|
-
})).min(2),
|
|
169
|
-
});
|
|
170
|
-
export const SemanticCorrelationSchema = z.object({
|
|
171
|
-
instruction: z.string().min(1),
|
|
172
|
-
input: z.array(z.string().min(1)).min(1),
|
|
173
|
-
matchThreshold: z.number().min(0).max(1),
|
|
174
|
-
rejectThreshold: z.number().min(0).max(1),
|
|
175
|
-
uncertain: z.enum(['escalate', 'reject', 'match']).default('escalate'),
|
|
176
|
-
});
|
|
177
111
|
export const CompositeTriggerDefinitionSchema = z.object({
|
|
178
112
|
protocolVersion: z.literal(COMPOSITE_TRIGGER_PROTOCOL_VERSION)
|
|
179
113
|
.default(COMPOSITE_TRIGGER_PROTOCOL_VERSION),
|
|
@@ -182,27 +116,41 @@ export const CompositeTriggerDefinitionSchema = z.object({
|
|
|
182
116
|
triggerId: Id,
|
|
183
117
|
version: z.string().min(1),
|
|
184
118
|
description: z.string().max(500).optional(),
|
|
119
|
+
conditionOnly: z.boolean().default(false),
|
|
185
120
|
continuation: ContinuationContractSchema.optional(),
|
|
186
121
|
clauses: z.array(TriggerClauseSchema).min(1),
|
|
187
|
-
|
|
188
|
-
|
|
122
|
+
pattern: PatternAstV2DefinitionSchema,
|
|
123
|
+
eventTime: EventTimePolicySchema.optional(),
|
|
189
124
|
lifecycle: TriggerLifecyclePolicySchema.default({
|
|
190
125
|
oneShot: false,
|
|
191
126
|
cooldownMs: 0,
|
|
192
127
|
completeOnGoal: false,
|
|
193
128
|
}),
|
|
194
129
|
withinMs: z.number().int().positive().max(1000 * 60 * 60 * 24 * 30),
|
|
195
|
-
correlation: z.object({
|
|
196
|
-
deterministic: DeterministicCorrelationSchema.optional(),
|
|
197
|
-
semantic: SemanticCorrelationSchema.optional(),
|
|
198
|
-
}).optional(),
|
|
199
130
|
target: RuntimeTargetSchema.optional(),
|
|
200
131
|
derivedEvent: DerivedEventDefinitionSchema.optional(),
|
|
201
132
|
}).superRefine((value, ctx) => {
|
|
202
|
-
if (!value.target && !value.derivedEvent) {
|
|
133
|
+
if (!value.target && !value.derivedEvent && !value.conditionOnly) {
|
|
134
|
+
ctx.addIssue({
|
|
135
|
+
code: 'custom',
|
|
136
|
+
message: 'Trigger requires target, derivedEvent, or conditionOnly=true',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (value.conditionOnly &&
|
|
140
|
+
(value.target || value.derivedEvent || value.continuation)) {
|
|
141
|
+
ctx.addIssue({
|
|
142
|
+
code: 'custom',
|
|
143
|
+
message: 'conditionOnly triggers cannot declare target, derivedEvent, or continuation',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (value.conditionOnly &&
|
|
147
|
+
(value.lifecycle.oneShot ||
|
|
148
|
+
value.lifecycle.maxFirings !== undefined ||
|
|
149
|
+
value.lifecycle.cooldownMs > 0 ||
|
|
150
|
+
value.lifecycle.completeOnGoal)) {
|
|
203
151
|
ctx.addIssue({
|
|
204
152
|
code: 'custom',
|
|
205
|
-
message: '
|
|
153
|
+
message: 'conditionOnly triggers cannot use effect-based lifecycle fields',
|
|
206
154
|
});
|
|
207
155
|
}
|
|
208
156
|
if (value.continuation && !value.target) {
|
|
@@ -215,27 +163,38 @@ export const CompositeTriggerDefinitionSchema = z.object({
|
|
|
215
163
|
if (ids.size !== value.clauses.length) {
|
|
216
164
|
ctx.addIssue({ code: 'custom', message: 'Trigger clause ids must be unique' });
|
|
217
165
|
}
|
|
218
|
-
const refs = value.expression.kind === 'count'
|
|
219
|
-
? [value.expression.ref]
|
|
220
|
-
: value.expression.refs;
|
|
221
|
-
for (const ref of refs) {
|
|
222
|
-
if (!ids.has(ref)) {
|
|
223
|
-
ctx.addIssue({
|
|
224
|
-
code: 'custom',
|
|
225
|
-
message: `Expression references unknown clause: ${ref}`,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
for (const field of value.correlation?.deterministic?.fields ?? []) {
|
|
230
|
-
if (!ids.has(field.ref)) {
|
|
231
|
-
ctx.addIssue({
|
|
232
|
-
code: 'custom',
|
|
233
|
-
message: `Correlation references unknown clause: ${field.ref}`,
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
166
|
if (value.derivedEvent) {
|
|
238
167
|
const projectionKeys = new Set();
|
|
168
|
+
const measureKeys = new Set();
|
|
169
|
+
for (const measure of value.derivedEvent.measures ?? []) {
|
|
170
|
+
if (measure.key === '_derived') {
|
|
171
|
+
ctx.addIssue({
|
|
172
|
+
code: 'custom',
|
|
173
|
+
message: 'Derived event measure key _derived is reserved',
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (measureKeys.has(measure.key)) {
|
|
177
|
+
ctx.addIssue({
|
|
178
|
+
code: 'custom',
|
|
179
|
+
message: `Derived event measure key must be unique: ${measure.key}`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (Object.prototype.hasOwnProperty.call(value.derivedEvent.constants, measure.key)) {
|
|
183
|
+
ctx.addIssue({
|
|
184
|
+
code: 'custom',
|
|
185
|
+
message: `Derived event key cannot be both constant and measure: ${measure.key}`,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
for (const ref of collectPatternMeasureRefs(measure)) {
|
|
189
|
+
if (!ids.has(ref)) {
|
|
190
|
+
ctx.addIssue({
|
|
191
|
+
code: 'custom',
|
|
192
|
+
message: `Derived event measure ${measure.key} references unknown clause: ${ref}`,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
measureKeys.add(measure.key);
|
|
197
|
+
}
|
|
239
198
|
for (const projection of value.derivedEvent.projections) {
|
|
240
199
|
if (!ids.has(projection.ref)) {
|
|
241
200
|
ctx.addIssue({
|
|
@@ -243,6 +202,12 @@ export const CompositeTriggerDefinitionSchema = z.object({
|
|
|
243
202
|
message: `Derived event projection references unknown clause: ${projection.ref}`,
|
|
244
203
|
});
|
|
245
204
|
}
|
|
205
|
+
if (measureKeys.has(projection.key)) {
|
|
206
|
+
ctx.addIssue({
|
|
207
|
+
code: 'custom',
|
|
208
|
+
message: `Derived event key cannot be both measure and projection: ${projection.key}`,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
246
211
|
if (projectionKeys.has(projection.key)) {
|
|
247
212
|
ctx.addIssue({
|
|
248
213
|
code: 'custom',
|
|
@@ -270,61 +235,68 @@ export const CompositeTriggerDefinitionSchema = z.object({
|
|
|
270
235
|
});
|
|
271
236
|
}
|
|
272
237
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
ctx.addIssue({
|
|
277
|
-
code: 'custom',
|
|
278
|
-
message: `Temporal condition id must be unique: ${condition.id}`,
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
conditionIds.add(condition.id);
|
|
282
|
-
const conditionRefs = [];
|
|
283
|
-
if ('ref' in condition)
|
|
284
|
-
conditionRefs.push(condition.ref);
|
|
285
|
-
if ('afterRef' in condition)
|
|
286
|
-
conditionRefs.push(condition.afterRef);
|
|
287
|
-
if ('beforeRef' in condition)
|
|
288
|
-
conditionRefs.push(condition.beforeRef);
|
|
289
|
-
for (const ref of conditionRefs) {
|
|
238
|
+
{
|
|
239
|
+
const patternRefs = collectPatternRefs(value.pattern.root);
|
|
240
|
+
for (const ref of patternRefs) {
|
|
290
241
|
if (!ids.has(ref)) {
|
|
291
242
|
ctx.addIssue({
|
|
292
243
|
code: 'custom',
|
|
293
|
-
message: `
|
|
244
|
+
message: `Pattern AST references unknown clause: ${ref}`,
|
|
294
245
|
});
|
|
295
246
|
}
|
|
296
247
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
248
|
+
for (const dimension of value.pattern.partitionBy) {
|
|
249
|
+
const dimensionRefs = new Set();
|
|
250
|
+
for (const field of dimension.fields) {
|
|
251
|
+
if (!ids.has(field.ref)) {
|
|
252
|
+
ctx.addIssue({
|
|
253
|
+
code: 'custom',
|
|
254
|
+
message: `Pattern partition ${dimension.key} references unknown clause: ${field.ref}`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (dimensionRefs.has(field.ref)) {
|
|
258
|
+
ctx.addIssue({
|
|
259
|
+
code: 'custom',
|
|
260
|
+
message: `Pattern partition ${dimension.key} has duplicate field mapping for ${field.ref}`,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
dimensionRefs.add(field.ref);
|
|
306
264
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
265
|
+
for (const ref of patternRefs) {
|
|
266
|
+
if (!dimensionRefs.has(ref)) {
|
|
267
|
+
ctx.addIssue({
|
|
268
|
+
code: 'custom',
|
|
269
|
+
message: `Pattern partition ${dimension.key} does not map pattern ref: ${ref}`,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
314
272
|
}
|
|
315
273
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
274
|
+
const guaranteedPatternRefs = collectGuaranteedPatternBindings(value.pattern.root);
|
|
275
|
+
if (typeof value.pattern.selection.afterMatch === 'object' &&
|
|
276
|
+
!guaranteedPatternRefs.includes(value.pattern.selection.afterMatch.ref)) {
|
|
277
|
+
ctx.addIssue({
|
|
278
|
+
code: 'custom',
|
|
279
|
+
message: `Pattern afterMatch ref is not guaranteed by every match: ${value.pattern.selection.afterMatch.ref}`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
for (const measure of value.derivedEvent?.measures ?? []) {
|
|
283
|
+
for (const ref of collectPatternMeasureRefs(measure)) {
|
|
284
|
+
if (!guaranteedPatternRefs.includes(ref)) {
|
|
285
|
+
ctx.addIssue({
|
|
286
|
+
code: 'custom',
|
|
287
|
+
message: `Derived measure ${measure.key} references non-guaranteed pattern ref: ${ref}`,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
326
290
|
}
|
|
327
291
|
}
|
|
292
|
+
const oversized = collectPatternDurationsMs(value.pattern.root)
|
|
293
|
+
.filter((duration) => duration > value.withinMs);
|
|
294
|
+
if (oversized.length) {
|
|
295
|
+
ctx.addIssue({
|
|
296
|
+
code: 'custom',
|
|
297
|
+
message: `Pattern AST duration exceeds trigger withinMs: ${Math.max(...oversized)} > ${value.withinMs}`,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
328
300
|
}
|
|
329
301
|
});
|
|
330
302
|
export const CorrelatableEventSchema = z.object({
|
|
@@ -332,6 +304,7 @@ export const CorrelatableEventSchema = z.object({
|
|
|
332
304
|
sourceEventId: Id,
|
|
333
305
|
name: z.string().min(1),
|
|
334
306
|
occurredAt: Timestamp,
|
|
307
|
+
receivedAt: Timestamp.optional(),
|
|
335
308
|
provider: z.string().min(1).optional(),
|
|
336
309
|
serverId: Id.optional(),
|
|
337
310
|
subscriptionArguments: z.record(z.string(), z.unknown()).default({}),
|
|
@@ -353,13 +326,14 @@ export const TriggerSourceEventSchema = z.object({
|
|
|
353
326
|
sourceEventId: Id,
|
|
354
327
|
eventName: z.string().min(1),
|
|
355
328
|
occurredAt: Timestamp,
|
|
329
|
+
receivedAt: Timestamp.optional(),
|
|
356
330
|
provider: z.string().min(1).optional(),
|
|
357
331
|
serverId: Id.optional(),
|
|
358
332
|
subscriptionArguments: z.record(z.string(), z.unknown()).default({}),
|
|
359
333
|
payloadHash: z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
360
334
|
data: z.record(z.string(), z.unknown()),
|
|
361
335
|
});
|
|
362
|
-
export const
|
|
336
|
+
export const PatternSemanticDecisionSchema = z.object({
|
|
363
337
|
evaluator: z.string().min(1),
|
|
364
338
|
outcome: z.enum(['match', 'reject', 'uncertain']),
|
|
365
339
|
probability: z.number().min(0).max(1),
|
|
@@ -376,6 +350,17 @@ export const TriggerMatchStatusSchema = z.enum([
|
|
|
376
350
|
'fired',
|
|
377
351
|
'expired',
|
|
378
352
|
]);
|
|
353
|
+
export const PatternMatchStateSchema = z.object({
|
|
354
|
+
version: z.literal('2'),
|
|
355
|
+
role: z.enum(['buffer', 'match']),
|
|
356
|
+
signature: z.string().min(1).optional(),
|
|
357
|
+
maxObservedOccurredAt: Timestamp.optional(),
|
|
358
|
+
completedAt: Timestamp.optional(),
|
|
359
|
+
semanticDecisions: z.array(z.object({
|
|
360
|
+
nodeId: Id,
|
|
361
|
+
decision: PatternSemanticDecisionSchema,
|
|
362
|
+
}).strict()).default([]),
|
|
363
|
+
}).strict();
|
|
379
364
|
export const TriggerMatchRecordSchema = z.object({
|
|
380
365
|
protocolVersion: z.literal(COMPOSITE_TRIGGER_PROTOCOL_VERSION),
|
|
381
366
|
schemaVersion: z.literal(COMPOSITE_TRIGGER_SCHEMA_VERSION),
|
|
@@ -383,12 +368,13 @@ export const TriggerMatchRecordSchema = z.object({
|
|
|
383
368
|
triggerId: Id,
|
|
384
369
|
triggerVersion: z.string().min(1),
|
|
385
370
|
status: TriggerMatchStatusSchema,
|
|
386
|
-
|
|
371
|
+
partitionKey: z.string().nullable(),
|
|
387
372
|
openedAt: Timestamp,
|
|
388
373
|
expiresAt: Timestamp,
|
|
389
374
|
updatedAt: Timestamp,
|
|
390
375
|
sourceEvents: z.array(TriggerSourceEventSchema),
|
|
391
|
-
|
|
376
|
+
semanticDecision: PatternSemanticDecisionSchema.nullable(),
|
|
377
|
+
patternState: PatternMatchStateSchema.optional(),
|
|
392
378
|
firedWakeId: Id.nullable(),
|
|
393
379
|
derivedEventIds: z.array(Id).default([]),
|
|
394
380
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const EVENT_INTELLIGENCE_PROTOCOL: "mcp-event-intelligence";
|
|
2
|
-
export declare const EVENT_INTELLIGENCE_PROTOCOL_VERSION: "0.
|
|
3
|
-
export declare const EVENT_INTELLIGENCE_SCHEMA_VERSION: "ei.v0.
|
|
2
|
+
export declare const EVENT_INTELLIGENCE_PROTOCOL_VERSION: "0.2.0";
|
|
3
|
+
export declare const EVENT_INTELLIGENCE_SCHEMA_VERSION: "ei.v0.2";
|
|
4
4
|
export declare const EVENT_INTELLIGENCE_COMPATIBILITY: {
|
|
5
5
|
readonly mcpEvents: "experimental-ext-triggers-events/design-sketch";
|
|
6
6
|
readonly mcpCore: "2026-07-28";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const EVENT_INTELLIGENCE_PROTOCOL = 'mcp-event-intelligence';
|
|
2
|
-
export const EVENT_INTELLIGENCE_PROTOCOL_VERSION = '0.
|
|
3
|
-
export const EVENT_INTELLIGENCE_SCHEMA_VERSION = 'ei.v0.
|
|
2
|
+
export const EVENT_INTELLIGENCE_PROTOCOL_VERSION = '0.2.0';
|
|
3
|
+
export const EVENT_INTELLIGENCE_SCHEMA_VERSION = 'ei.v0.2';
|
|
4
4
|
export const EVENT_INTELLIGENCE_COMPATIBILITY = {
|
|
5
5
|
mcpEvents: 'experimental-ext-triggers-events/design-sketch',
|
|
6
6
|
mcpCore: '2026-07-28',
|
|
@@ -6,6 +6,7 @@ export async function mcpOccurrenceToCorrelatableEvent(event, input) {
|
|
|
6
6
|
sourceEventId: event.eventId,
|
|
7
7
|
name: event.name,
|
|
8
8
|
occurredAt: event.timestamp,
|
|
9
|
+
...(input.receivedAt ? { receivedAt: input.receivedAt } : {}),
|
|
9
10
|
...(input.provider ? { provider: input.provider } : {}),
|
|
10
11
|
...(input.serverId ? { serverId: input.serverId } : {}),
|
|
11
12
|
subscriptionArguments: input.subscriptionArguments ?? {},
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SemanticDecision, SemanticEvaluator } from '../semantic/types.js';
|
|
2
|
+
import type { TriggerSourceEvent } from '../intelligenceProtocol/triggerSchemas.js';
|
|
3
|
+
import type { PatternAstV2Definition, PatternMeasure } from '../intelligenceProtocol/patternV2Schemas.js';
|
|
4
|
+
export interface PatternV2SemanticDecision {
|
|
5
|
+
nodeId: string;
|
|
6
|
+
decision: SemanticDecision;
|
|
7
|
+
}
|
|
8
|
+
export interface PatternV2Candidate {
|
|
9
|
+
bindings: Record<string, TriggerSourceEvent[]>;
|
|
10
|
+
events: TriggerSourceEvent[];
|
|
11
|
+
startIndex: number;
|
|
12
|
+
endIndex: number;
|
|
13
|
+
pendingUntil?: string;
|
|
14
|
+
semanticDecisions: PatternV2SemanticDecision[];
|
|
15
|
+
}
|
|
16
|
+
export interface PatternV2SemanticTrace {
|
|
17
|
+
nodeId: string;
|
|
18
|
+
candidateSignature: string;
|
|
19
|
+
decision: SemanticDecision;
|
|
20
|
+
}
|
|
21
|
+
export interface PatternV2SemanticCache {
|
|
22
|
+
get(key: string): Promise<SemanticDecision | null> | SemanticDecision | null;
|
|
23
|
+
set(key: string, decision: SemanticDecision): Promise<void> | void;
|
|
24
|
+
}
|
|
25
|
+
export interface PatternV2Evaluation {
|
|
26
|
+
matches: PatternV2Candidate[];
|
|
27
|
+
pending: PatternV2Candidate[];
|
|
28
|
+
semanticEvaluations: number;
|
|
29
|
+
semanticCacheHits: number;
|
|
30
|
+
semanticCacheMisses: number;
|
|
31
|
+
semanticTrace: PatternV2SemanticTrace[];
|
|
32
|
+
truncated: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function evaluatePatternAggregate(candidate: PatternV2Candidate, input: {
|
|
35
|
+
function: 'sum' | 'avg' | 'min' | 'max' | 'count' | 'countDistinct' | 'first' | 'last' | 'nth' | 'stddev' | 'percentile';
|
|
36
|
+
ref: string;
|
|
37
|
+
path?: string;
|
|
38
|
+
nth?: number;
|
|
39
|
+
percentile?: number;
|
|
40
|
+
}): unknown;
|
|
41
|
+
export declare function evaluatePatternMeasure(candidate: PatternV2Candidate, measure: PatternMeasure): unknown;
|
|
42
|
+
export declare function evaluatePatternV2({ definition, events, evaluator, now, allowedLatenessMs, semanticCache, semanticCacheNamespace, }: {
|
|
43
|
+
definition: PatternAstV2Definition;
|
|
44
|
+
events: TriggerSourceEvent[];
|
|
45
|
+
evaluator?: SemanticEvaluator | null;
|
|
46
|
+
now?: Date;
|
|
47
|
+
allowedLatenessMs?: number;
|
|
48
|
+
semanticCache?: PatternV2SemanticCache | null;
|
|
49
|
+
semanticCacheNamespace?: string;
|
|
50
|
+
}): Promise<PatternV2Evaluation>;
|
|
51
|
+
export declare function patternV2CandidateSignature(candidate: PatternV2Candidate): string;
|