mcp-event-intelligence 0.3.1 → 0.5.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 +81 -0
- package/README.md +123 -23
- package/SECURITY.md +4 -4
- package/bin/mcp-event-intelligence.mjs +3 -3
- package/dist/src/composite/engine.d.ts +6 -0
- package/dist/src/composite/engine.js +599 -10
- package/dist/src/composite/matching.d.ts +1 -1
- package/dist/src/composite/matching.js +66 -1
- package/dist/src/intelligenceProtocol/activationSchemas.d.ts +2 -0
- package/dist/src/intelligenceProtocol/activationSchemas.js +1 -0
- package/dist/src/intelligenceProtocol/index.d.ts +9 -2
- package/dist/src/intelligenceProtocol/index.js +5 -1
- package/dist/src/intelligenceProtocol/operatorRegistry.d.ts +567 -0
- package/dist/src/intelligenceProtocol/operatorRegistry.js +477 -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 +6 -0
- package/dist/src/intelligenceProtocol/schemas.js +3 -0
- package/dist/src/intelligenceProtocol/triggerPlanSchemas.d.ts +179 -4
- package/dist/src/intelligenceProtocol/triggerPlanSchemas.js +38 -4
- package/dist/src/intelligenceProtocol/triggerSchemas.d.ts +262 -0
- package/dist/src/intelligenceProtocol/triggerSchemas.js +164 -2
- package/dist/src/mcpEvents/consumer.d.ts +2 -0
- package/dist/src/mcpEvents/consumer.js +2 -0
- package/dist/src/mcpEvents/erpnextProvider.d.ts +0 -2
- package/dist/src/mcpEvents/erpnextProvider.js +0 -3
- package/dist/src/mcpEvents/provider.d.ts +24 -10
- package/dist/src/mcpEvents/provider.js +124 -55
- package/dist/src/mcpEvents/server.d.ts +3 -1
- package/dist/src/mcpEvents/server.js +20 -19
- package/dist/src/patternV2/evaluator.d.ts +43 -0
- package/dist/src/patternV2/evaluator.js +927 -0
- package/dist/src/patternV2/legacyCompiler.d.ts +3 -0
- package/dist/src/patternV2/legacyCompiler.js +184 -0
- package/dist/src/protocol/types.d.ts +1 -0
- package/package.json +5 -2
- package/scripts/host-integration.d.mts +47 -0
- package/scripts/host-integration.mjs +9 -0
- package/scripts/lib/activation-hydrator.mjs +1 -0
- package/scripts/lib/composite-event-consumer.mjs +4 -0
- package/scripts/lib/derived-event-coordinator.mjs +75 -1
- package/scripts/lib/json-schema.mjs +134 -0
- package/scripts/lib/local-event-intelligence-runtime.mjs +1 -0
- package/scripts/lib/mcp-events-client.mjs +798 -253
- package/scripts/lib/mcp-events-compatibility.mjs +54 -0
- package/scripts/lib/persistent-event-store.mjs +68 -9
- package/scripts/lib/trigger-control-plane.mjs +180 -0
- package/scripts/lib/trigger-inspector.mjs +15 -0
- package/scripts/lib/trigger-planner.mjs +213 -12
- package/scripts/mcp-stdio-server.mjs +38 -52
- package/server.json +4 -4
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
export const TRIGGER_LANGUAGE_VERSION = '2';
|
|
2
|
+
export const PREDICATE_OPERATOR = {
|
|
3
|
+
EQ: 'eq',
|
|
4
|
+
NEQ: 'neq',
|
|
5
|
+
CONTAINS: 'contains',
|
|
6
|
+
STARTS_WITH: 'startsWith',
|
|
7
|
+
ENDS_WITH: 'endsWith',
|
|
8
|
+
REGEX: 'regex',
|
|
9
|
+
IN: 'in',
|
|
10
|
+
NOT_IN: 'notIn',
|
|
11
|
+
BETWEEN: 'between',
|
|
12
|
+
EXISTS: 'exists',
|
|
13
|
+
IS_NULL: 'isNull',
|
|
14
|
+
TYPE: 'type',
|
|
15
|
+
GT: 'gt',
|
|
16
|
+
GTE: 'gte',
|
|
17
|
+
LT: 'lt',
|
|
18
|
+
LTE: 'lte',
|
|
19
|
+
};
|
|
20
|
+
export const COMPOSITION_OPERATOR = {
|
|
21
|
+
ALL: 'all',
|
|
22
|
+
ANY: 'any',
|
|
23
|
+
SEQUENCE: 'sequence',
|
|
24
|
+
COUNT: 'count',
|
|
25
|
+
};
|
|
26
|
+
export const TEMPORAL_OPERATOR = {
|
|
27
|
+
CALENDAR: 'calendar',
|
|
28
|
+
ABSENCE: 'absence',
|
|
29
|
+
NOT: 'not',
|
|
30
|
+
UNLESS: 'unless',
|
|
31
|
+
AFTER: 'after',
|
|
32
|
+
UNTIL: 'until',
|
|
33
|
+
DEBOUNCE: 'debounce',
|
|
34
|
+
THRESHOLD: 'threshold',
|
|
35
|
+
RATE: 'rate',
|
|
36
|
+
DISTINCT: 'distinct',
|
|
37
|
+
};
|
|
38
|
+
export const TRIGGER_LANGUAGE_CATALOG = Object.freeze({
|
|
39
|
+
version: TRIGGER_LANGUAGE_VERSION,
|
|
40
|
+
predicates: Object.freeze([
|
|
41
|
+
{
|
|
42
|
+
id: PREDICATE_OPERATOR.EQ,
|
|
43
|
+
description: 'Field equals a scalar value.',
|
|
44
|
+
fields: ['path', 'value'],
|
|
45
|
+
example: { path: 'status', op: 'eq', value: 'open' },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: PREDICATE_OPERATOR.NEQ,
|
|
49
|
+
description: 'Field does not equal a scalar value.',
|
|
50
|
+
fields: ['path', 'value'],
|
|
51
|
+
example: { path: 'status', op: 'neq', value: 'cancelled' },
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: PREDICATE_OPERATOR.CONTAINS,
|
|
55
|
+
description: 'String/array field contains the supplied scalar value.',
|
|
56
|
+
fields: ['path', 'value'],
|
|
57
|
+
example: { path: 'subject', op: 'contains', value: 'invoice' },
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: PREDICATE_OPERATOR.STARTS_WITH,
|
|
61
|
+
description: 'String field starts with the supplied text.',
|
|
62
|
+
fields: ['path', 'value'],
|
|
63
|
+
example: { path: 'subject', op: 'startsWith', value: 'URGENT:' },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: PREDICATE_OPERATOR.ENDS_WITH,
|
|
67
|
+
description: 'String field ends with the supplied text.',
|
|
68
|
+
fields: ['path', 'value'],
|
|
69
|
+
example: { path: 'filename', op: 'endsWith', value: '.pdf' },
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: PREDICATE_OPERATOR.REGEX,
|
|
73
|
+
description: 'String field matches a regular expression.',
|
|
74
|
+
fields: ['path', 'value'],
|
|
75
|
+
optionalFields: ['flags'],
|
|
76
|
+
example: { path: 'code', op: 'regex', value: '^ERR-[0-9]+$' },
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: PREDICATE_OPERATOR.IN,
|
|
80
|
+
description: 'Field equals one of the supplied scalar values.',
|
|
81
|
+
fields: ['path', 'value'],
|
|
82
|
+
example: { path: 'status', op: 'in', value: ['open', 'pending'] },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: PREDICATE_OPERATOR.NOT_IN,
|
|
86
|
+
description: 'Field does not equal any supplied scalar value.',
|
|
87
|
+
fields: ['path', 'value'],
|
|
88
|
+
example: { path: 'status', op: 'notIn', value: ['cancelled', 'closed'] },
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: PREDICATE_OPERATOR.BETWEEN,
|
|
92
|
+
description: 'Comparable field is inside the inclusive range.',
|
|
93
|
+
fields: ['path', 'value'],
|
|
94
|
+
example: { path: 'amount', op: 'between', value: [1000, 5000] },
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: PREDICATE_OPERATOR.EXISTS,
|
|
98
|
+
description: 'Field presence must match the supplied boolean.',
|
|
99
|
+
fields: ['path', 'value'],
|
|
100
|
+
example: { path: 'customerId', op: 'exists', value: true },
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: PREDICATE_OPERATOR.IS_NULL,
|
|
104
|
+
description: 'Field null/undefined state must match the supplied boolean.',
|
|
105
|
+
fields: ['path', 'value'],
|
|
106
|
+
example: { path: 'closedAt', op: 'isNull', value: true },
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: PREDICATE_OPERATOR.TYPE,
|
|
110
|
+
description: 'Field must have the requested JSON type.',
|
|
111
|
+
fields: ['path', 'value'],
|
|
112
|
+
values: ['string', 'number', 'boolean', 'null', 'object', 'array'],
|
|
113
|
+
example: { path: 'total', op: 'type', value: 'number' },
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: PREDICATE_OPERATOR.GT,
|
|
117
|
+
description: 'Numeric field is greater than the supplied number.',
|
|
118
|
+
fields: ['path', 'value'],
|
|
119
|
+
example: { path: 'grand_total', op: 'gt', value: 10000 },
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: PREDICATE_OPERATOR.GTE,
|
|
123
|
+
description: 'Numeric field is greater than or equal to the supplied number.',
|
|
124
|
+
fields: ['path', 'value'],
|
|
125
|
+
example: { path: 'grand_total', op: 'gte', value: 10000 },
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: PREDICATE_OPERATOR.LT,
|
|
129
|
+
description: 'Numeric field is less than the supplied number.',
|
|
130
|
+
fields: ['path', 'value'],
|
|
131
|
+
example: { path: 'stock', op: 'lt', value: 10 },
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: PREDICATE_OPERATOR.LTE,
|
|
135
|
+
description: 'Numeric field is less than or equal to the supplied number.',
|
|
136
|
+
fields: ['path', 'value'],
|
|
137
|
+
example: { path: 'stock', op: 'lte', value: 10 },
|
|
138
|
+
},
|
|
139
|
+
]),
|
|
140
|
+
composition: Object.freeze([
|
|
141
|
+
{
|
|
142
|
+
id: COMPOSITION_OPERATOR.ALL,
|
|
143
|
+
canonicalKind: 'allOf',
|
|
144
|
+
description: 'All referenced events must satisfy the legacy trigger.',
|
|
145
|
+
example: { match: 'all' },
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: COMPOSITION_OPERATOR.ANY,
|
|
149
|
+
canonicalKind: 'anyOf',
|
|
150
|
+
description: 'Any referenced event may satisfy the legacy trigger.',
|
|
151
|
+
example: { match: 'any' },
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: COMPOSITION_OPERATOR.SEQUENCE,
|
|
155
|
+
canonicalKind: 'sequence',
|
|
156
|
+
description: 'Referenced events must occur in event-time order.',
|
|
157
|
+
example: { match: 'sequence' },
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: COMPOSITION_OPERATOR.COUNT,
|
|
161
|
+
canonicalKind: 'count',
|
|
162
|
+
description: 'One referenced event must occur at least N times.',
|
|
163
|
+
example: { match: { kind: 'count', eventId: 'comment', atLeast: 3 } },
|
|
164
|
+
},
|
|
165
|
+
]),
|
|
166
|
+
temporal: Object.freeze([
|
|
167
|
+
{
|
|
168
|
+
id: TEMPORAL_OPERATOR.CALENDAR,
|
|
169
|
+
description: 'Calendar/timezone constraint.',
|
|
170
|
+
fields: ['id', 'kind', 'ref', 'timezone'],
|
|
171
|
+
optionalFields: ['before', 'after', 'weekdays', 'dates', 'dateRange', 'dayOfMonth'],
|
|
172
|
+
example: {
|
|
173
|
+
id: 'business-hours',
|
|
174
|
+
kind: 'calendar',
|
|
175
|
+
ref: 'order',
|
|
176
|
+
timezone: 'Europe/Rome',
|
|
177
|
+
after: '09:00',
|
|
178
|
+
before: '18:00',
|
|
179
|
+
weekdays: [1, 2, 3, 4, 5],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: TEMPORAL_OPERATOR.ABSENCE,
|
|
184
|
+
description: 'Referenced event must remain absent after an anchor for a durable period.',
|
|
185
|
+
fields: ['id', 'kind', 'ref', 'afterRef'],
|
|
186
|
+
oneOf: [['forMs'], ['untilLocalTime', 'timezone']],
|
|
187
|
+
example: {
|
|
188
|
+
id: 'no-errors',
|
|
189
|
+
kind: 'absence',
|
|
190
|
+
ref: 'error',
|
|
191
|
+
afterRef: 'deploy',
|
|
192
|
+
forMs: 600000,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: TEMPORAL_OPERATOR.NOT,
|
|
197
|
+
description: 'Referenced event must not be present.',
|
|
198
|
+
fields: ['id', 'kind', 'ref'],
|
|
199
|
+
example: { id: 'not-cancelled', kind: 'not', ref: 'cancelled' },
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: TEMPORAL_OPERATOR.UNLESS,
|
|
203
|
+
description: 'Condition remains valid unless the referenced event occurs.',
|
|
204
|
+
fields: ['id', 'kind', 'ref'],
|
|
205
|
+
example: { id: 'unless-blocked', kind: 'unless', ref: 'blocked' },
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: TEMPORAL_OPERATOR.AFTER,
|
|
209
|
+
description: 'ref must occur after afterRef.',
|
|
210
|
+
fields: ['id', 'kind', 'ref', 'afterRef'],
|
|
211
|
+
example: { id: 'deploy-after-merge', kind: 'after', ref: 'deploy', afterRef: 'merge' },
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: TEMPORAL_OPERATOR.UNTIL,
|
|
215
|
+
description: 'ref must occur no later than beforeRef.',
|
|
216
|
+
fields: ['id', 'kind', 'ref', 'beforeRef'],
|
|
217
|
+
example: { id: 'approve-before-expiry', kind: 'until', ref: 'approval', beforeRef: 'expiry' },
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: TEMPORAL_OPERATOR.DEBOUNCE,
|
|
221
|
+
description: 'Wait for a quiet period after the latest referenced event.',
|
|
222
|
+
fields: ['id', 'kind', 'ref', 'forMs'],
|
|
223
|
+
example: { id: 'quiet', kind: 'debounce', ref: 'change', forMs: 300000 },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
id: TEMPORAL_OPERATOR.THRESHOLD,
|
|
227
|
+
description: 'At least N occurrences are required.',
|
|
228
|
+
fields: ['id', 'kind', 'ref', 'atLeast'],
|
|
229
|
+
example: { id: 'three-comments', kind: 'threshold', ref: 'comment', atLeast: 3 },
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: TEMPORAL_OPERATOR.RATE,
|
|
233
|
+
description: 'At least N occurrences are required within a duration.',
|
|
234
|
+
fields: ['id', 'kind', 'ref', 'atLeast', 'perMs'],
|
|
235
|
+
example: { id: 'order-spike', kind: 'rate', ref: 'order', atLeast: 5, perMs: 600000 },
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: TEMPORAL_OPERATOR.DISTINCT,
|
|
239
|
+
description: 'At least N distinct values are required.',
|
|
240
|
+
fields: ['id', 'kind', 'ref', 'path', 'atLeast'],
|
|
241
|
+
example: { id: 'three-customers', kind: 'distinct', ref: 'order', path: 'customer', atLeast: 3 },
|
|
242
|
+
},
|
|
243
|
+
]),
|
|
244
|
+
pattern: Object.freeze([
|
|
245
|
+
{
|
|
246
|
+
id: 'event',
|
|
247
|
+
description: 'Bind one discovered event alias.',
|
|
248
|
+
example: { kind: 'event', ref: 'order' },
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
id: 'allOf',
|
|
252
|
+
description: 'Nested conjunction of child patterns.',
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
id: 'anyOf',
|
|
256
|
+
description: 'Nested disjunction of child patterns.',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 'sequence',
|
|
260
|
+
description: 'Ordered child patterns with explicit contiguity.',
|
|
261
|
+
contiguity: ['next', 'followedBy', 'followedByAny'],
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
id: 'repeat',
|
|
265
|
+
description: 'Quantifier with min/max, greedy/lazy preference and explicit internal contiguity.',
|
|
266
|
+
fields: ['child', 'min'],
|
|
267
|
+
optionalFields: ['max', 'mode', 'contiguity'],
|
|
268
|
+
contiguity: ['consecutive', 'relaxed', 'combinations'],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: 'optional',
|
|
272
|
+
description: 'Optional child pattern with greedy/lazy preference.',
|
|
273
|
+
fields: ['child'],
|
|
274
|
+
optionalFields: ['mode'],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: 'notNext',
|
|
278
|
+
description: 'Reject when the immediately next relevant event matches the forbidden pattern.',
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: 'notFollowedBy',
|
|
282
|
+
description: 'Durable bounded negative look-ahead.',
|
|
283
|
+
fields: ['id', 'child', 'forbidden', 'withinMs'],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'window',
|
|
287
|
+
description: 'Apply a streaming window to a nested pattern.',
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: 'compare',
|
|
291
|
+
description: 'Cross-event/value comparison with arithmetic expressions.',
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
id: 'aggregate',
|
|
295
|
+
description: 'Filter a nested pattern using an aggregate.',
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: 'state',
|
|
299
|
+
description: 'Detect state changes, deltas, crossings or stable periods.',
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 'semantic',
|
|
303
|
+
description: 'Vendor-neutral semantic predicate evaluated through SemanticEvaluator; Jev is optional.',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'calendar',
|
|
307
|
+
description: 'Calendar/timezone filter as a v2 wrapper node.',
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: 'absence',
|
|
311
|
+
description: 'Durable absence condition as a v2 wrapper node.',
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
id: 'notPresent',
|
|
315
|
+
description: 'Require an alias to be absent from the active partition buffer.',
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: 'after',
|
|
319
|
+
description: 'Require one bound event to occur after another.',
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: 'until',
|
|
323
|
+
description: 'Require one bound event to occur no later than another.',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: 'debounce',
|
|
327
|
+
description: 'Require a quiet period after the latest referenced event.',
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
id: 'threshold',
|
|
331
|
+
description: 'Require at least N occurrences in the active partition.',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
id: 'rate',
|
|
335
|
+
description: 'Require at least N occurrences within a duration.',
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
id: 'distinct',
|
|
339
|
+
description: 'Require at least N distinct values.',
|
|
340
|
+
},
|
|
341
|
+
]),
|
|
342
|
+
windows: Object.freeze([
|
|
343
|
+
{ id: 'within', description: 'Maximum event-time span.', fields: ['sizeMs'] },
|
|
344
|
+
{ id: 'sliding', description: 'Sliding event-time window.', fields: ['sizeMs'] },
|
|
345
|
+
{ id: 'tumbling', description: 'Non-overlapping fixed event-time windows.', fields: ['sizeMs'], optionalFields: ['offsetMs'] },
|
|
346
|
+
{ id: 'hopping', description: 'Overlapping fixed event-time windows.', fields: ['sizeMs', 'hopMs'], optionalFields: ['offsetMs'] },
|
|
347
|
+
{ id: 'session', description: 'Sessionize by maximum inactivity gap.', fields: ['gapMs'] },
|
|
348
|
+
{ id: 'count', description: 'Bound a candidate by stream-position count.', fields: ['size'] },
|
|
349
|
+
]),
|
|
350
|
+
aggregates: Object.freeze([
|
|
351
|
+
{ id: 'sum', description: 'Sum numeric values.' },
|
|
352
|
+
{ id: 'avg', description: 'Average numeric values.' },
|
|
353
|
+
{ id: 'min', description: 'Minimum numeric value.' },
|
|
354
|
+
{ id: 'max', description: 'Maximum numeric value.' },
|
|
355
|
+
{ id: 'count', description: 'Count occurrences.' },
|
|
356
|
+
{ id: 'countDistinct', description: 'Count distinct values.' },
|
|
357
|
+
{ id: 'first', description: 'First value in event-time order.' },
|
|
358
|
+
{ id: 'last', description: 'Last value in event-time order.' },
|
|
359
|
+
{ id: 'nth', description: 'Nth value in event-time order.' },
|
|
360
|
+
{ id: 'stddev', description: 'Population standard deviation.' },
|
|
361
|
+
{ id: 'percentile', description: 'Interpolated percentile.' },
|
|
362
|
+
]),
|
|
363
|
+
state: Object.freeze([
|
|
364
|
+
{ id: 'changed', description: 'Value changed between the latest two occurrences.' },
|
|
365
|
+
{ id: 'changedFrom', description: 'Value changed from one explicit value to another.' },
|
|
366
|
+
{ id: 'increasedBy', description: 'Numeric increase satisfies a comparator.' },
|
|
367
|
+
{ id: 'decreasedBy', description: 'Numeric decrease satisfies a comparator.' },
|
|
368
|
+
{ id: 'delta', description: 'Numeric delta satisfies a comparator.' },
|
|
369
|
+
{ id: 'percentChange', description: 'Percentage change satisfies a comparator.' },
|
|
370
|
+
{ id: 'stableFor', description: 'Value remained stable for a duration.' },
|
|
371
|
+
{ id: 'crossesAbove', description: 'Value crossed upward through a threshold.' },
|
|
372
|
+
{ id: 'crossesBelow', description: 'Value crossed downward through a threshold.' },
|
|
373
|
+
]),
|
|
374
|
+
selection: Object.freeze([
|
|
375
|
+
{
|
|
376
|
+
id: 'overlap',
|
|
377
|
+
values: ['allow', 'disallow'],
|
|
378
|
+
description: 'Whether emitted matches may share physical source events.',
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
id: 'afterMatch',
|
|
382
|
+
values: [
|
|
383
|
+
'skipPastLast',
|
|
384
|
+
'skipToNext',
|
|
385
|
+
'keepAll',
|
|
386
|
+
{ kind: 'skipToFirst', ref: '<pattern-ref>' },
|
|
387
|
+
{ kind: 'skipToLast', ref: '<pattern-ref>' },
|
|
388
|
+
],
|
|
389
|
+
description: 'How candidate matching and the partition buffer advance after a match. skipToFirst/skipToLast require an explicit pattern ref.',
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
id: 'greedyLazy',
|
|
393
|
+
values: ['greedy', 'lazy'],
|
|
394
|
+
description: 'Quantifier preference when multiple cardinalities are valid.',
|
|
395
|
+
},
|
|
396
|
+
]),
|
|
397
|
+
semantic: Object.freeze([
|
|
398
|
+
{
|
|
399
|
+
id: 'semantic',
|
|
400
|
+
description: 'First-class semantic predicate. The configured SemanticEvaluator executes it; TypeSafe Jev is the bundled optional evaluator.',
|
|
401
|
+
fields: ['id', 'child', 'refs', 'instruction', 'input', 'matchThreshold', 'rejectThreshold'],
|
|
402
|
+
optionalFields: ['uncertain', 'execution.cache', 'execution.timeoutMs', 'execution.onUnavailable'],
|
|
403
|
+
},
|
|
404
|
+
]),
|
|
405
|
+
correlation: Object.freeze([
|
|
406
|
+
{
|
|
407
|
+
id: 'same_value',
|
|
408
|
+
description: 'Legacy deterministic same-value correlation.',
|
|
409
|
+
authoringField: 'correlateBy',
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'semantic',
|
|
413
|
+
description: 'Legacy semantic-correlation compatibility field.',
|
|
414
|
+
authoringField: 'semanticCorrelation',
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: 'partitionBy',
|
|
418
|
+
description: 'Pattern AST v2 partitions stream state by one or more named dimensions.',
|
|
419
|
+
authoringField: 'patternV2.partitionBy',
|
|
420
|
+
},
|
|
421
|
+
]),
|
|
422
|
+
execution: Object.freeze([
|
|
423
|
+
{
|
|
424
|
+
id: 'maxCandidates',
|
|
425
|
+
description: 'Maximum candidate pattern states evaluated per pass.',
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
id: 'maxSemanticEvaluations',
|
|
429
|
+
description: 'Maximum semantic evaluator calls per evaluation pass.',
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
id: 'maxBufferedEvents',
|
|
433
|
+
description: 'Hard upper bound on raw events retained in one trigger partition.',
|
|
434
|
+
},
|
|
435
|
+
]),
|
|
436
|
+
timing: Object.freeze([
|
|
437
|
+
{
|
|
438
|
+
id: 'withinMs',
|
|
439
|
+
description: 'Global bounded retention / maximum pattern horizon.',
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
id: 'allowedLatenessMs',
|
|
443
|
+
description: 'Bounded tolerance for out-of-order event delivery.',
|
|
444
|
+
authoringPath: 'eventTime.allowedLatenessMs',
|
|
445
|
+
},
|
|
446
|
+
]),
|
|
447
|
+
lifecycle: Object.freeze([
|
|
448
|
+
{ id: 'oneShot', description: 'Complete after the first delivered effect.' },
|
|
449
|
+
{ id: 'maxFirings', description: 'Complete after N delivered effects.' },
|
|
450
|
+
{ id: 'cooldownMs', description: 'Minimum processing-time delay between effects.' },
|
|
451
|
+
{ id: 'expiresAt', description: 'Absolute trigger expiry timestamp.' },
|
|
452
|
+
{ id: 'leaseUntil', description: 'Absolute trigger lease boundary.' },
|
|
453
|
+
{ id: 'completeOnGoal', description: 'Complete lifecycle after goal delivery.' },
|
|
454
|
+
]),
|
|
455
|
+
});
|
|
456
|
+
export function describeTriggerLanguage(input = {}) {
|
|
457
|
+
const { category, operator } = input;
|
|
458
|
+
const categories = category
|
|
459
|
+
? [category]
|
|
460
|
+
: Object.keys(TRIGGER_LANGUAGE_CATALOG)
|
|
461
|
+
.filter((key) => key !== 'version');
|
|
462
|
+
const result = {
|
|
463
|
+
version: TRIGGER_LANGUAGE_VERSION,
|
|
464
|
+
authoringSurface: 'TriggerPlanInput',
|
|
465
|
+
planner: 'trigger_plan',
|
|
466
|
+
preferredAuthoring: 'TriggerPlanInput.patternV2',
|
|
467
|
+
canonicalRepresentation: 'CompositeTriggerDefinition + PatternAstV2',
|
|
468
|
+
};
|
|
469
|
+
for (const key of categories) {
|
|
470
|
+
const entries = TRIGGER_LANGUAGE_CATALOG[key];
|
|
471
|
+
const filtered = operator
|
|
472
|
+
? entries.filter((entry) => entry.id === operator)
|
|
473
|
+
: entries;
|
|
474
|
+
result[key] = filtered;
|
|
475
|
+
}
|
|
476
|
+
return result;
|
|
477
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PATTERN_AST_VERSION: "2";
|
|
3
|
+
export declare const PatternValueSelectorSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4
|
+
kind: z.ZodLiteral<"literal">;
|
|
5
|
+
value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodNull]>;
|
|
6
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
7
|
+
kind: z.ZodLiteral<"field">;
|
|
8
|
+
ref: z.ZodString;
|
|
9
|
+
path: z.ZodString;
|
|
10
|
+
select: z.ZodDefault<z.ZodEnum<{
|
|
11
|
+
first: "first";
|
|
12
|
+
last: "last";
|
|
13
|
+
nth: "nth";
|
|
14
|
+
}>>;
|
|
15
|
+
nth: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
17
|
+
kind: z.ZodLiteral<"occurredAt">;
|
|
18
|
+
ref: z.ZodString;
|
|
19
|
+
select: z.ZodDefault<z.ZodEnum<{
|
|
20
|
+
first: "first";
|
|
21
|
+
last: "last";
|
|
22
|
+
nth: "nth";
|
|
23
|
+
}>>;
|
|
24
|
+
nth: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
}, z.core.$strict>], "kind">;
|
|
26
|
+
export type PatternValueSelector = z.infer<typeof PatternValueSelectorSchema>;
|
|
27
|
+
export declare const PatternArithmeticValueSchema: z.ZodType<any>;
|
|
28
|
+
export type PatternArithmeticValue = z.infer<typeof PatternArithmeticValueSchema>;
|
|
29
|
+
export declare const PatternCompareOperatorSchema: z.ZodEnum<{
|
|
30
|
+
type: "type";
|
|
31
|
+
in: "in";
|
|
32
|
+
endsWith: "endsWith";
|
|
33
|
+
startsWith: "startsWith";
|
|
34
|
+
eq: "eq";
|
|
35
|
+
neq: "neq";
|
|
36
|
+
gt: "gt";
|
|
37
|
+
gte: "gte";
|
|
38
|
+
lt: "lt";
|
|
39
|
+
lte: "lte";
|
|
40
|
+
contains: "contains";
|
|
41
|
+
regex: "regex";
|
|
42
|
+
notIn: "notIn";
|
|
43
|
+
between: "between";
|
|
44
|
+
isNull: "isNull";
|
|
45
|
+
}>;
|
|
46
|
+
export declare const AggregateFunctionSchema: z.ZodEnum<{
|
|
47
|
+
first: "first";
|
|
48
|
+
last: "last";
|
|
49
|
+
nth: "nth";
|
|
50
|
+
sum: "sum";
|
|
51
|
+
avg: "avg";
|
|
52
|
+
min: "min";
|
|
53
|
+
max: "max";
|
|
54
|
+
count: "count";
|
|
55
|
+
countDistinct: "countDistinct";
|
|
56
|
+
stddev: "stddev";
|
|
57
|
+
percentile: "percentile";
|
|
58
|
+
}>;
|
|
59
|
+
export declare const PatternWindowSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
60
|
+
type: z.ZodLiteral<"within">;
|
|
61
|
+
sizeMs: z.ZodNumber;
|
|
62
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
63
|
+
type: z.ZodLiteral<"sliding">;
|
|
64
|
+
sizeMs: z.ZodNumber;
|
|
65
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
66
|
+
type: z.ZodLiteral<"tumbling">;
|
|
67
|
+
sizeMs: z.ZodNumber;
|
|
68
|
+
offsetMs: z.ZodDefault<z.ZodNumber>;
|
|
69
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
70
|
+
type: z.ZodLiteral<"hopping">;
|
|
71
|
+
sizeMs: z.ZodNumber;
|
|
72
|
+
hopMs: z.ZodNumber;
|
|
73
|
+
offsetMs: z.ZodDefault<z.ZodNumber>;
|
|
74
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
75
|
+
type: z.ZodLiteral<"session">;
|
|
76
|
+
gapMs: z.ZodNumber;
|
|
77
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
78
|
+
type: z.ZodLiteral<"count">;
|
|
79
|
+
size: z.ZodNumber;
|
|
80
|
+
}, z.core.$strict>], "type">;
|
|
81
|
+
export type PatternWindow = z.infer<typeof PatternWindowSchema>;
|
|
82
|
+
export declare const PatternNodeV2Schema: z.ZodType<any>;
|
|
83
|
+
export type PatternNodeV2 = z.infer<typeof PatternNodeV2Schema>;
|
|
84
|
+
export declare const PatternPartitionDimensionSchema: z.ZodObject<{
|
|
85
|
+
key: z.ZodString;
|
|
86
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
87
|
+
ref: z.ZodString;
|
|
88
|
+
path: z.ZodString;
|
|
89
|
+
}, z.core.$strict>>;
|
|
90
|
+
}, z.core.$strict>;
|
|
91
|
+
export declare const PatternAfterMatchSchema: z.ZodUnion<readonly [z.ZodEnum<{
|
|
92
|
+
skipPastLast: "skipPastLast";
|
|
93
|
+
skipToNext: "skipToNext";
|
|
94
|
+
keepAll: "keepAll";
|
|
95
|
+
}>, z.ZodObject<{
|
|
96
|
+
kind: z.ZodEnum<{
|
|
97
|
+
skipToFirst: "skipToFirst";
|
|
98
|
+
skipToLast: "skipToLast";
|
|
99
|
+
}>;
|
|
100
|
+
ref: z.ZodString;
|
|
101
|
+
}, z.core.$strict>]>;
|
|
102
|
+
export declare const PatternSelectionSchema: z.ZodObject<{
|
|
103
|
+
overlap: z.ZodDefault<z.ZodEnum<{
|
|
104
|
+
allow: "allow";
|
|
105
|
+
disallow: "disallow";
|
|
106
|
+
}>>;
|
|
107
|
+
afterMatch: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
|
|
108
|
+
skipPastLast: "skipPastLast";
|
|
109
|
+
skipToNext: "skipToNext";
|
|
110
|
+
keepAll: "keepAll";
|
|
111
|
+
}>, z.ZodObject<{
|
|
112
|
+
kind: z.ZodEnum<{
|
|
113
|
+
skipToFirst: "skipToFirst";
|
|
114
|
+
skipToLast: "skipToLast";
|
|
115
|
+
}>;
|
|
116
|
+
ref: z.ZodString;
|
|
117
|
+
}, z.core.$strict>]>>;
|
|
118
|
+
maxMatchesPerEvent: z.ZodDefault<z.ZodNumber>;
|
|
119
|
+
}, z.core.$strict>;
|
|
120
|
+
export declare const PatternExecutionPolicySchema: z.ZodObject<{
|
|
121
|
+
maxCandidates: z.ZodDefault<z.ZodNumber>;
|
|
122
|
+
maxSemanticEvaluations: z.ZodDefault<z.ZodNumber>;
|
|
123
|
+
maxBufferedEvents: z.ZodDefault<z.ZodNumber>;
|
|
124
|
+
}, z.core.$strict>;
|
|
125
|
+
export declare const PatternMeasureSchema: z.ZodObject<{
|
|
126
|
+
key: z.ZodString;
|
|
127
|
+
expression: z.ZodUnion<readonly [z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>, z.ZodObject<{
|
|
128
|
+
kind: z.ZodLiteral<"aggregate">;
|
|
129
|
+
function: z.ZodEnum<{
|
|
130
|
+
first: "first";
|
|
131
|
+
last: "last";
|
|
132
|
+
nth: "nth";
|
|
133
|
+
sum: "sum";
|
|
134
|
+
avg: "avg";
|
|
135
|
+
min: "min";
|
|
136
|
+
max: "max";
|
|
137
|
+
count: "count";
|
|
138
|
+
countDistinct: "countDistinct";
|
|
139
|
+
stddev: "stddev";
|
|
140
|
+
percentile: "percentile";
|
|
141
|
+
}>;
|
|
142
|
+
ref: z.ZodString;
|
|
143
|
+
path: z.ZodOptional<z.ZodString>;
|
|
144
|
+
nth: z.ZodOptional<z.ZodNumber>;
|
|
145
|
+
percentile: z.ZodOptional<z.ZodNumber>;
|
|
146
|
+
}, z.core.$strict>]>;
|
|
147
|
+
}, z.core.$strict>;
|
|
148
|
+
export declare function collectGuaranteedPatternBindings(node: PatternNodeV2): string[];
|
|
149
|
+
export declare const PatternAstV2DefinitionSchema: z.ZodObject<{
|
|
150
|
+
version: z.ZodDefault<z.ZodLiteral<"2">>;
|
|
151
|
+
root: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
|
|
152
|
+
partitionBy: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
153
|
+
key: z.ZodString;
|
|
154
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
155
|
+
ref: z.ZodString;
|
|
156
|
+
path: z.ZodString;
|
|
157
|
+
}, z.core.$strict>>;
|
|
158
|
+
}, z.core.$strict>>>;
|
|
159
|
+
selection: z.ZodDefault<z.ZodObject<{
|
|
160
|
+
overlap: z.ZodDefault<z.ZodEnum<{
|
|
161
|
+
allow: "allow";
|
|
162
|
+
disallow: "disallow";
|
|
163
|
+
}>>;
|
|
164
|
+
afterMatch: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
|
|
165
|
+
skipPastLast: "skipPastLast";
|
|
166
|
+
skipToNext: "skipToNext";
|
|
167
|
+
keepAll: "keepAll";
|
|
168
|
+
}>, z.ZodObject<{
|
|
169
|
+
kind: z.ZodEnum<{
|
|
170
|
+
skipToFirst: "skipToFirst";
|
|
171
|
+
skipToLast: "skipToLast";
|
|
172
|
+
}>;
|
|
173
|
+
ref: z.ZodString;
|
|
174
|
+
}, z.core.$strict>]>>;
|
|
175
|
+
maxMatchesPerEvent: z.ZodDefault<z.ZodNumber>;
|
|
176
|
+
}, z.core.$strict>>;
|
|
177
|
+
execution: z.ZodDefault<z.ZodObject<{
|
|
178
|
+
maxCandidates: z.ZodDefault<z.ZodNumber>;
|
|
179
|
+
maxSemanticEvaluations: z.ZodDefault<z.ZodNumber>;
|
|
180
|
+
maxBufferedEvents: z.ZodDefault<z.ZodNumber>;
|
|
181
|
+
}, z.core.$strict>>;
|
|
182
|
+
}, z.core.$strict>;
|
|
183
|
+
export type PatternAfterMatch = z.infer<typeof PatternAfterMatchSchema>;
|
|
184
|
+
export type PatternAstV2Definition = z.infer<typeof PatternAstV2DefinitionSchema>;
|
|
185
|
+
export type PatternMeasure = z.infer<typeof PatternMeasureSchema>;
|
|
186
|
+
export declare function collectPatternMeasureRefs(measure: PatternMeasure): string[];
|
|
187
|
+
export declare function collectPatternDurationsMs(node: PatternNodeV2): number[];
|
|
188
|
+
export declare function collectPatternRefs(node: PatternNodeV2): string[];
|