@agentix-e/nl2spel 1.2.1 → 1.2.2

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 (75) hide show
  1. package/dist/index.cjs +3040 -0
  2. package/dist/index.d.cts +908 -0
  3. package/dist/index.d.ts +908 -28
  4. package/dist/index.js +2999 -24
  5. package/package.json +16 -5
  6. package/dist/context/context-extractor.d.ts +0 -86
  7. package/dist/context/context-extractor.d.ts.map +0 -1
  8. package/dist/context/context-extractor.js +0 -181
  9. package/dist/context/context-extractor.js.map +0 -1
  10. package/dist/context/schema-formatter.d.ts +0 -20
  11. package/dist/context/schema-formatter.d.ts.map +0 -1
  12. package/dist/context/schema-formatter.js +0 -104
  13. package/dist/context/schema-formatter.js.map +0 -1
  14. package/dist/engine/nl2spel-engine.d.ts +0 -145
  15. package/dist/engine/nl2spel-engine.d.ts.map +0 -1
  16. package/dist/engine/nl2spel-engine.js +0 -130
  17. package/dist/engine/nl2spel-engine.js.map +0 -1
  18. package/dist/index.d.ts.map +0 -1
  19. package/dist/index.js.map +0 -1
  20. package/dist/pattern/builtin-patterns.d.ts +0 -12
  21. package/dist/pattern/builtin-patterns.d.ts.map +0 -1
  22. package/dist/pattern/builtin-patterns.js +0 -812
  23. package/dist/pattern/builtin-patterns.js.map +0 -1
  24. package/dist/pattern/pattern-definition.d.ts +0 -49
  25. package/dist/pattern/pattern-definition.d.ts.map +0 -1
  26. package/dist/pattern/pattern-definition.js +0 -2
  27. package/dist/pattern/pattern-definition.js.map +0 -1
  28. package/dist/pattern/pattern-matcher.d.ts +0 -55
  29. package/dist/pattern/pattern-matcher.d.ts.map +0 -1
  30. package/dist/pattern/pattern-matcher.js +0 -216
  31. package/dist/pattern/pattern-matcher.js.map +0 -1
  32. package/dist/provider/llm-provider.d.ts +0 -146
  33. package/dist/provider/llm-provider.d.ts.map +0 -1
  34. package/dist/provider/llm-provider.js +0 -2
  35. package/dist/provider/llm-provider.js.map +0 -1
  36. package/dist/provider/provider-registry.d.ts +0 -28
  37. package/dist/provider/provider-registry.d.ts.map +0 -1
  38. package/dist/provider/provider-registry.js +0 -65
  39. package/dist/provider/provider-registry.js.map +0 -1
  40. package/dist/strategy/strategy-router.d.ts +0 -79
  41. package/dist/strategy/strategy-router.d.ts.map +0 -1
  42. package/dist/strategy/strategy-router.js +0 -182
  43. package/dist/strategy/strategy-router.js.map +0 -1
  44. package/dist/template/intent-classifier.d.ts +0 -56
  45. package/dist/template/intent-classifier.d.ts.map +0 -1
  46. package/dist/template/intent-classifier.js +0 -251
  47. package/dist/template/intent-classifier.js.map +0 -1
  48. package/dist/template/nl-intent.d.ts +0 -38
  49. package/dist/template/nl-intent.d.ts.map +0 -1
  50. package/dist/template/nl-intent.js +0 -39
  51. package/dist/template/nl-intent.js.map +0 -1
  52. package/dist/template/prompts/prompt-builder.d.ts +0 -20
  53. package/dist/template/prompts/prompt-builder.d.ts.map +0 -1
  54. package/dist/template/prompts/prompt-builder.js +0 -243
  55. package/dist/template/prompts/prompt-builder.js.map +0 -1
  56. package/dist/template/template-engine.d.ts +0 -27
  57. package/dist/template/template-engine.d.ts.map +0 -1
  58. package/dist/template/template-engine.js +0 -378
  59. package/dist/template/template-engine.js.map +0 -1
  60. package/dist/utils/chinese-number-parser.d.ts +0 -30
  61. package/dist/utils/chinese-number-parser.d.ts.map +0 -1
  62. package/dist/utils/chinese-number-parser.js +0 -92
  63. package/dist/utils/chinese-number-parser.js.map +0 -1
  64. package/dist/validation/auto-fixer.d.ts +0 -13
  65. package/dist/validation/auto-fixer.d.ts.map +0 -1
  66. package/dist/validation/auto-fixer.js +0 -110
  67. package/dist/validation/auto-fixer.js.map +0 -1
  68. package/dist/validation/self-correction-loop.d.ts +0 -46
  69. package/dist/validation/self-correction-loop.d.ts.map +0 -1
  70. package/dist/validation/self-correction-loop.js +0 -132
  71. package/dist/validation/self-correction-loop.js.map +0 -1
  72. package/dist/validation/validation-pipeline.d.ts +0 -81
  73. package/dist/validation/validation-pipeline.d.ts.map +0 -1
  74. package/dist/validation/validation-pipeline.js +0 -306
  75. package/dist/validation/validation-pipeline.js.map +0 -1
