@lokascript/framework 2.0.0 → 2.2.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 (138) hide show
  1. package/dist/aot/index.d.ts +1 -0
  2. package/dist/aot/index.d.ts.map +1 -1
  3. package/dist/aot/registry-bridge.d.ts +27 -0
  4. package/dist/aot/registry-bridge.d.ts.map +1 -0
  5. package/dist/api/create-dsl.d.ts.map +1 -1
  6. package/dist/api/dispatcher.d.ts +22 -0
  7. package/dist/api/dispatcher.d.ts.map +1 -1
  8. package/dist/api/domain-registry.d.ts +41 -0
  9. package/dist/api/domain-registry.d.ts.map +1 -1
  10. package/dist/api/index.js +1438 -21
  11. package/dist/api/index.js.map +1 -1
  12. package/dist/core/index.js +247 -10
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/core/pattern-matching/index.js +74 -10
  15. package/dist/core/pattern-matching/index.js.map +1 -1
  16. package/dist/core/pattern-matching/pattern-matcher.d.ts.map +1 -1
  17. package/dist/core/tokenization/index.js +133 -0
  18. package/dist/core/tokenization/index.js.map +1 -1
  19. package/dist/core/tokenization/morphology/base-normalizer.d.ts +94 -0
  20. package/dist/core/tokenization/morphology/base-normalizer.d.ts.map +1 -0
  21. package/dist/core/tokenization/morphology/index.d.ts +3 -1
  22. package/dist/core/tokenization/morphology/index.d.ts.map +1 -1
  23. package/dist/core/types.d.ts +81 -2
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/core/types.js +40 -0
  26. package/dist/core/types.js.map +1 -1
  27. package/dist/feedback/confidence-gate.d.ts +28 -0
  28. package/dist/feedback/confidence-gate.d.ts.map +1 -0
  29. package/dist/feedback/feedback-formatter.d.ts +21 -0
  30. package/dist/feedback/feedback-formatter.d.ts.map +1 -0
  31. package/dist/feedback/index.d.ts +11 -0
  32. package/dist/feedback/index.d.ts.map +1 -0
  33. package/dist/feedback/pattern-tracker.d.ts +47 -0
  34. package/dist/feedback/pattern-tracker.d.ts.map +1 -0
  35. package/dist/feedback/types.d.ts +113 -0
  36. package/dist/feedback/types.d.ts.map +1 -0
  37. package/dist/generation/index.js +2 -1
  38. package/dist/generation/index.js.map +1 -1
  39. package/dist/index.cjs +3264 -132
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.ts +8 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +3223 -132
  44. package/dist/index.js.map +1 -1
  45. package/dist/ir/explicit-parser.d.ts +86 -0
  46. package/dist/ir/explicit-parser.d.ts.map +1 -0
  47. package/dist/ir/explicit-renderer.d.ts +34 -0
  48. package/dist/ir/explicit-renderer.d.ts.map +1 -0
  49. package/dist/ir/from-interchange.d.ts +51 -0
  50. package/dist/ir/from-interchange.d.ts.map +1 -0
  51. package/dist/ir/index.d.ts +31 -0
  52. package/dist/ir/index.d.ts.map +1 -0
  53. package/dist/ir/index.js +1934 -0
  54. package/dist/ir/index.js.map +1 -0
  55. package/dist/ir/json-schema.d.ts +40 -0
  56. package/dist/ir/json-schema.d.ts.map +1 -0
  57. package/dist/ir/protocol-json.d.ts +73 -0
  58. package/dist/ir/protocol-json.d.ts.map +1 -0
  59. package/dist/ir/references.d.ts +19 -0
  60. package/dist/ir/references.d.ts.map +1 -0
  61. package/dist/ir/to-runtime-ast.d.ts +53 -0
  62. package/dist/ir/to-runtime-ast.d.ts.map +1 -0
  63. package/dist/ir/types.d.ts +151 -0
  64. package/dist/ir/types.d.ts.map +1 -0
  65. package/dist/parsing/index.js +74 -10
  66. package/dist/parsing/index.js.map +1 -1
  67. package/dist/prompts/index.d.ts +9 -0
  68. package/dist/prompts/index.d.ts.map +1 -0
  69. package/dist/prompts/prompt-generator.d.ts +49 -0
  70. package/dist/prompts/prompt-generator.d.ts.map +1 -0
  71. package/dist/prompts/types.d.ts +64 -0
  72. package/dist/prompts/types.d.ts.map +1 -0
  73. package/dist/schema/command-schema.d.ts +17 -0
  74. package/dist/schema/command-schema.d.ts.map +1 -1
  75. package/dist/schema/index.js.map +1 -1
  76. package/dist/testing/index.js +8673 -8260
  77. package/dist/testing/index.js.map +1 -1
  78. package/dist/training/index.d.ts +11 -0
  79. package/dist/training/index.d.ts.map +1 -0
  80. package/dist/training/jsonl-writer.d.ts +42 -0
  81. package/dist/training/jsonl-writer.d.ts.map +1 -0
  82. package/dist/training/schema-synthesizer.d.ts +20 -0
  83. package/dist/training/schema-synthesizer.d.ts.map +1 -0
  84. package/dist/training/types.d.ts +73 -0
  85. package/dist/training/types.d.ts.map +1 -0
  86. package/package.json +5 -1
  87. package/src/aot/index.ts +1 -0
  88. package/src/aot/registry-bridge.test.ts +104 -0
  89. package/src/aot/registry-bridge.ts +66 -0
  90. package/src/api/create-dsl.test.ts +306 -0
  91. package/src/api/create-dsl.ts +21 -0
  92. package/src/api/dispatcher.test.ts +66 -0
  93. package/src/api/dispatcher.ts +77 -9
  94. package/src/api/domain-registry.ts +120 -4
  95. package/src/core/pattern-matching/pattern-matcher.test.ts +131 -0
  96. package/src/core/pattern-matching/pattern-matcher.ts +102 -19
  97. package/src/core/tokenization/morphology/base-normalizer.ts +249 -0
  98. package/src/core/tokenization/morphology/index.ts +3 -1
  99. package/src/core/types.ts +147 -2
  100. package/src/feedback/confidence-gate.test.ts +111 -0
  101. package/src/feedback/confidence-gate.ts +70 -0
  102. package/src/feedback/feedback-formatter.test.ts +198 -0
  103. package/src/feedback/feedback-formatter.ts +298 -0
  104. package/src/feedback/index.ts +24 -0
  105. package/src/feedback/pattern-tracker.test.ts +198 -0
  106. package/src/feedback/pattern-tracker.ts +140 -0
  107. package/src/feedback/types.ts +149 -0
  108. package/src/generation/pattern-generator.ts +2 -2
  109. package/src/index.ts +29 -0
  110. package/src/integration/llm-lse-integration.test.ts +457 -0
  111. package/src/ir/conformance.test.ts +120 -0
  112. package/src/ir/explicit-parser.test.ts +612 -0
  113. package/src/ir/explicit-parser.ts +793 -0
  114. package/src/ir/explicit-renderer.test.ts +229 -0
  115. package/src/ir/explicit-renderer.ts +198 -0
  116. package/src/ir/from-interchange.test.ts +853 -0
  117. package/src/ir/from-interchange.ts +594 -0
  118. package/src/ir/index.ts +77 -0
  119. package/src/ir/json-schema.test.ts +281 -0
  120. package/src/ir/json-schema.ts +299 -0
  121. package/src/ir/protocol-json.test.ts +1187 -0
  122. package/src/ir/protocol-json.ts +751 -0
  123. package/src/ir/references.test.ts +38 -0
  124. package/src/ir/references.ts +33 -0
  125. package/src/ir/round-trip.test.ts +557 -0
  126. package/src/ir/to-runtime-ast.ts +203 -0
  127. package/src/ir/types.ts +191 -0
  128. package/src/prompts/index.ts +15 -0
  129. package/src/prompts/prompt-generator.test.ts +386 -0
  130. package/src/prompts/prompt-generator.ts +531 -0
  131. package/src/prompts/types.ts +89 -0
  132. package/src/schema/command-schema.ts +19 -0
  133. package/src/training/index.ts +13 -0
  134. package/src/training/jsonl-writer.test.ts +138 -0
  135. package/src/training/jsonl-writer.ts +67 -0
  136. package/src/training/schema-synthesizer.test.ts +250 -0
  137. package/src/training/schema-synthesizer.ts +306 -0
  138. package/src/training/types.ts +103 -0
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Schema Synthesizer
3
+ *
4
+ * Generates synthetic (natural_language, LSE) training pairs from
5
+ * CommandSchema[]. Enumerates valid role combinations and produces
6
+ * examples in both bracket syntax and JSON wire format.
7
+ */
8
+
9
+ import type { CommandSchema, RoleSpec } from '../schema/command-schema';
10
+ import type { SemanticJSON, SemanticJSONValue } from '../ir/types';
11
+ import { renderExplicit } from '../ir/explicit-renderer';
12
+ import { createCommandNode } from '../core/types';
13
+ import type { TrainingPair, SynthesisConfig, SynthesisResult, SynthesisMetadata } from './types';
14
+
15
+ // =============================================================================
16
+ // Public API
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Synthesize training pairs from command schemas.
21
+ *
22
+ * Generates multiple examples per command by enumerating role combinations:
23
+ * 1. Required roles only (minimum viable)
24
+ * 2. Required + each optional role individually
25
+ * 3. Required + all optional roles (maximum)
26
+ * 4. Shuffled role order variants (teaches role-label independence)
27
+ */
28
+ export function synthesizeFromSchemas(
29
+ schemas: readonly CommandSchema[],
30
+ config: SynthesisConfig
31
+ ): SynthesisResult {
32
+ const maxPerCommand = config.maxPairsPerCommand ?? 5;
33
+ const minQuality = config.minQuality ?? 0.5;
34
+ const shuffleRoles = config.shuffleRoles ?? true;
35
+ const languages = config.languages ?? ['en'];
36
+
37
+ const pairs: TrainingPair[] = [];
38
+ let idCounter = 0;
39
+
40
+ for (const schema of schemas) {
41
+ const combos = generateRoleCombinations(schema);
42
+
43
+ for (const language of languages) {
44
+ let commandPairCount = 0;
45
+
46
+ for (const combo of combos) {
47
+ if (commandPairCount >= maxPerCommand) break;
48
+
49
+ const pair = buildTrainingPair(
50
+ schema,
51
+ combo,
52
+ language,
53
+ config.domain,
54
+ `${config.domain}-synth-${idCounter++}`
55
+ );
56
+
57
+ if (pair.quality >= minQuality) {
58
+ pairs.push(pair);
59
+ commandPairCount++;
60
+ }
61
+
62
+ // Generate shuffled variant
63
+ if (shuffleRoles && combo.length >= 2 && commandPairCount < maxPerCommand) {
64
+ const shuffled = [...combo].reverse();
65
+ const shuffledPair = buildTrainingPair(
66
+ schema,
67
+ shuffled,
68
+ language,
69
+ config.domain,
70
+ `${config.domain}-synth-${idCounter++}`
71
+ );
72
+ if (shuffledPair.quality >= minQuality) {
73
+ pairs.push(shuffledPair);
74
+ commandPairCount++;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ const metadata: SynthesisMetadata = {
82
+ domain: config.domain,
83
+ commandCount: schemas.length,
84
+ pairCount: pairs.length,
85
+ bySource: { synthetic: pairs.length },
86
+ languages,
87
+ };
88
+
89
+ return { pairs, metadata };
90
+ }
91
+
92
+ // =============================================================================
93
+ // Role Combination Generation
94
+ // =============================================================================
95
+
96
+ function generateRoleCombinations(schema: CommandSchema): RoleSpec[][] {
97
+ const required = schema.roles.filter(r => r.required);
98
+ const optional = schema.roles.filter(r => !r.required);
99
+
100
+ const combos: RoleSpec[][] = [];
101
+
102
+ // 1. Required only
103
+ if (required.length > 0) {
104
+ combos.push(required);
105
+ }
106
+
107
+ // 2. Required + each optional individually
108
+ for (const opt of optional) {
109
+ combos.push([...required, opt]);
110
+ }
111
+
112
+ // 3. Required + all optional (if 2+ optional)
113
+ if (optional.length >= 2) {
114
+ combos.push([...required, ...optional]);
115
+ }
116
+
117
+ // Fallback: if no required roles, use all roles
118
+ if (combos.length === 0) {
119
+ combos.push(schema.roles.slice());
120
+ }
121
+
122
+ return combos;
123
+ }
124
+
125
+ // =============================================================================
126
+ // Pair Building
127
+ // =============================================================================
128
+
129
+ function buildTrainingPair(
130
+ schema: CommandSchema,
131
+ roles: RoleSpec[],
132
+ language: string,
133
+ domain: string,
134
+ id: string
135
+ ): TrainingPair {
136
+ const sampledRoles = new Map<string, { type: string; value: string | number | boolean }>();
137
+
138
+ for (const role of roles) {
139
+ sampledRoles.set(role.role, sampleValue(role));
140
+ }
141
+
142
+ // Build SemanticNode for bracket syntax
143
+ const nodeRoles = new Map<string, unknown>();
144
+ for (const [name, sample] of sampledRoles) {
145
+ nodeRoles.set(name, toSemanticValue(sample));
146
+ }
147
+ const node = createCommandNode(schema.action, nodeRoles as never);
148
+ const explicit = renderExplicit(node);
149
+
150
+ // Build JSON format
151
+ const jsonRoles: Record<string, SemanticJSONValue> = {};
152
+ for (const [name, sample] of sampledRoles) {
153
+ jsonRoles[name] = sample as SemanticJSONValue;
154
+ }
155
+ const json: SemanticJSON = { action: schema.action, roles: jsonRoles };
156
+
157
+ // Build natural language form
158
+ const natural = buildNaturalForm(schema, sampledRoles, language);
159
+
160
+ // Quality: synthetic pairs get a base quality, higher if more roles are filled
161
+ const requiredCount = schema.roles.filter(r => r.required).length;
162
+ const filledRequired = roles.filter(r => r.required).length;
163
+ const quality = requiredCount > 0 ? filledRequired / requiredCount : 0.8;
164
+
165
+ return {
166
+ id,
167
+ natural,
168
+ language,
169
+ explicit,
170
+ json,
171
+ domain,
172
+ action: schema.action,
173
+ source: 'synthetic',
174
+ quality,
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Build a natural language form from sampled roles.
180
+ * Uses marker overrides for the given language when available.
181
+ */
182
+ function buildNaturalForm(
183
+ schema: CommandSchema,
184
+ roles: Map<string, { type: string; value: string | number | boolean }>,
185
+ language: string
186
+ ): string {
187
+ const parts: string[] = [schema.action];
188
+
189
+ for (const roleSpec of schema.roles) {
190
+ const sample = roles.get(roleSpec.role);
191
+ if (!sample) continue;
192
+
193
+ const marker = roleSpec.markerOverride?.[language];
194
+ if (marker) {
195
+ parts.push(marker);
196
+ }
197
+ parts.push(String(sample.value));
198
+ }
199
+
200
+ return parts.join(' ');
201
+ }
202
+
203
+ // =============================================================================
204
+ // Value Sampling
205
+ // =============================================================================
206
+
207
+ function sampleValue(role: RoleSpec): { type: string; value: string | number | boolean } {
208
+ const primaryType = role.expectedTypes[0] || 'expression';
209
+
210
+ switch (primaryType) {
211
+ case 'selector':
212
+ return sampleSelector(role.role);
213
+ case 'literal':
214
+ return sampleLiteral(role.role);
215
+ case 'reference':
216
+ return { type: 'reference', value: 'me' };
217
+ case 'expression':
218
+ return sampleExpression(role.role);
219
+ case 'flag':
220
+ return { type: 'flag', value: true };
221
+ default:
222
+ return { type: 'literal', value: 'example' };
223
+ }
224
+ }
225
+
226
+ function sampleSelector(roleName: string): { type: string; value: string } {
227
+ const selectors: Record<string, string> = {
228
+ patient: '.active',
229
+ destination: '#output',
230
+ source: '#input',
231
+ target: '#target',
232
+ };
233
+ return { type: 'selector', value: selectors[roleName] || `#${roleName}` };
234
+ }
235
+
236
+ function sampleLiteral(roleName: string): { type: string; value: string | number } {
237
+ const literals: Record<string, string | number> = {
238
+ duration: '30s',
239
+ interval: '5s',
240
+ delay: '500ms',
241
+ timeout: '10s',
242
+ quantity: 5,
243
+ limit: 10,
244
+ style: 'json',
245
+ manner: 'rolling',
246
+ format: 'html',
247
+ };
248
+ return { type: 'literal', value: literals[roleName] || roleName };
249
+ }
250
+
251
+ function sampleExpression(roleName: string): { type: string; value: string } {
252
+ const expressions: Record<string, string> = {
253
+ source: '/api/data',
254
+ destination: '#output',
255
+ patient: '.active',
256
+ instrument: 'toUpperCase',
257
+ condition: 'age > 18',
258
+ style: 'json',
259
+ duration: '5s',
260
+ url: '/api/users',
261
+ };
262
+ return { type: 'expression', value: expressions[roleName] || `/api/${roleName}` };
263
+ }
264
+
265
+ function toSemanticValue(sample: { type: string; value: string | number | boolean }): {
266
+ type: string;
267
+ value: string | number | boolean;
268
+ raw?: string;
269
+ dataType?: string;
270
+ selectorKind?: string;
271
+ } {
272
+ switch (sample.type) {
273
+ case 'selector':
274
+ return {
275
+ type: 'selector',
276
+ value: String(sample.value),
277
+ selectorKind: detectSelectorKind(String(sample.value)),
278
+ };
279
+ case 'literal':
280
+ return {
281
+ type: 'literal',
282
+ value: sample.value,
283
+ dataType:
284
+ typeof sample.value === 'number'
285
+ ? 'number'
286
+ : typeof sample.value === 'boolean'
287
+ ? 'boolean'
288
+ : 'string',
289
+ };
290
+ case 'reference':
291
+ return { type: 'reference', value: String(sample.value) };
292
+ case 'expression':
293
+ return { type: 'expression', value: String(sample.value), raw: String(sample.value) };
294
+ case 'flag':
295
+ return { type: 'flag', value: sample.value };
296
+ default:
297
+ return { type: 'literal', value: String(sample.value), dataType: 'string' };
298
+ }
299
+ }
300
+
301
+ function detectSelectorKind(selector: string): string {
302
+ if (selector.startsWith('#')) return 'id';
303
+ if (selector.startsWith('.')) return 'class';
304
+ if (selector.startsWith('[')) return 'attribute';
305
+ return 'complex';
306
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Training Data Types
3
+ *
4
+ * Types for generating (natural_language, LSE) training pairs from
5
+ * domain schemas. Used for fine-tuning or few-shot prompting LLMs
6
+ * to output valid LokaScript Explicit Syntax.
7
+ */
8
+
9
+ import type { SemanticJSON } from '../ir/types';
10
+
11
+ // =============================================================================
12
+ // Training Pairs
13
+ // =============================================================================
14
+
15
+ /**
16
+ * A single training pair: natural language ↔ explicit syntax.
17
+ */
18
+ export interface TrainingPair {
19
+ /** Unique identifier for deduplication */
20
+ readonly id: string;
21
+
22
+ /** Natural language form (e.g., "fetch /api/users as json into #list") */
23
+ readonly natural: string;
24
+
25
+ /** Language code (e.g., "en") */
26
+ readonly language: string;
27
+
28
+ /** LSE bracket syntax (e.g., "[fetch source:/api/users style:json destination:#list]") */
29
+ readonly explicit: string;
30
+
31
+ /** LLM-simplified JSON wire format */
32
+ readonly json: SemanticJSON;
33
+
34
+ /** Domain this pair belongs to */
35
+ readonly domain: string;
36
+
37
+ /** Command action */
38
+ readonly action: string;
39
+
40
+ /** How this pair was generated */
41
+ readonly source: 'synthetic' | 'test' | 'compilation';
42
+
43
+ /** Parse confidence (if from real parsing) */
44
+ readonly confidence?: number;
45
+
46
+ /** Quality score 0-1 for filtering */
47
+ readonly quality: number;
48
+ }
49
+
50
+ // =============================================================================
51
+ // Synthesis Configuration
52
+ // =============================================================================
53
+
54
+ /**
55
+ * Configuration for training data synthesis.
56
+ */
57
+ export interface SynthesisConfig {
58
+ /** Domain identifier */
59
+ readonly domain: string;
60
+
61
+ /** Maximum pairs per command */
62
+ readonly maxPairsPerCommand?: number;
63
+
64
+ /** Minimum quality threshold (0-1). Default: 0.5 */
65
+ readonly minQuality?: number;
66
+
67
+ /** Whether to shuffle role order for some examples. Default: true */
68
+ readonly shuffleRoles?: boolean;
69
+
70
+ /** Language codes to generate for. Default: ['en'] */
71
+ readonly languages?: readonly string[];
72
+ }
73
+
74
+ /**
75
+ * Result of training data synthesis.
76
+ */
77
+ export interface SynthesisResult {
78
+ /** Generated training pairs */
79
+ readonly pairs: readonly TrainingPair[];
80
+
81
+ /** Metadata about the synthesis */
82
+ readonly metadata: SynthesisMetadata;
83
+ }
84
+
85
+ /**
86
+ * Metadata about a synthesis run.
87
+ */
88
+ export interface SynthesisMetadata {
89
+ /** Domain the data was synthesized for */
90
+ readonly domain: string;
91
+
92
+ /** Number of command schemas processed */
93
+ readonly commandCount: number;
94
+
95
+ /** Total pairs generated */
96
+ readonly pairCount: number;
97
+
98
+ /** Pairs per source type */
99
+ readonly bySource: Record<string, number>;
100
+
101
+ /** Languages included */
102
+ readonly languages: readonly string[];
103
+ }