@agentix-e/nl2spel 0.0.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +69 -39
  2. package/dist/SpelEvaluator.d.ts +124 -0
  3. package/dist/SpelEvaluator.d.ts.map +1 -0
  4. package/dist/SpelEvaluator.js +2 -0
  5. package/dist/SpelEvaluator.js.map +1 -0
  6. package/dist/__tests__/auto-fixer.test.d.ts +2 -0
  7. package/dist/__tests__/auto-fixer.test.d.ts.map +1 -0
  8. package/dist/__tests__/auto-fixer.test.js +285 -0
  9. package/dist/__tests__/auto-fixer.test.js.map +1 -0
  10. package/dist/__tests__/chinese-number-parser.test.d.ts +2 -0
  11. package/dist/__tests__/chinese-number-parser.test.d.ts.map +1 -0
  12. package/dist/__tests__/chinese-number-parser.test.js +106 -0
  13. package/dist/__tests__/chinese-number-parser.test.js.map +1 -0
  14. package/dist/__tests__/context-extractor.test.d.ts +2 -0
  15. package/dist/__tests__/context-extractor.test.d.ts.map +1 -0
  16. package/dist/__tests__/context-extractor.test.js +347 -0
  17. package/dist/__tests__/context-extractor.test.js.map +1 -0
  18. package/dist/__tests__/coverage-gaps.test.d.ts +2 -0
  19. package/dist/__tests__/coverage-gaps.test.d.ts.map +1 -0
  20. package/dist/__tests__/coverage-gaps.test.js +578 -0
  21. package/dist/__tests__/coverage-gaps.test.js.map +1 -0
  22. package/dist/__tests__/intent-classifier.test.d.ts +2 -0
  23. package/dist/__tests__/intent-classifier.test.d.ts.map +1 -0
  24. package/dist/__tests__/intent-classifier.test.js +384 -0
  25. package/dist/__tests__/intent-classifier.test.js.map +1 -0
  26. package/dist/__tests__/nl2spel-engine.test.d.ts +2 -0
  27. package/dist/__tests__/nl2spel-engine.test.d.ts.map +1 -0
  28. package/dist/__tests__/nl2spel-engine.test.js +344 -0
  29. package/dist/__tests__/nl2spel-engine.test.js.map +1 -0
  30. package/dist/__tests__/pattern-matcher.test.d.ts +2 -0
  31. package/dist/__tests__/pattern-matcher.test.d.ts.map +1 -0
  32. package/dist/__tests__/pattern-matcher.test.js +754 -0
  33. package/dist/__tests__/pattern-matcher.test.js.map +1 -0
  34. package/dist/__tests__/prompt-builder.test.d.ts +2 -0
  35. package/dist/__tests__/prompt-builder.test.d.ts.map +1 -0
  36. package/dist/__tests__/prompt-builder.test.js +99 -0
  37. package/dist/__tests__/prompt-builder.test.js.map +1 -0
  38. package/dist/__tests__/provider-registry.test.d.ts +2 -0
  39. package/dist/__tests__/provider-registry.test.d.ts.map +1 -0
  40. package/dist/__tests__/provider-registry.test.js +240 -0
  41. package/dist/__tests__/provider-registry.test.js.map +1 -0
  42. package/dist/__tests__/schema-formatter.test.d.ts +2 -0
  43. package/dist/__tests__/schema-formatter.test.d.ts.map +1 -0
  44. package/dist/__tests__/schema-formatter.test.js +298 -0
  45. package/dist/__tests__/schema-formatter.test.js.map +1 -0
  46. package/dist/__tests__/self-correction-loop.test.d.ts +2 -0
  47. package/dist/__tests__/self-correction-loop.test.d.ts.map +1 -0
  48. package/dist/__tests__/self-correction-loop.test.js +253 -0
  49. package/dist/__tests__/self-correction-loop.test.js.map +1 -0
  50. package/dist/__tests__/strategy-router.test.d.ts +2 -0
  51. package/dist/__tests__/strategy-router.test.d.ts.map +1 -0
  52. package/dist/__tests__/strategy-router.test.js +493 -0
  53. package/dist/__tests__/strategy-router.test.js.map +1 -0
  54. package/dist/__tests__/template-engine.test.d.ts +2 -0
  55. package/dist/__tests__/template-engine.test.d.ts.map +1 -0
  56. package/dist/__tests__/template-engine.test.js +367 -0
  57. package/dist/__tests__/template-engine.test.js.map +1 -0
  58. package/dist/__tests__/validation-pipeline.test.d.ts +2 -0
  59. package/dist/__tests__/validation-pipeline.test.d.ts.map +1 -0
  60. package/dist/__tests__/validation-pipeline.test.js +262 -0
  61. package/dist/__tests__/validation-pipeline.test.js.map +1 -0
  62. package/dist/context/context-extractor.d.ts +82 -0
  63. package/dist/context/context-extractor.d.ts.map +1 -0
  64. package/dist/context/context-extractor.js +166 -0
  65. package/dist/context/context-extractor.js.map +1 -0
  66. package/dist/context/schema-formatter.d.ts +20 -0
  67. package/dist/context/schema-formatter.d.ts.map +1 -0
  68. package/dist/context/schema-formatter.js +104 -0
  69. package/dist/context/schema-formatter.js.map +1 -0
  70. package/dist/engine/nl2spel-engine.d.ts +144 -0
  71. package/dist/engine/nl2spel-engine.d.ts.map +1 -0
  72. package/dist/engine/nl2spel-engine.js +125 -0
  73. package/dist/engine/nl2spel-engine.js.map +1 -0
  74. package/dist/index.d.ts +28 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +24 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/pattern/builtin-patterns.d.ts +12 -0
  79. package/dist/pattern/builtin-patterns.d.ts.map +1 -0
  80. package/dist/pattern/builtin-patterns.js +812 -0
  81. package/dist/pattern/builtin-patterns.js.map +1 -0
  82. package/dist/pattern/pattern-definition.d.ts +49 -0
  83. package/dist/pattern/pattern-definition.d.ts.map +1 -0
  84. package/dist/pattern/pattern-definition.js +2 -0
  85. package/dist/pattern/pattern-definition.js.map +1 -0
  86. package/dist/pattern/pattern-matcher.d.ts +55 -0
  87. package/dist/pattern/pattern-matcher.d.ts.map +1 -0
  88. package/dist/pattern/pattern-matcher.js +216 -0
  89. package/dist/pattern/pattern-matcher.js.map +1 -0
  90. package/dist/provider/llm-provider.d.ts +146 -0
  91. package/dist/provider/llm-provider.d.ts.map +1 -0
  92. package/dist/provider/llm-provider.js +2 -0
  93. package/dist/provider/llm-provider.js.map +1 -0
  94. package/dist/provider/provider-registry.d.ts +28 -0
  95. package/dist/provider/provider-registry.d.ts.map +1 -0
  96. package/dist/provider/provider-registry.js +65 -0
  97. package/dist/provider/provider-registry.js.map +1 -0
  98. package/dist/strategy/strategy-router.d.ts +79 -0
  99. package/dist/strategy/strategy-router.d.ts.map +1 -0
  100. package/dist/strategy/strategy-router.js +182 -0
  101. package/dist/strategy/strategy-router.js.map +1 -0
  102. package/dist/template/intent-classifier.d.ts +56 -0
  103. package/dist/template/intent-classifier.d.ts.map +1 -0
  104. package/dist/template/intent-classifier.js +251 -0
  105. package/dist/template/intent-classifier.js.map +1 -0
  106. package/dist/template/nl-intent.d.ts +38 -0
  107. package/dist/template/nl-intent.d.ts.map +1 -0
  108. package/dist/template/nl-intent.js +39 -0
  109. package/dist/template/nl-intent.js.map +1 -0
  110. package/dist/template/prompts/prompt-builder.d.ts +20 -0
  111. package/dist/template/prompts/prompt-builder.d.ts.map +1 -0
  112. package/dist/template/prompts/prompt-builder.js +243 -0
  113. package/dist/template/prompts/prompt-builder.js.map +1 -0
  114. package/dist/template/template-engine.d.ts +27 -0
  115. package/dist/template/template-engine.d.ts.map +1 -0
  116. package/dist/template/template-engine.js +378 -0
  117. package/dist/template/template-engine.js.map +1 -0
  118. package/dist/utils/chinese-number-parser.d.ts +30 -0
  119. package/dist/utils/chinese-number-parser.d.ts.map +1 -0
  120. package/dist/utils/chinese-number-parser.js +92 -0
  121. package/dist/utils/chinese-number-parser.js.map +1 -0
  122. package/dist/validation/auto-fixer.d.ts +14 -0
  123. package/dist/validation/auto-fixer.d.ts.map +1 -0
  124. package/dist/validation/auto-fixer.js +111 -0
  125. package/dist/validation/auto-fixer.js.map +1 -0
  126. package/dist/validation/self-correction-loop.d.ts +46 -0
  127. package/dist/validation/self-correction-loop.d.ts.map +1 -0
  128. package/dist/validation/self-correction-loop.js +141 -0
  129. package/dist/validation/self-correction-loop.js.map +1 -0
  130. package/dist/validation/validation-pipeline.d.ts +81 -0
  131. package/dist/validation/validation-pipeline.d.ts.map +1 -0
  132. package/dist/validation/validation-pipeline.js +306 -0
  133. package/dist/validation/validation-pipeline.js.map +1 -0
  134. package/package.json +36 -7
@@ -0,0 +1,812 @@
1
+ /**
2
+ * Built-in pattern library — covers ≥80% Easy scenarios, ≥35 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 92
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