@@ -1,812 +0,0 @@
1
- /**
2
- * Built-in pattern library — covers ≥80% Easy scenarios, 63 PatternDefinitions.
3
- *
4
- * Core design:
5
- * 1. All patterns use named capture groups `(?<field>…)` or `(?<value>…)` to extract parameters
6
- * 2. Separate Chinese/English patterns (don't mix keywords, avoids cross-language false matches)
7
- * 3. High-specificity patterns have higher priority ("not empty" > "not")
8
- * 4. Sorted by priority descending
9
- */
10
- export const BUILTIN_PATTERNS = [
11
- // ================================================================
12
- // P93+: Pure English numeric comparison (covers "amount > 500" etc.)
13
- // ================================================================
14
- {
15
- id: 'EN-CMP-GT',
16
- match: /^(?<field>\w+)\s*>\s*(?<value>\d+(?:\.\d+)?)/,
17
- spelTemplate: '#{field} > {value}',
18
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
19
- priority: 93,
20
- tags: ['comparison', 'gt', 'english'],
21
- examples: [{ nl: 'amount > 500', spel: '#amount > 500' }],
22
- difficulty: 'easy',
23
- confidence: 0.98,
24
- },
25
- {
26
- id: 'EN-CMP-LT',
27
- match: /^(?<field>\w+)\s*(?:less\s+than|lower\s+than|<)\s*(?<value>\d+(?:\.\d+)?)/i,
28
- spelTemplate: '#{field} < {value}',
29
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
30
- priority: 94,
31
- tags: ['comparison', 'lt', 'english'],
32
- examples: [
33
- { nl: 'amount less than 100', spel: '#amount < 100' },
34
- { nl: 'price lower than 50', spel: '#price < 50' },
35
- ],
36
- difficulty: 'easy',
37
- confidence: 0.98,
38
- },
39
- {
40
- id: 'EN-CMP-GE',
41
- match: /^(?<field>\w+)\s*>=\s*(?<value>\d+(?:\.\d+)?)/,
42
- spelTemplate: '#{field} >= {value}',
43
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
44
- priority: 93,
45
- tags: ['comparison', 'ge', 'english'],
46
- examples: [{ nl: 'amount >= 50', spel: '#amount >= 50' }],
47
- difficulty: 'easy',
48
- confidence: 0.98,
49
- },
50
- {
51
- id: 'EN-CMP-LE',
52
- match: /^(?<field>\w+)\s*<=\s*(?<value>\d+(?:\.\d+)?)/,
53
- spelTemplate: '#{field} <= {value}',
54
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
55
- priority: 93,
56
- tags: ['comparison', 'le', 'english'],
57
- examples: [{ nl: 'amount <= 200', spel: '#amount <= 200' }],
58
- difficulty: 'easy',
59
- confidence: 0.98,
60
- },
61
- // ================================================================
62
- // Group 1: Null / Empty — pri 97-96 (highest specificity)
63
- // ================================================================
64
- {
65
- id: 'CN-NULL-NOT',
66
- match: /^(?<field>\S+?)\s*(?:不为空|不是空的|有值|存在|不为null)$/,
67
- spelTemplate: '#{field} != null',
68
- slots: {},
69
- priority: 98,
70
- tags: ['null', 'isNotNull'],
71
- examples: [{ nl: '备注不为空', spel: '#备注 != null' }],
72
- difficulty: 'easy',
73
- confidence: 0.98,
74
- },
75
- {
76
- id: 'CN-NULL-IS',
77
- match: /^(?<field>\S+?)\s*(?:为空|是空的|不存在|无值|为null)$/,
78
- spelTemplate: '#{field} == null',
79
- slots: {},
80
- priority: 97,
81
- tags: ['null', 'isNull'],
82
- examples: [{ nl: '备注为空', spel: '#备注 == null' }],
83
- difficulty: 'easy',
84
- confidence: 0.98,
85
- },
86
- {
87
- id: 'EN-NULL-IS',
88
- match: /^(?<field>\w+)\s+is\s+(?:null|empty)$/i,
89
- spelTemplate: '#{field} == null',
90
- slots: {},
91
- priority: 96,
92
- tags: ['null', 'isNull', 'english'],
93
- examples: [{ nl: 'remark is null', spel: '#remark == null' }],
94
- difficulty: 'easy',
95
- confidence: 0.98,
96
- },
97
- {
98
- id: 'EN-NULL-NOT',
99
- match: /^(?<field>\w+)\s+is\s+not\s+(?:null|empty)$/i,
100
- spelTemplate: '#{field} != null',
101
- slots: {},
102
- priority: 96,
103
- tags: ['null', 'isNotNull', 'english'],
104
- examples: [{ nl: 'remark is not null', spel: '#remark != null' }],
105
- difficulty: 'easy',
106
- confidence: 0.98,
107
- },
108
- // ================================================================
109
- // Group 2: Chinese numeric comparison — pri 93
110
- // ================================================================
111
- {
112
- id: 'CN-CMP-GE',
113
- match: /^(?<field>[^\s,,、]+?)\s*(?:金额|值)?\s*(?:不小于|不低于|大于等于|>=)\s*(?<value>\d+(?:\.\d+)?)/,
114
- spelTemplate: '#{field} >= {value}',
115
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
116
- priority: 93,
117
- tags: ['comparison', 'ge', 'chinese'],
118
- examples: [{ nl: '金额不小于100', spel: '#金额 >= 100' }],
119
- difficulty: 'easy',
120
- confidence: 0.95,
121
- },
122
- {
123
- id: 'CN-CMP-LE',
124
- match: /^(?<field>[^\s,,、]+?)\s*(?:金额|值)?\s*(?:不大于|不超过|小于等于|<=)\s*(?<value>\d+(?:\.\d+)?)/,
125
- spelTemplate: '#{field} <= {value}',
126
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
127
- priority: 93,
128
- tags: ['comparison', 'le', 'chinese'],
129
- examples: [{ nl: '金额不超过500', spel: '#金额 <= 500' }],
130
- difficulty: 'easy',
131
- confidence: 0.95,
132
- },
133
- {
134
- id: 'CN-CMP-GT',
135
- match: /^(?<field>[^\s,,、]+?)\s*(?:金额|值|数量|价格)?\s*(?:大于|超过|高于)\s*(?<value>\d+(?:\.\d+)?)/,
136
- spelTemplate: '#{field} > {value}',
137
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
138
- priority: 92,
139
- tags: ['comparison', 'gt', 'chinese'],
140
- examples: [{ nl: '订单金额大于1000', spel: '#订单金额 > 1000' }],
141
- difficulty: 'easy',
142
- confidence: 0.95,
143
- },
144
- {
145
- id: 'CN-CMP-LT',
146
- match: /^(?<field>[^\s,,、]+?)\s*(?:金额|值|数量|价格)?\s*(?:小于|低于|不到)\s*(?<value>\d+(?:\.\d+)?)/,
147
- spelTemplate: '#{field} < {value}',
148
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
149
- priority: 92,
150
- tags: ['comparison', 'lt', 'chinese'],
151
- examples: [{ nl: '订单金额小于500', spel: '#订单金额 < 500' }],
152
- difficulty: 'easy',
153
- confidence: 0.95,
154
- },
155
- // ================================================================
156
- // Group 3: String/status equality — pri 91
157
- // ================================================================
158
- {
159
- id: 'CN-EQ-STATUS',
160
- match: /^(?<field>[^\s,,、]+?)\s*(?:状态|类型)?\s*(?:等于|是|为)\s*(?<value>[^\s,,、]+)$/,
161
- spelTemplate: "#{field} == '{value}'",
162
- slots: { value: { key: 'value', type: 'string' } },
163
- priority: 85,
164
- tags: ['comparison', 'eq', 'string'],
165
- examples: [{ nl: '订单状态是已发货', spel: "#订单状态 == '已发货'" }],
166
- difficulty: 'easy',
167
- confidence: 0.95,
168
- },
169
- {
170
- id: 'EN-EQ-STRING',
171
- match: /\b(?<field>\w+)\s+(?:equals?|==)\s+(?<value>[a-zA-Z_]\w*)/i,
172
- spelTemplate: "#{field} == '{value}'",
173
- slots: { value: { key: 'value', type: 'string' } },
174
- priority: 91,
175
- tags: ['comparison', 'eq', 'string', 'english'],
176
- examples: [{ nl: 'status equals completed', spel: "#status == 'completed'" }],
177
- difficulty: 'easy',
178
- confidence: 0.95,
179
- },
180
- // CN: "order status is not cancelled" — must be before NOT pattern
181
- {
182
- id: 'CN-NE-STATUS',
183
- match: /^(?<field>[^\s,,、]+?)\s*(?:状态|类型)?\s*(?:不等于|!=|不是)\s*(?<value>[^\s,,、]+)$/,
184
- spelTemplate: "#{field} != '{value}'",
185
- slots: { value: { key: 'value', type: 'string' } },
186
- priority: 91,
187
- tags: ['comparison', 'ne', 'string'],
188
- examples: [{ nl: '订单状态不是已取消', spel: "#订单状态 != '已取消'" }],
189
- difficulty: 'easy',
190
- confidence: 0.95,
191
- },
192
- {
193
- id: 'EN-NE-STRING',
194
- match: /\b(?<field>\w+)\s*!=\s*(?<value>[a-zA-Z_]\w*)/i,
195
- spelTemplate: "#{field} != '{value}'",
196
- slots: { value: { key: 'value', type: 'string' } },
197
- priority: 91,
198
- tags: ['comparison', 'ne', 'string', 'english'],
199
- examples: [{ nl: 'status != cancelled', spel: "#status != 'cancelled'" }],
200
- difficulty: 'easy',
201
- confidence: 0.95,
202
- },
203
- // CN/EN: count equality
204
- {
205
- id: 'CN-EQ-COUNT',
206
- match: /^(?<field>[^\s,,、]+?)\s*(?:数量|个数|计数)?\s*(?:等于|==)\s*(?<value>\d+)/,
207
- spelTemplate: '#{field} == {value}',
208
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
209
- priority: 91,
210
- tags: ['comparison', 'eq', 'number'],
211
- examples: [{ nl: '数量等于5', spel: '#数量 == 5' }],
212
- difficulty: 'easy',
213
- confidence: 0.95,
214
- },
215
- {
216
- id: 'EN-EQ-NUMBER',
217
- match: /\b(?<field>\w+)\s+(?:equals?|==)\s+(?<value>\d+)/i,
218
- spelTemplate: '#{field} == {value}',
219
- slots: { value: { key: 'value', type: 'number', transform: 'toNumber' } },
220
- priority: 91,
221
- tags: ['comparison', 'eq', 'number', 'english'],
222
- examples: [{ nl: 'count equals 10', spel: '#count == 10' }],
223
- difficulty: 'easy',
224
- confidence: 0.95,
225
- },
226
- // ================================================================
227
- // Group 4: Permission checks — pri 88
228
- // ================================================================
229
- {
230
- id: 'CN-PERM-ROLE',
231
- match: /^(?<field>[^\s,,、]+?)\s*(?:是|拥有|有)\s*(?<role>[^\s,,、]+?)(?:角色|权限)?$/,
232
- spelTemplate: "hasRole('{role}')",
233
- slots: { role: { key: 'role', type: 'string' } },
234
- priority: 86,
235
- tags: ['permission', 'hasRole'],
236
- examples: [{ nl: '用户是管理员', spel: "hasRole('管理员')" }],
237
- difficulty: 'easy',
238
- confidence: 0.9,
239
- },
240
- {
241
- id: 'EN-PERM-ROLE',
242
- match: /\buser\s+(?:has|is)\s+(?<role>[a-zA-Z_]+)\s*(?:role)?$/i,
243
- spelTemplate: "hasRole('{role}')",
244
- slots: { role: { key: 'role', type: 'string' } },
245
- priority: 88,
246
- tags: ['permission', 'hasRole', 'english'],
247
- examples: [{ nl: 'user has admin role', spel: "hasRole('admin')" }],
248
- difficulty: 'easy',
249
- confidence: 0.9,
250
- },
251
- {
252
- id: 'CN-PERM-PERM',
253
- match: /^(?<field>[^\s,,、]+)\s*(?:可以|能够|允许|may|can)\s+(?<permission>.+)$/i,
254
- spelTemplate: "hasPermission('{permission}')",
255
- slots: { permission: { key: 'permission', type: 'string' } },
256
- priority: 88,
257
- tags: ['permission', 'hasPermission'],
258
- examples: [{ nl: '用户可以删除订单', spel: "hasPermission('删除订单')" }],
259
- difficulty: 'easy',
260
- confidence: 0.9,
261
- },
262
- {
263
- id: 'EN-PERM-PERM',
264
- match: /\buser\s+(?:can|may|is\s+allowed\s+to)\s+(?<permission>\w+)/i,
265
- spelTemplate: "hasPermission('{permission}')",
266
- slots: { permission: { key: 'permission', type: 'string' } },
267
- priority: 88,
268
- tags: ['permission', 'hasPermission', 'english'],
269
- examples: [{ nl: 'user can delete', spel: "hasPermission('delete')" }],
270
- difficulty: 'easy',
271
- confidence: 0.9,
272
- },
273
- // ================================================================
274
- // Group 5: Collection operations — pri 85-89
275
- // ================================================================
276
- {
277
- id: 'CN-COLL-EMPTY',
278
- match: /^(?<field>[^\s,,、]+?)\s*(?:列表|数组|集合)?\s*(?:为空|是空的|没有|无)\s*(?:元素|数据|项)?$/,
279
- spelTemplate: '#{field}.isEmpty()',
280
- slots: {},
281
- priority: 89,
282
- tags: ['collection', 'isEmpty'],
283
- examples: [{ nl: '订单列表为空', spel: '#订单列表.isEmpty()' }],
284
- difficulty: 'easy',
285
- confidence: 0.98,
286
- },
287
- {
288
- id: 'EN-COLL-EMPTY',
289
- match: /^(?<field>\w+)\s+is\s+empty$/i,
290
- spelTemplate: '#{field}.isEmpty()',
291
- slots: {},
292
- priority: 88,
293
- tags: ['collection', 'isEmpty', 'english'],
294
- examples: [{ nl: 'items is empty', spel: '#items.isEmpty()' }],
295
- difficulty: 'easy',
296
- confidence: 0.98,
297
- },
298
- {
299
- id: 'CN-COLL-NOTEMPTY',
300
- match: /^(?<field>[^\s,,、]+?)\s*(?:列表|数组|集合)?\s*(?:不为空|有)\s*(?:元素|数据|项)?$/,
301
- spelTemplate: '!#{field}.isEmpty()',
302
- slots: {},
303
- priority: 89,
304
- tags: ['collection', 'isNotEmpty'],
305
- examples: [{ nl: '订单列表有数据', spel: '!#订单列表.isEmpty()' }],
306
- difficulty: 'easy',
307
- confidence: 0.95,
308
- },
309
- {
310
- id: 'EN-COLL-NOTEMPTY',
311
- match: /^(?<field>\w+)\s+(?:has\s+items|is\s+not\s+empty)$/i,
312
- spelTemplate: '!#{field}.isEmpty()',
313
- slots: {},
314
- priority: 86,
315
- tags: ['collection', 'isNotEmpty', 'english'],
316
- examples: [{ nl: 'items is not empty', spel: '!#items.isEmpty()' }],
317
- difficulty: 'easy',
318
- confidence: 0.95,
319
- },
320
- {
321
- id: 'CN-COLL-CONTAINS',
322
- match: /^(?<field>[^\s,,、]+?)\s*(?:列表|数组|集合)?\s*(?:中\s*)?(?:包含|含有|有)\s*(?<element>[^\s,,、]+)/,
323
- spelTemplate: "#{field}.contains('{element}')",
324
- slots: { element: { key: 'element', type: 'string' } },
325
- priority: 87,
326
- tags: ['collection', 'contains'],
327
- examples: [{ nl: '标签列表中包含VIP', spel: "#标签列表.contains('VIP')" }],
328
- difficulty: 'easy',
329
- confidence: 0.95,
330
- },
331
- {
332
- id: 'EN-COLL-CONTAINS',
333
- match: /\b(?<field>\w+)\s+(?:contains?|includes?)\s+(?<element>\S+)/i,
334
- spelTemplate: "#{field}.contains('{element}')",
335
- slots: { element: { key: 'element', type: 'string' } },
336
- priority: 86,
337
- tags: ['collection', 'contains', 'english'],
338
- examples: [{ nl: 'tags contains premium', spel: "#tags.contains('premium')" }],
339
- difficulty: 'easy',
340
- confidence: 0.95,
341
- },
342
- {
343
- id: 'CN-COLL-SIZE',
344
- match: /^(?<field>[^\s,,、]+?)\s*(?:列表|数组|集合)?\s*(?:数量|个数|大小|长度)\s*(?<op>大于|>|超过|小于|<|等于|==)\s*(?<value>\d+)/,
345
- spelTemplate: '#{field}.size() {op} {value}',
346
- slots: {
347
- value: { key: 'value', type: 'number', transform: 'toNumber' },
348
- op: { key: 'op', type: 'literal' },
349
- },
350
- priority: 85,
351
- tags: ['collection', 'size'],
352
- examples: [{ nl: '订单列表数量大于10', spel: '#订单列表.size() > 10' }],
353
- difficulty: 'medium',
354
- confidence: 0.85,
355
- },
356
- {
357
- id: 'EN-COLL-SIZE',
358
- match: /\b(?<field>\w+)\s+(?:size|length|count)\s*(?<op>>|<|>=|<=|==)\s*(?<value>\d+)/i,
359
- spelTemplate: '#{field}.size() {op} {value}',
360
- slots: {
361
- value: { key: 'value', type: 'number', transform: 'toNumber' },
362
- op: { key: 'op', type: 'literal' },
363
- },
364
- priority: 84,
365
- tags: ['collection', 'size', 'english'],
366
- examples: [{ nl: 'items size > 5', spel: '#items.size() > 5' }],
367
- difficulty: 'medium',
368
- confidence: 0.9,
369
- },
370
- // ================================================================
371
- // Group 6: String operations — pri 82-85
372
- // ================================================================
373
- {
374
- id: 'CN-STR-CONTAINS',
375
- match: /^(?<field>[^\s,,、]+?)(?:备注|名称|描述|标签|标题)?\s*(?:包含|含有|包括)\s*(?<substr>[^\s,,、]+)/,
376
- spelTemplate: "#{field}.contains('{substr}')",
377
- slots: { substr: { key: 'substr', type: 'string' } },
378
- priority: 85,
379
- tags: ['string', 'contains'],
380
- examples: [{ nl: '订单备注包含加急', spel: "#订单备注.contains('加急')" }],
381
- difficulty: 'easy',
382
- confidence: 0.95,
383
- },
384
- {
385
- id: 'EN-STR-CONTAINS',
386
- match: /\b(?<field>\w+)\s+(?:contains?|includes?)\s+(?<substr>\S+)/i,
387
- spelTemplate: "#{field}.contains('{substr}')",
388
- slots: { substr: { key: 'substr', type: 'string' } },
389
- priority: 84,
390
- tags: ['string', 'contains', 'english'],
391
- examples: [{ nl: 'name contains test', spel: "#name.contains('test')" }],
392
- difficulty: 'easy',
393
- confidence: 0.95,
394
- },
395
- {
396
- id: 'CN-STR-STARTS',
397
- match: /^(?<field>[^\s,,、]+?)\s*以\s*(?<prefix>[^\s,,、]+)\s*(?:开头|开始)/,
398
- spelTemplate: "#{field}.startsWith('{prefix}')",
399
- slots: { prefix: { key: 'prefix', type: 'string' } },
400
- priority: 85,
401
- tags: ['string', 'startsWith'],
402
- examples: [{ nl: '订单号以ORD开头', spel: "#订单号.startsWith('ORD')" }],
403
- difficulty: 'easy',
404
- confidence: 0.95,
405
- },
406
- {
407
- id: 'EN-STR-STARTS',
408
- match: /\b(?<field>\w+)\s+(?:startsWith|starts\s+with)\s+(?<prefix>\S+)/i,
409
- spelTemplate: "#{field}.startsWith('{prefix}')",
410
- slots: { prefix: { key: 'prefix', type: 'string' } },
411
- priority: 84,
412
- tags: ['string', 'startsWith', 'english'],
413
- examples: [{ nl: 'id starts with ORD', spel: "#id.startsWith('ORD')" }],
414
- difficulty: 'easy',
415
- confidence: 0.95,
416
- },
417
- {
418
- id: 'CN-STR-ENDS',
419
- match: /^(?<field>[^\s,,、]+?)\s*以\s*(?<suffix>[^\s,,、]+)\s*(?:结尾|结束)/,
420
- spelTemplate: "#{field}.endsWith('{suffix}')",
421
- slots: { suffix: { key: 'suffix', type: 'string' } },
422
- priority: 85,
423
- tags: ['string', 'endsWith'],
424
- examples: [{ nl: '文件名以.pdf结尾', spel: "#文件名.endsWith('.pdf')" }],
425
- difficulty: 'easy',
426
- confidence: 0.95,
427
- },
428
- {
429
- id: 'EN-STR-ENDS',
430
- match: /\b(?<field>\w+)\s+(?:endsWith|ends\s+with)\s+(?<suffix>\S+)/i,
431
- spelTemplate: "#{field}.endsWith('{suffix}')",
432
- slots: { suffix: { key: 'suffix', type: 'string' } },
433
- priority: 84,
434
- tags: ['string', 'endsWith', 'english'],
435
- examples: [{ nl: 'name endsWith .pdf', spel: "#name.endsWith('.pdf')" }],
436
- difficulty: 'easy',
437
- confidence: 0.95,
438
- },
439
- {
440
- id: 'CN-STR-MATCHES',
441
- match: /^(?<field>[^\s,,、]+?)\s*(?:匹配|符合)\s*(?<pattern>[^\s,,、]+)/,
442
- spelTemplate: "#{field} matches '{pattern}'",
443
- slots: { pattern: { key: 'pattern', type: 'string' } },
444
- priority: 82,
445
- tags: ['string', 'matches'],
446
- examples: [{ nl: '手机号匹配正则', spel: "#手机号 matches '正则'" }],
447
- difficulty: 'medium',
448
- confidence: 0.9,
449
- },
450
- {
451
- id: 'EN-STR-MATCHES',
452
- match: /\b(?<field>\w+)\s+matches\s+(?<pattern>\S+)/i,
453
- spelTemplate: "#{field} matches '{pattern}'",
454
- slots: { pattern: { key: 'pattern', type: 'string' } },
455
- priority: 81,
456
- tags: ['string', 'matches', 'english'],
457
- examples: [{ nl: 'id matches REGEX', spel: "#id matches 'REGEX'" }],
458
- difficulty: 'medium',
459
- confidence: 0.9,
460
- },
461
- // ================================================================
462
- // Group 7: Range — pri 82
463
- // ================================================================
464
- {
465
- id: 'CN-RANGE-BETWEEN',
466
- match: /^(?<field>[^\s,,、]+?)\s*(?:在|介于)\s*(?<min>\d+)\s*(?:和|到|~)\s*(?<max>\d+)\s*(?:之间|范围)?/,
467
- spelTemplate: '#{field} between {{{min}, {max}}}',
468
- slots: {
469
- min: { key: 'min', type: 'number', transform: 'toNumber' },
470
- max: { key: 'max', type: 'number', transform: 'toNumber' },
471
- },
472
- priority: 82,
473
- tags: ['range', 'between'],
474
- examples: [{ nl: '年龄在18到60之间', spel: '#年龄 between {18, 60}' }],
475
- difficulty: 'easy',
476
- confidence: 0.95,
477
- },
478
- {
479
- id: 'EN-RANGE-BETWEEN',
480
- match: /\b(?<field>\w+)\s+between\s+(?<min>\d+)\s+and\s+(?<max>\d+)/i,
481
- spelTemplate: '#{field} between {{{min}, {max}}}',
482
- slots: {
483
- min: { key: 'min', type: 'number', transform: 'toNumber' },
484
- max: { key: 'max', type: 'number', transform: 'toNumber' },
485
- },
486
- priority: 82,
487
- tags: ['range', 'between', 'english'],
488
- examples: [{ nl: 'amount between 100 and 500', spel: '#amount between {100, 500}' }],
489
- difficulty: 'easy',
490
- confidence: 0.95,
491
- },
492
- // ================================================================
493
- // Group 8: Elvis — pri 78
494
- // ================================================================
495
- {
496
- id: 'CN-ELVIS',
497
- match: /^(?<field>[^\s,,、]+?)\s*(?:或者|或\s+|默认|否则)\s*(?<default>[^\s,,、]+)/,
498
- spelTemplate: "#{field} ?: '{default}'",
499
- slots: { default: { key: 'default', type: 'string' } },
500
- priority: 78,
501
- tags: ['elvis'],
502
- examples: [{ nl: '用户名或者匿名用户', spel: "#用户名 ?: '匿名用户'" }],
503
- difficulty: 'medium',
504
- confidence: 0.85,
505
- },
506
- {
507
- id: 'EN-ELVIS',
508
- match: /\b(?<field>\w+)\s+(?:or\s+default|default\s+to)\s+(?<default>\S+)/i,
509
- spelTemplate: "#{field} ?: '{default}'",
510
- slots: { default: { key: 'default', type: 'string' } },
511
- priority: 77,
512
- tags: ['elvis', 'english'],
513
- examples: [{ nl: 'name or default Guest', spel: "#name ?: 'Guest'" }],
514
- difficulty: 'medium',
515
- confidence: 0.85,
516
- },
517
- // ================================================================
518
- // Group 9: Date — pri 75
519
- // ================================================================
520
- {
521
- id: 'CN-DATE-AFTER',
522
- match: /^(?<field>[^\s,,、]+?)\s*在\s*(?<date>[^\s,,、]+?)\s*之后/,
523
- spelTemplate: "#{field} > T(java.time.LocalDate).parse('{date}')",
524
- slots: { date: { key: 'date', type: 'string' } },
525
- priority: 75,
526
- tags: ['date', 'after'],
527
- examples: [
528
- {
529
- nl: '创建日期在2024-01-01之后',
530
- spel: "#创建日期 > T(java.time.LocalDate).parse('2024-01-01')",
531
- },
532
- ],
533
- difficulty: 'easy',
534
- confidence: 0.9,
535
- },
536
- {
537
- id: 'CN-DATE-BEFORE',
538
- match: /^(?<field>[^\s,,、]+?)\s*在\s*(?<date>[^\s,,、]+?)\s*之前/,
539
- spelTemplate: "#{field} < T(java.time.LocalDate).parse('{date}')",
540
- slots: { date: { key: 'date', type: 'string' } },
541
- priority: 75,
542
- tags: ['date', 'before'],
543
- examples: [
544
- {
545
- nl: '过期日期在2025-12-31之前',
546
- spel: "#过期日期 < T(java.time.LocalDate).parse('2025-12-31')",
547
- },
548
- ],
549
- difficulty: 'easy',
550
- confidence: 0.9,
551
- },
552
- {
553
- id: 'EN-DATE-AFTER',
554
- match: /\b(?<field>\w+)\s+after\s+(?<date>\S+)/i,
555
- spelTemplate: "#{field} > T(java.time.LocalDate).parse('{date}')",
556
- slots: { date: { key: 'date', type: 'string' } },
557
- priority: 75,
558
- tags: ['date', 'after', 'english'],
559
- examples: [
560
- { nl: 'date after 2024-06-01', spel: "#date > T(java.time.LocalDate).parse('2024-06-01')" },
561
- ],
562
- difficulty: 'easy',
563
- confidence: 0.9,
564
- },
565
- {
566
- id: 'EN-DATE-BEFORE',
567
- match: /\b(?<field>\w+)\s+before\s+(?<date>\S+)/i,
568
- spelTemplate: "#{field} < T(java.time.LocalDate).parse('{date}')",
569
- slots: { date: { key: 'date', type: 'string' } },
570
- priority: 75,
571
- tags: ['date', 'before', 'english'],
572
- examples: [
573
- { nl: 'date before 2025-01-01', spel: "#date < T(java.time.LocalDate).parse('2025-01-01')" },
574
- ],
575
- difficulty: 'easy',
576
- confidence: 0.9,
577
- },
578
- // ================================================================
579
- // Group 10: Type check — pri 73
580
- // ================================================================
581
- {
582
- id: 'CN-TYPE-INSTANCEOF',
583
- match: /^(?<field>[^\s,,、]+?)\s*(?:是否是|是否为|是|instanceof)\s*(?<type>[^\s,,、]+?)\s*(?:类型|类型|type|class)?$/i,
584
- spelTemplate: '#{field} instanceof T({type})',
585
- slots: { type: { key: 'type', type: 'variable' } },
586
- priority: 74,
587
- tags: ['type', 'instanceof'],
588
- examples: [{ nl: '账号是否是Admin类型', spel: '#账号 instanceof T(Admin)' }],
589
- difficulty: 'medium',
590
- confidence: 0.85,
591
- },
592
- {
593
- id: 'EN-TYPE-INSTANCEOF',
594
- match: /\b(?<field>\w+)\s+(?:is|instanceof)\s+(?<type>\w+)/i,
595
- spelTemplate: '#{field} instanceof T({type})',
596
- slots: { type: { key: 'type', type: 'variable' } },
597
- priority: 72,
598
- tags: ['type', 'instanceof', 'english'],
599
- examples: [{ nl: 'account is Admin', spel: '#account instanceof T(Admin)' }],
600
- difficulty: 'medium',
601
- confidence: 0.9,
602
- },
603
- // ================================================================
604
- // Group 11: Boolean — pri 70-74
605
- // ================================================================
606
- {
607
- id: 'CN-BOOL-TRUE',
608
- match: /^(?<field>[^\s,,、]+?)\s*(?:是|为|等于|==)\s*(?:true|真|是|yes)$/i,
609
- spelTemplate: '#{field} == true',
610
- slots: {},
611
- priority: 74,
612
- tags: ['boolean', 'isTrue'],
613
- examples: [{ nl: '用户是VIP', spel: '#用户 == true' }],
614
- difficulty: 'easy',
615
- confidence: 0.92,
616
- },
617
- {
618
- id: 'CN-BOOL-FALSE',
619
- match: /^(?<field>[^\s,,、]+?)\s*(?:不是|非|为|是|等于|==)\s*(?:false|假|否|no)$/i,
620
- spelTemplate: '#{field} == false',
621
- slots: {},
622
- priority: 73,
623
- tags: ['boolean', 'isFalse'],
624
- examples: [{ nl: '用户不是VIP', spel: '#用户 == false' }],
625
- difficulty: 'easy',
626
- confidence: 0.92,
627
- },
628
- {
629
- id: 'EN-BOOL-TRUE',
630
- match: /^(?<field>\w+)\s+(?:is\s+)?true$/i,
631
- spelTemplate: '#{field} == true',
632
- slots: {},
633
- priority: 75,
634
- tags: ['boolean', 'isTrue', 'english'],
635
- examples: [{ nl: 'isVIP is true', spel: '#isVIP == true' }],
636
- difficulty: 'easy',
637
- confidence: 0.95,
638
- },
639
- {
640
- id: 'EN-BOOL-FALSE',
641
- match: /^(?<field>\w+)\s+(?:is\s+)?false$/i,
642
- spelTemplate: '#{field} == false',
643
- slots: {},
644
- priority: 75,
645
- tags: ['boolean', 'isFalse', 'english'],
646
- examples: [{ nl: 'flag is false', spel: '#flag == false' }],
647
- difficulty: 'easy',
648
- confidence: 0.95,
649
- },
650
- {
651
- id: 'CN-BOOL-FIELD',
652
- match: /^(?:是否|is\s+)(?<field>[^\s,,、]+?)(?:\?|吗|呢)?$/i,
653
- spelTemplate: '#{field}',
654
- slots: {},
655
- priority: 70,
656
- tags: ['boolean', 'field'],
657
- examples: [{ nl: '是否已支付', spel: '#已支付' }],
658
- difficulty: 'easy',
659
- confidence: 0.8,
660
- },
661
- // ================================================================
662
- // Group 12: Logical combination — pri 63-65
663
- // ================================================================
664
- {
665
- id: 'CN-LOGIC-AND',
666
- match: /(?<left>.+?)\s*(?:且|并且|而且|同时|&&)\s*(?<right>.+)/,
667
- spelTemplate: '({left}) and ({right})',
668
- slots: {
669
- left: { key: 'left', type: 'variable' },
670
- right: { key: 'right', type: 'variable' },
671
- },
672
- priority: 65,
673
- tags: ['logic', 'and'],
674
- examples: [{ nl: '金额大于1000且订单已确认', spel: '(金额大于1000) and (订单已确认)' }],
675
- difficulty: 'medium',
676
- confidence: 0.75,
677
- },
678
- {
679
- id: 'CN-LOGIC-OR',
680
- match: /(?<left>.+?)\s*(?:或|或者|\|\|)\s*(?<right>.+)/,
681
- spelTemplate: '({left}) or ({right})',
682
- slots: {
683
- left: { key: 'left', type: 'variable' },
684
- right: { key: 'right', type: 'variable' },
685
- },
686
- priority: 65,
687
- tags: ['logic', 'or'],
688
- examples: [{ nl: '金额大于1000或已发货', spel: '(金额大于1000) or (已发货)' }],
689
- difficulty: 'medium',
690
- confidence: 0.75,
691
- },
692
- {
693
- id: 'EN-LOGIC-AND',
694
- match: /\b(?<left>.+?)\s+\band\b\s+(?<right>.+)/i,
695
- spelTemplate: '({left}) and ({right})',
696
- slots: {
697
- left: { key: 'left', type: 'variable' },
698
- right: { key: 'right', type: 'variable' },
699
- },
700
- priority: 64,
701
- tags: ['logic', 'and', 'english'],
702
- examples: [
703
- { nl: 'amount > 100 and status == done', spel: '(amount > 100) and (status == done)' },
704
- ],
705
- difficulty: 'medium',
706
- confidence: 0.75,
707
- },
708
- {
709
- id: 'EN-LOGIC-OR',
710
- match: /\b(?<left>.+?)\s+\bor\b\s+(?<right>.+)/i,
711
- spelTemplate: '({left}) or ({right})',
712
- slots: {
713
- left: { key: 'left', type: 'variable' },
714
- right: { key: 'right', type: 'variable' },
715
- },
716
- priority: 64,
717
- tags: ['logic', 'or', 'english'],
718
- examples: [{ nl: 'VIP or amount > 1000', spel: '(VIP) or (amount > 1000)' }],
719
- difficulty: 'medium',
720
- confidence: 0.75,
721
- },
722
- // ================================================================
723
- // Group 13: Logical NOT — pri 61-62
724
- // ================================================================
725
- {
726
- id: 'CN-LOGIC-NOT',
727
- match: /^不是\s+(?<expr>.+)/,
728
- spelTemplate: '!({expr})',
729
- slots: { expr: { key: 'expr', type: 'variable' } },
730
- priority: 62,
731
- tags: ['logic', 'not'],
732
- examples: [{ nl: '不是有效', spel: '!(有效)' }],
733
- difficulty: 'easy',
734
- confidence: 0.85,
735
- },
736
- {
737
- id: 'EN-LOGIC-NOT',
738
- match: /^not\s+(?<expr>.+)/i,
739
- spelTemplate: '!({expr})',
740
- slots: { expr: { key: 'expr', type: 'variable' } },
741
- priority: 61,
742
- tags: ['logic', 'not', 'english'],
743
- examples: [{ nl: 'not cancelled', spel: '!(cancelled)' }],
744
- difficulty: 'easy',
745
- confidence: 0.85,
746
- },
747
- // ================================================================
748
- // Group 14: Projection & selection — pri 55-60
749
- // ================================================================
750
- {
751
- id: 'CN-SELECT-FIRST',
752
- match: /^(?<root>[^\s,,、]+?)\s*中\s*第一[个位]\s*(?<field>[^\s,,、]+?)\s*(?:大于|>|超过|<|小于|等于|==)\s*(?<value>[^\s,,、]+)/,
753
- spelTemplate: '#{root}.items.^[#{this}.{field} > {value}]',
754
- slots: {
755
- root: { key: 'root', type: 'variable' },
756
- field: { key: 'field', type: 'variable' },
757
- value: { key: 'value', type: 'literal' },
758
- },
759
- priority: 60,
760
- tags: ['selection', 'first'],
761
- examples: [{ nl: '订单中第一个金额大于1000的', spel: '#订单.items.^[#this.金额 > 1000]' }],
762
- difficulty: 'medium',
763
- confidence: 0.8,
764
- },
765
- {
766
- id: 'CN-SELECT-ALL',
767
- match: /^(?<root>[^\s,,、]+?)\s*中\s*所有\s*(?<field>[^\s,,、]+?)\s*(?:大于|>|超过|<|小于|等于|==|包含|满足)\s*(?<value>[^\s,,、]+)/,
768
- spelTemplate: '#{root}.items.?[#{this}.{field} > {value}]',
769
- slots: {
770
- root: { key: 'root', type: 'variable' },
771
- field: { key: 'field', type: 'variable' },
772
- value: { key: 'value', type: 'literal' },
773
- },
774
- priority: 60,
775
- tags: ['selection', 'all'],
776
- examples: [{ nl: '订单中所有金额大于1000的', spel: '#订单.items.?[#this.金额 > 1000]' }],
777
- difficulty: 'medium',
778
- confidence: 0.8,
779
- },
780
- {
781
- id: 'CN-PROJ',
782
- match: /^(?<root>[^\s,,、]+?)\s*中\s*每[个一]\s*(?:的)?(?<field>[^\s,,、]+?)\s*(?:值|金额|名称|价格|name|amount|price)?/,
783
- spelTemplate: '#{root}.items.![#{this}.{field}]',
784
- slots: {
785
- root: { key: 'root', type: 'variable' },
786
- field: { key: 'field', type: 'variable' },
787
- },
788
- priority: 55,
789
- tags: ['projection'],
790
- examples: [{ nl: '订单中每个商品的价格', spel: '#订单.items.![#this.商品]' }],
791
- difficulty: 'medium',
792
- confidence: 0.75,
793
- },
794
- {
795
- id: 'EN-SELECT-ALL',
796
- match: /all\s+(?<root>\w+)\s+with\s+(?<field>\w+)\s*>\s*(?<value>\d+)/i,
797
- spelTemplate: '#{root}.items.?[#{this}.{field} > {value}]',
798
- slots: {
799
- root: { key: 'root', type: 'variable' },
800
- field: { key: 'field', type: 'variable' },
801
- value: { key: 'value', type: 'number', transform: 'toNumber' },
802
- },
803
- priority: 50,
804
- tags: ['selection', 'all', 'english'],
805
- examples: [{ nl: 'all items with price > 100', spel: '#items.items.?[#this.price > 100]' }],
806
- difficulty: 'medium',
807
- confidence: 0.8,
808
- },
809
- ];
810
- // Sort by priority descending
811
- BUILTIN_PATTERNS.sort((a, b) => b.priority - a.priority);
812
- //# sourceMappingURL=builtin-patterns.js.map