@lokascript/framework 2.3.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/api/index.js +29 -516
  2. package/dist/api/index.js.map +1 -1
  3. package/dist/core/index.js +20 -128
  4. package/dist/core/index.js.map +1 -1
  5. package/dist/core/pattern-matching/index.js +19 -12
  6. package/dist/core/pattern-matching/index.js.map +1 -1
  7. package/dist/core/tokenization/index.js.map +1 -1
  8. package/dist/core/types.d.ts +7 -354
  9. package/dist/core/types.d.ts.map +1 -1
  10. package/dist/core/types.js +21 -129
  11. package/dist/core/types.js.map +1 -1
  12. package/dist/generation/diagnostics.d.ts +5 -115
  13. package/dist/generation/diagnostics.d.ts.map +1 -1
  14. package/dist/generation/index.js +20 -77
  15. package/dist/generation/index.js.map +1 -1
  16. package/dist/index.cjs +189 -1458
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.js +108 -1347
  19. package/dist/index.js.map +1 -1
  20. package/dist/interfaces/value-extractor.d.ts +20 -0
  21. package/dist/interfaces/value-extractor.d.ts.map +1 -1
  22. package/dist/ir/explicit-parser.d.ts +2 -83
  23. package/dist/ir/explicit-parser.d.ts.map +1 -1
  24. package/dist/ir/explicit-renderer.d.ts +2 -31
  25. package/dist/ir/explicit-renderer.d.ts.map +1 -1
  26. package/dist/ir/index.js +89 -1260
  27. package/dist/ir/index.js.map +1 -1
  28. package/dist/ir/protocol-json.d.ts +2 -70
  29. package/dist/ir/protocol-json.d.ts.map +1 -1
  30. package/dist/ir/references.d.ts +2 -16
  31. package/dist/ir/references.d.ts.map +1 -1
  32. package/dist/ir/types.d.ts +2 -148
  33. package/dist/ir/types.d.ts.map +1 -1
  34. package/dist/parsing/index.js +19 -12
  35. package/dist/parsing/index.js.map +1 -1
  36. package/dist/schema/command-schema.d.ts +3 -92
  37. package/dist/schema/command-schema.d.ts.map +1 -1
  38. package/dist/schema/index.js +3 -20
  39. package/dist/schema/index.js.map +1 -1
  40. package/dist/testing/index.js +1066 -712
  41. package/dist/testing/index.js.map +1 -1
  42. package/package.json +6 -2
  43. package/src/core/types.ts +71 -600
  44. package/src/generation/diagnostics.ts +12 -233
  45. package/src/interfaces/value-extractor.ts +32 -0
  46. package/src/ir/explicit-parser.ts +12 -792
  47. package/src/ir/explicit-renderer.ts +2 -195
  48. package/src/ir/from-interchange.test.ts +91 -4
  49. package/src/ir/from-interchange.ts +59 -0
  50. package/src/ir/protocol-json.test.ts +16 -7
  51. package/src/ir/protocol-json.ts +9 -748
  52. package/src/ir/references.ts +2 -30
  53. package/src/ir/types.ts +18 -190
  54. package/src/schema/command-schema.ts +3 -134
package/dist/index.cjs CHANGED
@@ -26,13 +26,14 @@ __export(index_exports, {
26
26
  CrossDomainDispatcher: () => CrossDomainDispatcher,
27
27
  DEFAULT_OPERATORS: () => DEFAULT_OPERATORS,
28
28
  DEFAULT_PUNCTUATION: () => DEFAULT_PUNCTUATION,
29
- DEFAULT_REFERENCES: () => DEFAULT_REFERENCES,
29
+ DEFAULT_REFERENCES: () => import_intent2.DEFAULT_REFERENCES,
30
30
  DomainAwareScanner: () => DomainAwareScanner,
31
31
  DomainRegistry: () => DomainRegistry,
32
32
  GrammarTransformer: () => GrammarTransformer,
33
33
  IdentifierExtractor: () => IdentifierExtractor,
34
34
  InMemoryDictionary: () => InMemoryDictionary,
35
35
  InMemoryProfileProvider: () => InMemoryProfileProvider,
36
+ LatinExtendedIdentifierExtractor: () => LatinExtendedIdentifierExtractor,
36
37
  NullDictionary: () => NullDictionary,
37
38
  NullProfileProvider: () => NullProfileProvider,
38
39
  NumberExtractor: () => NumberExtractor,
@@ -51,44 +52,44 @@ __export(index_exports, {
51
52
  buildTablesFromProfiles: () => buildTablesFromProfiles,
52
53
  combineClassifiers: () => combineClassifiers,
53
54
  convertValue: () => convertValue,
54
- createAsyncNode: () => createAsyncNode,
55
- createCommandNode: () => createCommandNode,
56
- createCompoundNode: () => createCompoundNode,
57
- createConditionalNode: () => createConditionalNode,
58
- createDiagnosticCollector: () => createDiagnosticCollector,
59
- createEventHandlerNode: () => createEventHandlerNode,
60
- createExpression: () => createExpression,
61
- createFlag: () => createFlag,
55
+ createAsyncNode: () => import_intent.createAsyncNode,
56
+ createCommandNode: () => import_intent.createCommandNode,
57
+ createCompoundNode: () => import_intent.createCompoundNode,
58
+ createConditionalNode: () => import_intent.createConditionalNode,
59
+ createDiagnosticCollector: () => import_intent7.createDiagnosticCollector,
60
+ createEventHandlerNode: () => import_intent.createEventHandlerNode,
61
+ createExpression: () => import_intent.createExpression,
62
+ createFlag: () => import_intent.createFlag,
62
63
  createLatinCharClassifiers: () => createLatinCharClassifiers,
63
- createLiteral: () => createLiteral,
64
- createLoopNode: () => createLoopNode,
65
- createMatchNode: () => createMatchNode,
64
+ createLiteral: () => import_intent.createLiteral,
65
+ createLoopNode: () => import_intent.createLoopNode,
66
+ createMatchNode: () => import_intent.createMatchNode,
66
67
  createMultiStatementParser: () => createMultiStatementParser,
67
68
  createMultilingualDSL: () => createMultilingualDSL,
68
69
  createPosition: () => createPosition,
69
- createPropertyPath: () => createPropertyPath,
70
- createReference: () => createReference,
70
+ createPropertyPath: () => import_intent.createPropertyPath,
71
+ createReference: () => import_intent.createReference,
71
72
  createSchemaRenderer: () => createSchemaRenderer,
72
- createSelector: () => createSelector,
73
+ createSelector: () => import_intent.createSelector,
73
74
  createSimpleTokenizer: () => createSimpleTokenizer,
74
75
  createToken: () => createToken,
75
76
  createTokenizerContext: () => createTokenizerContext,
76
- createTryNode: () => createTryNode,
77
+ createTryNode: () => import_intent.createTryNode,
77
78
  createUnicodeRangeClassifier: () => createUnicodeRangeClassifier,
78
- defineCommand: () => defineCommand,
79
- defineRole: () => defineRole,
79
+ defineCommand: () => import_intent6.defineCommand,
80
+ defineRole: () => import_intent6.defineRole,
80
81
  detectWordOrders: () => detectWordOrders,
81
82
  extractCssSelector: () => extractCssSelector,
82
83
  extractNumber: () => extractNumber,
83
- extractRoleValue: () => extractRoleValue,
84
+ extractRoleValue: () => import_intent.extractRoleValue,
84
85
  extractStringLiteral: () => extractStringLiteral,
85
86
  extractUrl: () => extractUrl,
86
- extractValue: () => extractValue,
87
- filterBySeverity: () => filterBySeverity,
88
- fromEnvelopeJSON: () => fromEnvelopeJSON,
89
- fromError: () => fromError,
87
+ extractValue: () => import_intent.extractValue,
88
+ filterBySeverity: () => import_intent7.filterBySeverity,
89
+ fromEnvelopeJSON: () => import_intent5.fromEnvelopeJSON,
90
+ fromError: () => import_intent7.fromError,
90
91
  fromInterchangeNode: () => fromInterchangeNode,
91
- fromProtocolJSON: () => fromProtocolJSON,
92
+ fromProtocolJSON: () => import_intent5.fromProtocolJSON,
92
93
  generateExamples: () => generateExamples,
93
94
  generatePattern: () => generatePattern,
94
95
  generatePatternVariants: () => generatePatternVariants,
@@ -97,6 +98,8 @@ __export(index_exports, {
97
98
  getAllPossessiveKeywords: () => getAllPossessiveKeywords,
98
99
  getDefaultExtractors: () => getDefaultExtractors,
99
100
  getPossessiveReference: () => getPossessiveReference,
101
+ getRoleSpec: () => import_intent6.getRoleSpec,
102
+ getRoleValue: () => import_intent.getRoleValue,
100
103
  insertMarkers: () => insertMarkers,
101
104
  isAsciiIdentifierChar: () => isAsciiIdentifierChar,
102
105
  isAsciiLetter: () => isAsciiLetter,
@@ -104,12 +107,12 @@ __export(index_exports, {
104
107
  isCSSPropertyRef: () => isCSSPropertyRef,
105
108
  isCSSSelector: () => isCSSSelector,
106
109
  isClassName: () => isClassName,
107
- isCompoundSyntax: () => isCompoundSyntax,
110
+ isCompoundSyntax: () => import_intent3.isCompoundSyntax,
108
111
  isContextAwareExtractor: () => isContextAwareExtractor,
109
112
  isDigit: () => isDigit,
110
- isDocumentSyntax: () => isDocumentSyntax,
111
- isEnvelope: () => isEnvelope,
112
- isExplicitSyntax: () => isExplicitSyntax,
113
+ isDocumentSyntax: () => import_intent3.isDocumentSyntax,
114
+ isEnvelope: () => import_intent5.isEnvelope,
115
+ isExplicitSyntax: () => import_intent3.isExplicitSyntax,
113
116
  isIdSelector: () => isIdSelector,
114
117
  isNumericValue: () => isNumericValue,
115
118
  isPossessiveKeyword: () => isPossessiveKeyword,
@@ -119,7 +122,7 @@ __export(index_exports, {
119
122
  isSelectorStart: () => isSelectorStart,
120
123
  isTypeCompatible: () => isTypeCompatible,
121
124
  isUrlStart: () => isUrlStart,
122
- isValidReference: () => isValidReference2,
125
+ isValidReference: () => import_intent2.isValidReference,
123
126
  isVariableRef: () => isVariableRef,
124
127
  isWhitespace: () => isWhitespace,
125
128
  joinTokens: () => joinTokens,
@@ -131,25 +134,25 @@ __export(index_exports, {
131
134
  needsDisambiguation: () => needsDisambiguation,
132
135
  noChange: () => noChange,
133
136
  normalized: () => normalized,
134
- parseCompound: () => parseCompound,
135
- parseDocument: () => parseDocument,
136
- parseExplicit: () => parseExplicit,
137
+ parseCompound: () => import_intent3.parseCompound,
138
+ parseDocument: () => import_intent3.parseDocument,
139
+ parseExplicit: () => import_intent3.parseExplicit,
137
140
  parseJSONL: () => parseJSONL,
138
141
  patternMatcher: () => patternMatcher,
139
142
  registryToAOTBackends: () => registryToAOTBackends,
140
- renderDocument: () => renderDocument,
141
- renderExplicit: () => renderExplicit,
143
+ renderDocument: () => import_intent4.renderDocument,
144
+ renderExplicit: () => import_intent4.renderExplicit,
142
145
  renderExpr: () => renderExpr,
143
146
  reorderRoles: () => reorderRoles,
144
147
  semanticNodeToJSON: () => semanticNodeToJSON,
145
148
  semanticNodeToRuntimeAST: () => semanticNodeToRuntimeAST,
146
149
  semanticValueToAST: () => semanticValueToAST,
147
150
  synthesizeFromSchemas: () => synthesizeFromSchemas,
148
- toEnvelopeJSON: () => toEnvelopeJSON,
151
+ toEnvelopeJSON: () => import_intent5.toEnvelopeJSON,
149
152
  toJSONL: () => toJSONL,
150
153
  toJSONLRow: () => toJSONLRow,
151
- toProtocolJSON: () => toProtocolJSON,
152
- validateProtocolJSON: () => validateProtocolJSON,
154
+ toProtocolJSON: () => import_intent5.toProtocolJSON,
155
+ validateProtocolJSON: () => import_intent5.validateProtocolJSON,
153
156
  validateSemanticJSON: () => validateSemanticJSON,
154
157
  validateValueType: () => validateValueType,
155
158
  withDefaultExtractors: () => withDefaultExtractors
@@ -157,134 +160,7 @@ __export(index_exports, {
157
160
  module.exports = __toCommonJS(index_exports);
158
161
 
159
162
  // src/core/types.ts
160
- function createLiteral(value, dataType) {
161
- return dataType ? { type: "literal", value, dataType } : { type: "literal", value };
162
- }
163
- function createSelector(value, selectorKind) {
164
- return selectorKind ? { type: "selector", value, selectorKind } : { type: "selector", value };
165
- }
166
- function createReference(value) {
167
- return { type: "reference", value };
168
- }
169
- function createPropertyPath(object, property) {
170
- return { type: "property-path", object, property };
171
- }
172
- function createExpression(raw) {
173
- return { type: "expression", raw };
174
- }
175
- function createFlag(name, enabled = true) {
176
- return { type: "flag", name, enabled };
177
- }
178
- function createCommandNode(action, roles, metadata) {
179
- const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
180
- const node = {
181
- kind: "command",
182
- action,
183
- roles: rolesMap
184
- };
185
- if (metadata) {
186
- return { ...node, metadata };
187
- }
188
- return node;
189
- }
190
- function createEventHandlerNode(action, roles, body, metadata, eventModifiers) {
191
- const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
192
- const base = {
193
- kind: "event-handler",
194
- action,
195
- roles: rolesMap,
196
- body
197
- };
198
- return {
199
- ...base,
200
- ...eventModifiers && { eventModifiers },
201
- ...metadata && { metadata }
202
- };
203
- }
204
- function createConditionalNode(action, roles, thenBranch, elseBranch, metadata) {
205
- const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
206
- const base = {
207
- kind: "conditional",
208
- action,
209
- roles: rolesMap,
210
- thenBranch
211
- };
212
- return {
213
- ...base,
214
- ...elseBranch && { elseBranch },
215
- ...metadata && { metadata }
216
- };
217
- }
218
- function createCompoundNode(statements, chainType = "sequential", metadata) {
219
- const base = {
220
- kind: "compound",
221
- action: "compound",
222
- roles: /* @__PURE__ */ new Map(),
223
- statements,
224
- chainType
225
- };
226
- return metadata ? { ...base, metadata } : base;
227
- }
228
- function extractValue(value) {
229
- if (value.type === "flag") return value.name;
230
- if ("raw" in value && value.raw !== void 0) return String(value.raw);
231
- if ("value" in value && value.value !== void 0) return String(value.value);
232
- if (value.type === "property-path") return `${extractValue(value.object)}.${value.property}`;
233
- return "";
234
- }
235
- function extractRoleValue(node, role) {
236
- const value = node.roles.get(role);
237
- if (!value) return "";
238
- return extractValue(value);
239
- }
240
- function createLoopNode(action, roles, loopVariant, body, loopVariable, indexVariable, metadata) {
241
- const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
242
- const base = {
243
- kind: "loop",
244
- action,
245
- roles: rolesMap,
246
- loopVariant,
247
- body
248
- };
249
- return {
250
- ...base,
251
- ...loopVariable && { loopVariable },
252
- ...indexVariable && { indexVariable },
253
- ...metadata && { metadata }
254
- };
255
- }
256
- function createTryNode(body, catchBranch, finallyBranch, metadata) {
257
- return {
258
- kind: "command",
259
- action: "try",
260
- roles: /* @__PURE__ */ new Map(),
261
- body,
262
- ...catchBranch && catchBranch.length > 0 ? { catchBranch } : {},
263
- ...finallyBranch && finallyBranch.length > 0 ? { finallyBranch } : {},
264
- ...metadata ? { metadata } : {}
265
- };
266
- }
267
- function createAsyncNode(variant, asyncBody, metadata) {
268
- return {
269
- kind: "command",
270
- action: variant,
271
- roles: /* @__PURE__ */ new Map(),
272
- asyncVariant: variant,
273
- asyncBody,
274
- ...metadata ? { metadata } : {}
275
- };
276
- }
277
- function createMatchNode(roles, arms, defaultArm, metadata) {
278
- const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
279
- return {
280
- kind: "command",
281
- action: "match",
282
- roles: rolesMap,
283
- arms,
284
- ...defaultArm && defaultArm.length > 0 ? { defaultArm } : {},
285
- ...metadata ? { metadata } : {}
286
- };
287
- }
163
+ var import_intent = require("@lokascript/intent");
288
164
 
289
165
  // src/core/logger.ts
290
166
  var DebugLogger = class {
@@ -869,7 +745,7 @@ var _PatternMatcher = class _PatternMatcher {
869
745
  chainedProps += nextPeek.value;
870
746
  tokens.advance();
871
747
  }
872
- return createPropertyPath(createReference(baseRef), chainedProps);
748
+ return (0, import_intent.createPropertyPath)((0, import_intent.createReference)(baseRef), chainedProps);
873
749
  }
874
750
  tokens.reset(mark);
875
751
  return null;
@@ -1068,7 +944,7 @@ var _PatternMatcher = class _PatternMatcher {
1068
944
  return null;
1069
945
  }
1070
946
  tokens.advance();
1071
- return createPropertyPath(createSelector(token.value), propertyToken.value);
947
+ return (0, import_intent.createPropertyPath)((0, import_intent.createSelector)(token.value), propertyToken.value);
1072
948
  }
1073
949
  /**
1074
950
  * Try to match a selector + property expression like "#output.innerText".
@@ -1099,7 +975,7 @@ var _PatternMatcher = class _PatternMatcher {
1099
975
  }
1100
976
  tokens.advance();
1101
977
  const propertyName = propertyToken.value.slice(1);
1102
- return createPropertyPath(createSelector(token.value), propertyName);
978
+ return (0, import_intent.createPropertyPath)((0, import_intent.createSelector)(token.value), propertyName);
1103
979
  }
1104
980
  /**
1105
981
  * Match a group pattern token (optional sequence).
@@ -1230,27 +1106,27 @@ var _PatternMatcher = class _PatternMatcher {
1230
1106
  tokenToSemanticValue(token) {
1231
1107
  switch (token.kind) {
1232
1108
  case "selector":
1233
- return createSelector(token.value);
1109
+ return (0, import_intent.createSelector)(token.value);
1234
1110
  case "literal":
1235
1111
  return this.parseLiteralValue(token.value);
1236
1112
  case "keyword":
1237
1113
  const tokenValue = token.normalized || token.value;
1238
1114
  const lower = this.safeToLowerCase(tokenValue);
1239
1115
  if (isValidReference(lower)) {
1240
- return createReference(lower);
1116
+ return (0, import_intent.createReference)(lower);
1241
1117
  }
1242
- return createLiteral(token.normalized || token.value);
1118
+ return (0, import_intent.createLiteral)(token.normalized || token.value);
1243
1119
  case "identifier":
1244
1120
  if (typeof token.value === "string" && token.value.startsWith(":")) {
1245
- return createReference(token.value);
1121
+ return (0, import_intent.createReference)(token.value);
1246
1122
  }
1247
1123
  const identLower = this.safeToLowerCase(token.value);
1248
1124
  if (isValidReference(identLower)) {
1249
- return createReference(identLower);
1125
+ return (0, import_intent.createReference)(identLower);
1250
1126
  }
1251
1127
  return { type: "expression", raw: token.value };
1252
1128
  case "url":
1253
- return createLiteral(token.value, "string");
1129
+ return (0, import_intent.createLiteral)(token.value, "string");
1254
1130
  default:
1255
1131
  return null;
1256
1132
  }
@@ -1261,24 +1137,24 @@ var _PatternMatcher = class _PatternMatcher {
1261
1137
  parseLiteralValue(value) {
1262
1138
  if (value.startsWith('"') || value.startsWith("'") || value.startsWith("`") || value.startsWith("\u300C")) {
1263
1139
  const inner = value.slice(1, -1);
1264
- return createLiteral(inner, "string");
1140
+ return (0, import_intent.createLiteral)(inner, "string");
1265
1141
  }
1266
- if (value === "true") return createLiteral(true, "boolean");
1267
- if (value === "false") return createLiteral(false, "boolean");
1142
+ if (value === "true") return (0, import_intent.createLiteral)(true, "boolean");
1143
+ if (value === "false") return (0, import_intent.createLiteral)(false, "boolean");
1268
1144
  const durationMatch = value.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/);
1269
1145
  if (durationMatch) {
1270
1146
  const num2 = parseFloat(durationMatch[1]);
1271
1147
  const unit = durationMatch[2];
1272
1148
  if (unit) {
1273
- return createLiteral(value, "duration");
1149
+ return (0, import_intent.createLiteral)(value, "duration");
1274
1150
  }
1275
- return createLiteral(num2, "number");
1151
+ return (0, import_intent.createLiteral)(num2, "number");
1276
1152
  }
1277
1153
  const num = parseFloat(value);
1278
1154
  if (!isNaN(num)) {
1279
- return createLiteral(num, "number");
1155
+ return (0, import_intent.createLiteral)(num, "number");
1280
1156
  }
1281
- return createLiteral(value, "string");
1157
+ return (0, import_intent.createLiteral)(value, "string");
1282
1158
  }
1283
1159
  /**
1284
1160
  * Apply extraction rules to fill in static values and defaults for missing roles.
@@ -2132,6 +2008,22 @@ var UnicodeIdentifierExtractor = class {
2132
2008
  return length > 0 ? { value: input.substring(position, position + length), length } : null;
2133
2009
  }
2134
2010
  };
2011
+ var LatinExtendedIdentifierExtractor = class {
2012
+ constructor() {
2013
+ this.name = "latin-extended-identifier";
2014
+ }
2015
+ canExtract(input, position) {
2016
+ return /\p{L}/u.test(input[position]);
2017
+ }
2018
+ extract(input, position) {
2019
+ let end = position;
2020
+ while (end < input.length && /[\p{L}\p{N}_-]/u.test(input[end])) {
2021
+ end++;
2022
+ }
2023
+ if (end === position) return null;
2024
+ return { value: input.slice(position, end), length: end - position };
2025
+ }
2026
+ };
2135
2027
  var WhitespaceExtractor = class {
2136
2028
  constructor() {
2137
2029
  this.name = "whitespace";
@@ -2168,621 +2060,13 @@ function createTokenizerContext(tokenizer) {
2168
2060
  }
2169
2061
 
2170
2062
  // src/ir/references.ts
2171
- var DEFAULT_REFERENCES = /* @__PURE__ */ new Set([
2172
- "me",
2173
- "you",
2174
- "it",
2175
- "result",
2176
- "event",
2177
- "target",
2178
- "body"
2179
- ]);
2180
- function isValidReference2(value, referenceSet = DEFAULT_REFERENCES) {
2181
- return referenceSet.has(value);
2182
- }
2063
+ var import_intent2 = require("@lokascript/intent");
2183
2064
 
2184
2065
  // src/ir/explicit-parser.ts
2185
- var STRUCTURAL_ROLES = /* @__PURE__ */ new Set([
2186
- "body",
2187
- "then",
2188
- "else",
2189
- "condition",
2190
- "loop-body",
2191
- "variable",
2192
- "catch",
2193
- // v1.2: try/catch/finally
2194
- "finally"
2195
- // v1.2: try/catch/finally
2196
- ]);
2197
- function isNestedCommand(value) {
2198
- const inner = value.slice(1, -1);
2199
- let depth = 0;
2200
- for (const ch of inner) {
2201
- if (ch === "[") depth++;
2202
- else if (ch === "]") depth--;
2203
- else if (depth === 0 && (ch === " " || ch === ":")) return true;
2204
- }
2205
- return false;
2206
- }
2207
- function parseExplicit(input, options = {}) {
2208
- const trimmed = input.trim();
2209
- const collect = options.collectDiagnostics === true;
2210
- const diagnostics = [];
2211
- if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
2212
- throw new Error("Explicit syntax must be wrapped in brackets: [command role:value ...]");
2213
- }
2214
- const content = trimmed.slice(1, -1).trim();
2215
- if (!content) {
2216
- throw new Error("Empty explicit statement");
2217
- }
2218
- const tokens = tokenizeExplicit(content);
2219
- if (tokens.length === 0) {
2220
- throw new Error("No command specified in explicit statement");
2221
- }
2222
- const command = tokens[0].toLowerCase();
2223
- const roles = /* @__PURE__ */ new Map();
2224
- const refSet = options.referenceSet ?? DEFAULT_REFERENCES;
2225
- const schema = options.schemaLookup?.getSchema(command);
2226
- const validRoleNames = schema ? new Set(schema.roles.map((r) => r.role)) : null;
2227
- for (let i = 1; i < tokens.length; i++) {
2228
- const token = tokens[i];
2229
- if (token.startsWith("+") || token.startsWith("~")) {
2230
- const enabled = token.startsWith("+");
2231
- const flagName = token.slice(1);
2232
- if (!flagName) {
2233
- if (collect) {
2234
- diagnostics.push({
2235
- severity: "error",
2236
- code: "EMPTY_FLAG",
2237
- message: `Empty flag name: "${token}"`,
2238
- source: "schema"
2239
- });
2240
- continue;
2241
- }
2242
- throw new Error(`Empty flag name: "${token}"`);
2243
- }
2244
- if (validRoleNames && !validRoleNames.has(flagName)) {
2245
- const roleList = [...validRoleNames].join(", ");
2246
- if (collect) {
2247
- diagnostics.push({
2248
- severity: "error",
2249
- code: "UNKNOWN_FLAG",
2250
- message: `Unknown flag "${flagName}" for command "${command}"`,
2251
- source: "schema",
2252
- suggestions: [...validRoleNames].map((r) => `+${r}`)
2253
- });
2254
- roles.set(flagName, createFlag(flagName, enabled));
2255
- continue;
2256
- }
2257
- throw new Error(
2258
- `Unknown flag "${flagName}" for command "${command}". Valid roles: ${roleList}`
2259
- );
2260
- }
2261
- roles.set(flagName, createFlag(flagName, enabled));
2262
- continue;
2263
- }
2264
- const colonIndex = token.indexOf(":");
2265
- if (colonIndex === -1) {
2266
- if (collect) {
2267
- diagnostics.push({
2268
- severity: "error",
2269
- code: "INVALID_ROLE_FORMAT",
2270
- message: `Invalid role format: "${token}". Expected role:value or +flag`,
2271
- source: "schema"
2272
- });
2273
- continue;
2274
- }
2275
- throw new Error(`Invalid role format: "${token}". Expected role:value or +flag`);
2276
- }
2277
- const roleName = token.slice(0, colonIndex);
2278
- if (validRoleNames && !STRUCTURAL_ROLES.has(roleName) && !validRoleNames.has(roleName)) {
2279
- const roleList = [...validRoleNames].join(", ");
2280
- if (collect) {
2281
- diagnostics.push({
2282
- severity: "error",
2283
- code: "UNKNOWN_ROLE",
2284
- message: `Unknown role "${roleName}" for command "${command}"`,
2285
- source: "schema",
2286
- suggestions: [...validRoleNames]
2287
- });
2288
- } else {
2289
- throw new Error(
2290
- `Unknown role "${roleName}" for command "${command}". Valid roles: ${roleList}`
2291
- );
2292
- }
2293
- }
2294
- const role = roleName;
2295
- const valueStr = token.slice(colonIndex + 1);
2296
- if (STRUCTURAL_ROLES.has(roleName) && valueStr.startsWith("[") && isNestedCommand(valueStr)) {
2297
- const nestedEnd = findMatchingBracket(token, colonIndex + 1);
2298
- const nestedSyntax = token.slice(colonIndex + 1, nestedEnd + 1);
2299
- roles.set(role, { type: "expression", raw: nestedSyntax });
2300
- continue;
2301
- }
2302
- const value = parseExplicitValue(valueStr, refSet);
2303
- roles.set(role, value);
2304
- }
2305
- if (schema && command !== "on") {
2306
- for (const roleSpec of schema.roles) {
2307
- if (roleSpec.required && !roles.has(roleSpec.role) && !roleSpec.default) {
2308
- if (collect) {
2309
- diagnostics.push({
2310
- severity: "error",
2311
- code: "MISSING_REQUIRED_ROLE",
2312
- message: `Missing required role "${roleSpec.role}" for command "${command}": ${roleSpec.description}`,
2313
- source: "schema"
2314
- });
2315
- } else {
2316
- throw new Error(
2317
- `Missing required role "${roleSpec.role}" for command "${command}": ${roleSpec.description}`
2318
- );
2319
- }
2320
- }
2321
- }
2322
- }
2323
- const attachDiagnostics = (node) => {
2324
- if (diagnostics.length === 0) return node;
2325
- return { ...node, diagnostics };
2326
- };
2327
- switch (command) {
2328
- case "on": {
2329
- const eventValue = roles.get("event");
2330
- if (!eventValue) {
2331
- if (collect) {
2332
- diagnostics.push({
2333
- severity: "error",
2334
- code: "MISSING_EVENT_ROLE",
2335
- message: "Event handler requires event role: [on event:click ...]",
2336
- source: "schema"
2337
- });
2338
- return attachDiagnostics(
2339
- createEventHandlerNode("on", roles, [], {
2340
- sourceLanguage: "explicit"
2341
- })
2342
- );
2343
- }
2344
- throw new Error("Event handler requires event role: [on event:click ...]");
2345
- }
2346
- const body = extractStructuralBody(roles, "body", options);
2347
- roles.delete("body");
2348
- return attachDiagnostics(
2349
- createEventHandlerNode("on", roles, body, {
2350
- sourceLanguage: "explicit"
2351
- })
2352
- );
2353
- }
2354
- case "if": {
2355
- const thenBranch = extractStructuralBody(roles, "then", options);
2356
- const elseBranch = extractStructuralBody(roles, "else", options);
2357
- roles.delete("then");
2358
- roles.delete("else");
2359
- return attachDiagnostics(
2360
- createConditionalNode(
2361
- command,
2362
- roles,
2363
- thenBranch,
2364
- elseBranch.length > 0 ? elseBranch : void 0,
2365
- {
2366
- sourceLanguage: "explicit"
2367
- }
2368
- )
2369
- );
2370
- }
2371
- case "repeat": {
2372
- const loopBody = extractStructuralBody(roles, "loop-body", options);
2373
- const loopVariantValue = roles.get("loop-variant");
2374
- const variableValue = roles.get("variable");
2375
- const indexVariableValue = roles.get("index-variable");
2376
- roles.delete("loop-body");
2377
- roles.delete("loop-variant");
2378
- roles.delete("variable");
2379
- roles.delete("index-variable");
2380
- let variant;
2381
- if (loopVariantValue && loopVariantValue.type === "literal" && typeof loopVariantValue.value === "string") {
2382
- variant = loopVariantValue.value;
2383
- } else if (roles.has("quantity")) {
2384
- variant = "times";
2385
- } else if (roles.has("source")) {
2386
- variant = "for";
2387
- } else if (roles.has("condition")) {
2388
- variant = "while";
2389
- } else {
2390
- variant = "forever";
2391
- }
2392
- const loopVariable = variableValue?.type === "literal" && typeof variableValue.value === "string" ? variableValue.value : variableValue?.type === "expression" ? variableValue.raw : void 0;
2393
- const indexVariable = indexVariableValue?.type === "literal" && typeof indexVariableValue.value === "string" ? indexVariableValue.value : void 0;
2394
- return attachDiagnostics(
2395
- createLoopNode(command, roles, variant, loopBody, loopVariable, indexVariable, {
2396
- sourceLanguage: "explicit"
2397
- })
2398
- );
2399
- }
2400
- default:
2401
- return attachDiagnostics(
2402
- createCommandNode(command, roles, {
2403
- sourceLanguage: "explicit"
2404
- })
2405
- );
2406
- }
2407
- }
2408
- function isExplicitSyntax(input) {
2409
- const trimmed = input.trim();
2410
- return trimmed.startsWith("[") && trimmed.endsWith("]");
2411
- }
2412
- var CHAIN_KEYWORDS = /* @__PURE__ */ new Set(["then", "and", "async", "sequential"]);
2413
- function splitCompoundSegments(input) {
2414
- const segments = [];
2415
- let chainType = null;
2416
- let current = "";
2417
- let bracketDepth = 0;
2418
- let inString = false;
2419
- let stringChar = "";
2420
- for (let i = 0; i < input.length; i++) {
2421
- const char = input[i];
2422
- if (inString) {
2423
- current += char;
2424
- if (char === stringChar && input[i - 1] !== "\\") {
2425
- inString = false;
2426
- }
2427
- continue;
2428
- }
2429
- if (char === '"' || char === "'") {
2430
- inString = true;
2431
- stringChar = char;
2432
- current += char;
2433
- continue;
2434
- }
2435
- if (char === "[") {
2436
- bracketDepth++;
2437
- current += char;
2438
- continue;
2439
- }
2440
- if (char === "]") {
2441
- bracketDepth--;
2442
- current += char;
2443
- if (bracketDepth === 0) {
2444
- const rest = input.slice(i + 1);
2445
- const pipeMatch = rest.match(/^\s*\|>\s*/);
2446
- if (pipeMatch) {
2447
- segments.push(current.trim());
2448
- current = "";
2449
- chainType ?? (chainType = "pipe");
2450
- i += pipeMatch[0].length;
2451
- continue;
2452
- }
2453
- const keywordMatch = rest.match(/^\s+(then|and|async|sequential)\s+/);
2454
- if (keywordMatch && CHAIN_KEYWORDS.has(keywordMatch[1])) {
2455
- segments.push(current.trim());
2456
- current = "";
2457
- chainType ?? (chainType = keywordMatch[1]);
2458
- i += keywordMatch[0].length;
2459
- continue;
2460
- }
2461
- }
2462
- continue;
2463
- }
2464
- current += char;
2465
- }
2466
- if (current.trim()) {
2467
- segments.push(current.trim());
2468
- }
2469
- return { segments, chainType };
2470
- }
2471
- function parseCompound(input, options) {
2472
- const trimmed = input.trim();
2473
- const { annotations, remainder } = extractAnnotations(trimmed);
2474
- const { segments, chainType } = splitCompoundSegments(remainder);
2475
- let node;
2476
- if (segments.length <= 1) {
2477
- node = parseExplicit(segments[0] || remainder, options);
2478
- } else {
2479
- const statements = segments.map((seg) => parseExplicit(seg, options));
2480
- node = createCompoundNode(statements, chainType ?? "sequential");
2481
- }
2482
- if (annotations.length > 0) {
2483
- return { ...node, annotations };
2484
- }
2485
- return node;
2486
- }
2487
- function extractAnnotations(input) {
2488
- const annotations = [];
2489
- let pos = 0;
2490
- while (pos < input.length) {
2491
- while (pos < input.length && (input[pos] === " " || input[pos] === " ")) {
2492
- pos++;
2493
- }
2494
- if (pos >= input.length || input[pos] !== "@") {
2495
- break;
2496
- }
2497
- pos++;
2498
- const nameStart = pos;
2499
- while (pos < input.length && /[A-Za-z0-9\-_]/.test(input[pos])) {
2500
- pos++;
2501
- }
2502
- const name = input.slice(nameStart, pos);
2503
- if (!name) break;
2504
- let value;
2505
- if (pos < input.length && input[pos] === "(") {
2506
- pos++;
2507
- const valueStart = pos;
2508
- if (pos < input.length && (input[pos] === '"' || input[pos] === "'")) {
2509
- const quote = input[pos];
2510
- pos++;
2511
- while (pos < input.length && input[pos] !== quote) {
2512
- if (input[pos] === "\\") pos++;
2513
- pos++;
2514
- }
2515
- pos++;
2516
- value = input.slice(valueStart + 1, pos - 1);
2517
- } else {
2518
- while (pos < input.length && input[pos] !== ")") {
2519
- pos++;
2520
- }
2521
- value = input.slice(valueStart, pos);
2522
- }
2523
- if (pos < input.length && input[pos] === ")") {
2524
- pos++;
2525
- }
2526
- }
2527
- annotations.push(value !== void 0 ? { name, value } : { name });
2528
- }
2529
- return { annotations, remainder: input.slice(pos).trim() };
2530
- }
2531
- var VERSION_HEADER_RE = /^#!lse\s+(\d+\.\d+(?:\.\d+)?)\s*$/;
2532
- function parseDocument(input, options) {
2533
- const lines = input.split("\n");
2534
- let lseVersion = "1.0";
2535
- const nodes = [];
2536
- let startLine = 0;
2537
- for (let i = 0; i < lines.length; i++) {
2538
- const trimmed = lines[i].trim();
2539
- if (!trimmed) continue;
2540
- const versionMatch = trimmed.match(VERSION_HEADER_RE);
2541
- if (versionMatch) {
2542
- lseVersion = versionMatch[1];
2543
- startLine = i + 1;
2544
- }
2545
- break;
2546
- }
2547
- for (let i = startLine; i < lines.length; i++) {
2548
- const trimmed = lines[i].trim();
2549
- if (!trimmed) continue;
2550
- if (trimmed.startsWith("//") || trimmed.startsWith("#") && !trimmed.startsWith("#!")) {
2551
- continue;
2552
- }
2553
- nodes.push(parseCompound(trimmed, options));
2554
- }
2555
- return { lseVersion, nodes };
2556
- }
2557
- function isCompoundSyntax(input) {
2558
- const { segments } = splitCompoundSegments(input.trim());
2559
- return segments.length > 1;
2560
- }
2561
- function isDocumentSyntax(input) {
2562
- const trimmed = input.trim();
2563
- if (trimmed.includes("\n")) return true;
2564
- if (VERSION_HEADER_RE.test(trimmed)) return true;
2565
- if (trimmed.startsWith("//") || trimmed.startsWith("#") && !trimmed.startsWith("#!")) {
2566
- return true;
2567
- }
2568
- return false;
2569
- }
2570
- function extractStructuralBody(roles, roleName, options) {
2571
- const value = roles.get(roleName);
2572
- if (!value) return [];
2573
- if (value.type === "expression") {
2574
- return [parseExplicit(value.raw, options)];
2575
- }
2576
- return [];
2577
- }
2578
- function inferSelectorKind(value) {
2579
- if (!value) return void 0;
2580
- if (value.startsWith("#")) return "id";
2581
- if (value.startsWith(".")) return "class";
2582
- if (value.startsWith("[")) return "attribute";
2583
- if (value.startsWith("<") || value.startsWith("*")) return "element";
2584
- if (/[>+~ ]/.test(value) && value.length > 1) return "complex";
2585
- return void 0;
2586
- }
2587
- function tokenizeExplicit(content) {
2588
- const tokens = [];
2589
- let current = "";
2590
- let inString = false;
2591
- let stringChar = "";
2592
- let bracketDepth = 0;
2593
- for (let i = 0; i < content.length; i++) {
2594
- const char = content[i];
2595
- if (inString) {
2596
- current += char;
2597
- if (char === stringChar && content[i - 1] !== "\\") {
2598
- inString = false;
2599
- }
2600
- continue;
2601
- }
2602
- if (char === '"' || char === "'") {
2603
- inString = true;
2604
- stringChar = char;
2605
- current += char;
2606
- continue;
2607
- }
2608
- if (char === "[") {
2609
- bracketDepth++;
2610
- current += char;
2611
- continue;
2612
- }
2613
- if (char === "]") {
2614
- bracketDepth--;
2615
- current += char;
2616
- continue;
2617
- }
2618
- if (char === " " && bracketDepth === 0) {
2619
- if (current) {
2620
- tokens.push(current);
2621
- current = "";
2622
- }
2623
- continue;
2624
- }
2625
- current += char;
2626
- }
2627
- if (current) {
2628
- tokens.push(current);
2629
- }
2630
- return tokens;
2631
- }
2632
- function parseExplicitValue(valueStr, referenceSet) {
2633
- if (valueStr.startsWith("#") || valueStr.startsWith(".") || valueStr.startsWith("[") || valueStr.startsWith("@") || valueStr.startsWith("*")) {
2634
- return createSelector(valueStr, inferSelectorKind(valueStr));
2635
- }
2636
- if (valueStr.startsWith('"') || valueStr.startsWith("'")) {
2637
- const inner = valueStr.slice(1, -1);
2638
- return createLiteral(inner, "string");
2639
- }
2640
- if (valueStr === "true") return createLiteral(true, "boolean");
2641
- if (valueStr === "false") return createLiteral(false, "boolean");
2642
- const lowerRef = valueStr.toLowerCase();
2643
- if (isValidReference2(lowerRef, referenceSet)) {
2644
- return createReference(lowerRef);
2645
- }
2646
- const numMatch = valueStr.match(/^(-?\d+(?:\.\d+)?)(ms|s|m|h)?$/);
2647
- if (numMatch) {
2648
- const num = parseFloat(numMatch[1]);
2649
- const suffix = numMatch[2];
2650
- if (suffix) {
2651
- return createLiteral(valueStr, "duration");
2652
- }
2653
- return createLiteral(num, "number");
2654
- }
2655
- return createLiteral(valueStr);
2656
- }
2657
- function findMatchingBracket(str, start) {
2658
- let depth = 0;
2659
- for (let i = start; i < str.length; i++) {
2660
- if (str[i] === "[") depth++;
2661
- else if (str[i] === "]") {
2662
- depth--;
2663
- if (depth === 0) return i;
2664
- }
2665
- }
2666
- return str.length - 1;
2667
- }
2066
+ var import_intent3 = require("@lokascript/intent");
2668
2067
 
2669
2068
  // src/ir/explicit-renderer.ts
2670
- function renderExplicit(node) {
2671
- let result;
2672
- if (node.kind === "compound") {
2673
- const compoundNode = node;
2674
- const renderedStatements = compoundNode.statements.map((stmt) => renderExplicit(stmt));
2675
- result = renderedStatements.join(` ${compoundNode.chainType} `);
2676
- } else {
2677
- result = renderBracketCommand(node);
2678
- }
2679
- if (node.annotations && node.annotations.length > 0) {
2680
- const annParts = node.annotations.map(
2681
- (ann) => ann.value !== void 0 ? `@${ann.name}(${ann.value})` : `@${ann.name}`
2682
- );
2683
- return annParts.join(" ") + " " + result;
2684
- }
2685
- return result;
2686
- }
2687
- function renderDocument(envelope) {
2688
- const lines = [];
2689
- if (envelope.lseVersion && envelope.lseVersion !== "1.0") {
2690
- lines.push(`#!lse ${envelope.lseVersion}`);
2691
- }
2692
- for (const node of envelope.nodes) {
2693
- lines.push(renderExplicit(node));
2694
- }
2695
- return lines.join("\n");
2696
- }
2697
- function renderBracketCommand(node) {
2698
- const parts = [node.action];
2699
- for (const [role, value] of node.roles) {
2700
- if (value.type === "flag") {
2701
- parts.push(value.enabled ? `+${value.name}` : `~${value.name}`);
2702
- } else {
2703
- parts.push(`${role}:${valueToString(value)}`);
2704
- }
2705
- }
2706
- if (node.kind === "event-handler") {
2707
- const eventNode = node;
2708
- if (eventNode.body && eventNode.body.length > 0) {
2709
- const bodyParts = eventNode.body.map((n) => renderExplicit(n));
2710
- parts.push(`body:${bodyParts.join(" ")}`);
2711
- }
2712
- }
2713
- if (node.kind === "conditional") {
2714
- const condNode = node;
2715
- if (condNode.thenBranch && condNode.thenBranch.length > 0) {
2716
- const thenParts = condNode.thenBranch.map((n) => renderExplicit(n));
2717
- parts.push(`then:${thenParts.join(" ")}`);
2718
- }
2719
- if (condNode.elseBranch && condNode.elseBranch.length > 0) {
2720
- const elseParts = condNode.elseBranch.map((n) => renderExplicit(n));
2721
- parts.push(`else:${elseParts.join(" ")}`);
2722
- }
2723
- }
2724
- if (node.kind === "loop") {
2725
- const loopNode = node;
2726
- if (loopNode.loopVariant) {
2727
- parts.push(`loop-variant:${loopNode.loopVariant}`);
2728
- }
2729
- if (loopNode.loopVariable) {
2730
- parts.push(`variable:${loopNode.loopVariable}`);
2731
- }
2732
- if (loopNode.indexVariable) {
2733
- parts.push(`index-variable:${loopNode.indexVariable}`);
2734
- }
2735
- if (loopNode.body && loopNode.body.length > 0) {
2736
- const bodyParts = loopNode.body.map((n) => renderExplicit(n));
2737
- parts.push(`loop-body:${bodyParts.join(" ")}`);
2738
- }
2739
- }
2740
- if (node.kind === "command") {
2741
- const cmd = node;
2742
- if (cmd.body && cmd.body.length > 0) {
2743
- const bodyParts = cmd.body.map((n) => renderExplicit(n));
2744
- parts.push(`body:${bodyParts.join(" ")}`);
2745
- }
2746
- if (cmd.catchBranch && cmd.catchBranch.length > 0) {
2747
- const catchParts = cmd.catchBranch.map((n) => renderExplicit(n));
2748
- parts.push(`catch:${catchParts.join(" ")}`);
2749
- }
2750
- if (cmd.finallyBranch && cmd.finallyBranch.length > 0) {
2751
- const finallyParts = cmd.finallyBranch.map((n) => renderExplicit(n));
2752
- parts.push(`finally:${finallyParts.join(" ")}`);
2753
- }
2754
- if (cmd.asyncVariant) {
2755
- parts.push(`async-variant:${cmd.asyncVariant}`);
2756
- }
2757
- if (cmd.asyncBody && cmd.asyncBody.length > 0) {
2758
- const asyncParts = cmd.asyncBody.map((n) => renderExplicit(n));
2759
- parts.push(`async-body:${asyncParts.join(" ")}`);
2760
- }
2761
- }
2762
- return `[${parts.join(" ")}]`;
2763
- }
2764
- function valueToString(value) {
2765
- switch (value.type) {
2766
- case "literal":
2767
- if (typeof value.value === "string") {
2768
- if (value.dataType === "string" || /\s/.test(value.value)) {
2769
- return `"${value.value}"`;
2770
- }
2771
- return value.value;
2772
- }
2773
- return String(value.value);
2774
- case "selector":
2775
- return value.value;
2776
- case "reference":
2777
- return value.value;
2778
- case "property-path":
2779
- return `${valueToString(value.object)}'s ${value.property}`;
2780
- case "expression":
2781
- return value.raw;
2782
- case "flag":
2783
- return value.name;
2784
- }
2785
- }
2069
+ var import_intent4 = require("@lokascript/intent");
2786
2070
 
2787
2071
  // src/ir/json-schema.ts
2788
2072
  var VALID_VALUE_TYPES = /* @__PURE__ */ new Set([
@@ -2853,11 +2137,11 @@ function jsonToSemanticNode(input) {
2853
2137
  }
2854
2138
  }
2855
2139
  if (input.trigger) {
2856
- roles.set("event", createLiteral(input.trigger.event, "string"));
2140
+ roles.set("event", (0, import_intent.createLiteral)(input.trigger.event, "string"));
2857
2141
  const bodyRoles = new Map(roles);
2858
2142
  bodyRoles.delete("event");
2859
- const bodyNode = createCommandNode(input.action, bodyRoles);
2860
- return createEventHandlerNode(
2143
+ const bodyNode = (0, import_intent.createCommandNode)(input.action, bodyRoles);
2144
+ return (0, import_intent.createEventHandlerNode)(
2861
2145
  "on",
2862
2146
  roles,
2863
2147
  [bodyNode],
@@ -2865,7 +2149,7 @@ function jsonToSemanticNode(input) {
2865
2149
  input.trigger.modifiers ?? {}
2866
2150
  );
2867
2151
  }
2868
- return createCommandNode(input.action, roles, {
2152
+ return (0, import_intent.createCommandNode)(input.action, roles, {
2869
2153
  sourceLanguage: "json"
2870
2154
  });
2871
2155
  }
@@ -2909,22 +2193,22 @@ function semanticNodeToJSON(node) {
2909
2193
  function convertJSONValue(value) {
2910
2194
  switch (value.type) {
2911
2195
  case "selector":
2912
- return createSelector(String(value.value), detectSelectorKind(String(value.value)));
2196
+ return (0, import_intent.createSelector)(String(value.value), detectSelectorKind(String(value.value)));
2913
2197
  case "literal":
2914
- return createLiteral(
2198
+ return (0, import_intent.createLiteral)(
2915
2199
  value.value,
2916
2200
  typeof value.value === "number" ? "number" : typeof value.value === "boolean" ? "boolean" : "string"
2917
2201
  );
2918
2202
  case "reference":
2919
- return createReference(String(value.value));
2203
+ return (0, import_intent.createReference)(String(value.value));
2920
2204
  case "expression":
2921
- return createExpression(String(value.value));
2205
+ return (0, import_intent.createExpression)(String(value.value));
2922
2206
  case "property-path":
2923
- return createExpression(String(value.value));
2207
+ return (0, import_intent.createExpression)(String(value.value));
2924
2208
  case "flag":
2925
- return createFlag(String(value.value), true);
2209
+ return (0, import_intent.createFlag)(String(value.value), true);
2926
2210
  default:
2927
- return createLiteral(String(value.value), "string");
2211
+ return (0, import_intent.createLiteral)(String(value.value), "string");
2928
2212
  }
2929
2213
  }
2930
2214
  function semanticValueToJSON(value) {
@@ -2954,532 +2238,12 @@ function detectSelectorKind(selector) {
2954
2238
  }
2955
2239
 
2956
2240
  // src/ir/protocol-json.ts
2957
- function toProtocolJSON(node) {
2958
- const roles = rolesToProtocol(node.roles);
2959
- let result;
2960
- switch (node.kind) {
2961
- case "command": {
2962
- const cmd = node;
2963
- result = { kind: "command", action: node.action, roles };
2964
- if (cmd.body && cmd.body.length > 0) {
2965
- result.body = cmd.body.map(toProtocolJSON);
2966
- }
2967
- if (cmd.catchBranch && cmd.catchBranch.length > 0) {
2968
- result.catchBranch = cmd.catchBranch.map(toProtocolJSON);
2969
- }
2970
- if (cmd.finallyBranch && cmd.finallyBranch.length > 0) {
2971
- result.finallyBranch = cmd.finallyBranch.map(toProtocolJSON);
2972
- }
2973
- if (cmd.asyncVariant) {
2974
- result.asyncVariant = cmd.asyncVariant;
2975
- }
2976
- if (cmd.asyncBody && cmd.asyncBody.length > 0) {
2977
- result.asyncBody = cmd.asyncBody.map(toProtocolJSON);
2978
- }
2979
- if (cmd.arms && cmd.arms.length > 0) {
2980
- result.arms = cmd.arms.map((arm) => ({
2981
- pattern: valueToProtocol(arm.pattern),
2982
- body: arm.body.map(toProtocolJSON)
2983
- }));
2984
- }
2985
- if (cmd.defaultArm && cmd.defaultArm.length > 0) {
2986
- result.defaultArm = cmd.defaultArm.map(toProtocolJSON);
2987
- }
2988
- break;
2989
- }
2990
- case "event-handler": {
2991
- const eh = node;
2992
- result = {
2993
- kind: "event-handler",
2994
- action: node.action,
2995
- roles,
2996
- body: eh.body.map(toProtocolJSON)
2997
- };
2998
- break;
2999
- }
3000
- case "compound": {
3001
- const c = node;
3002
- result = {
3003
- kind: "compound",
3004
- action: "compound",
3005
- statements: c.statements.map(toProtocolJSON),
3006
- chainType: c.chainType
3007
- };
3008
- break;
3009
- }
3010
- case "conditional": {
3011
- const cond = node;
3012
- result = { kind: "command", action: node.action, roles };
3013
- result.thenBranch = cond.thenBranch.map(toProtocolJSON);
3014
- if (cond.elseBranch && cond.elseBranch.length > 0) {
3015
- result.elseBranch = cond.elseBranch.map(toProtocolJSON);
3016
- }
3017
- break;
3018
- }
3019
- case "loop": {
3020
- const loop = node;
3021
- result = { kind: "command", action: node.action, roles };
3022
- result.loopVariant = loop.loopVariant;
3023
- result.loopBody = loop.body.map(toProtocolJSON);
3024
- if (loop.loopVariable) result.loopVariable = loop.loopVariable;
3025
- if (loop.indexVariable) result.indexVariable = loop.indexVariable;
3026
- break;
3027
- }
3028
- }
3029
- if (node.annotations && node.annotations.length > 0) {
3030
- result.annotations = node.annotations.map(
3031
- (a) => a.value !== void 0 ? { name: a.name, value: a.value } : { name: a.name }
3032
- );
3033
- }
3034
- if (node.diagnostics && node.diagnostics.length > 0) {
3035
- result.diagnostics = node.diagnostics.map((d) => {
3036
- const json = {
3037
- level: d.severity,
3038
- message: d.message
3039
- };
3040
- if (d.code) json.code = d.code;
3041
- if (d.source) json.source = d.source;
3042
- if (d.suggestions && d.suggestions.length > 0) json.suggestions = [...d.suggestions];
3043
- return json;
3044
- });
3045
- }
3046
- return result;
3047
- }
3048
- function rolesToProtocol(roles) {
3049
- const result = {};
3050
- for (const [role, value] of roles) {
3051
- result[role] = valueToProtocol(value);
3052
- }
3053
- return result;
3054
- }
3055
- function valueToProtocol(value) {
3056
- switch (value.type) {
3057
- case "selector": {
3058
- const PROTOCOL_SELECTOR_KINDS = /* @__PURE__ */ new Set([
3059
- "id",
3060
- "class",
3061
- "attribute",
3062
- "element",
3063
- "complex"
3064
- ]);
3065
- const sk = "selectorKind" in value ? value.selectorKind : void 0;
3066
- const sv = { type: "selector", value: value.value };
3067
- if (sk && PROTOCOL_SELECTOR_KINDS.has(sk)) {
3068
- sv.selectorKind = sk;
3069
- }
3070
- return sv;
3071
- }
3072
- case "literal":
3073
- return value.dataType ? { type: "literal", value: value.value, dataType: value.dataType } : { type: "literal", value: value.value };
3074
- case "reference":
3075
- return { type: "reference", value: value.value };
3076
- case "expression":
3077
- return { type: "expression", raw: value.raw };
3078
- case "property-path":
3079
- return { type: "expression", raw: extractValue(value) };
3080
- case "flag":
3081
- return { type: "flag", name: value.name, enabled: value.enabled };
3082
- }
3083
- }
3084
- function fromProtocolJSON(json) {
3085
- const roles = new Map(
3086
- Object.entries(json.roles ?? {}).map(([role, val]) => [role, valueFromProtocol(val)])
3087
- );
3088
- const annotations = json.annotations?.map(
3089
- (a) => a.value !== void 0 ? { name: a.name, value: a.value } : { name: a.name }
3090
- );
3091
- const diagnostics = json.diagnostics?.map((d) => ({
3092
- severity: d.level,
3093
- message: d.message,
3094
- ...d.code ? { code: d.code } : {},
3095
- ...d.source ? { source: d.source } : {},
3096
- ...d.suggestions && d.suggestions.length > 0 ? { suggestions: d.suggestions } : {}
3097
- }));
3098
- if (json.trigger) {
3099
- const eventName = json.trigger.event;
3100
- roles.set("event", createLiteral(eventName, "string"));
3101
- const bodyRoles = new Map(roles);
3102
- bodyRoles.delete("event");
3103
- const bodyNode = createCommandNode(json.action, bodyRoles);
3104
- const node2 = createEventHandlerNode(
3105
- "on",
3106
- roles,
3107
- [bodyNode],
3108
- { sourceLanguage: "json" },
3109
- json.trigger.modifiers ?? {}
3110
- );
3111
- return applyV12Metadata(node2, annotations, diagnostics);
3112
- }
3113
- const kind = json.kind ?? "command";
3114
- if (kind === "event-handler") {
3115
- const body = (json.body ?? []).map(fromProtocolJSON);
3116
- const node2 = createEventHandlerNode(json.action, roles, body);
3117
- return applyV12Metadata(node2, annotations, diagnostics);
3118
- }
3119
- if (kind === "compound") {
3120
- const statements = (json.statements ?? []).map(fromProtocolJSON);
3121
- const node2 = createCompoundNode(
3122
- statements,
3123
- json.chainType ?? "sequential"
3124
- );
3125
- return applyV12Metadata(node2, annotations, diagnostics);
3126
- }
3127
- if (json.thenBranch && json.thenBranch.length > 0) {
3128
- const thenBranch = json.thenBranch.map(fromProtocolJSON);
3129
- const elseBranch = json.elseBranch ? json.elseBranch.map(fromProtocolJSON) : void 0;
3130
- const node2 = createConditionalNode(json.action, roles, thenBranch, elseBranch);
3131
- return applyV12Metadata(node2, annotations, diagnostics);
3132
- }
3133
- if (json.loopVariant) {
3134
- const loopBody = (json.loopBody ?? []).map(fromProtocolJSON);
3135
- const node2 = createLoopNode(
3136
- json.action,
3137
- roles,
3138
- json.loopVariant,
3139
- loopBody,
3140
- json.loopVariable,
3141
- json.indexVariable
3142
- );
3143
- return applyV12Metadata(node2, annotations, diagnostics);
3144
- }
3145
- if (json.catchBranch || json.finallyBranch) {
3146
- const body = (json.body ?? []).map(fromProtocolJSON);
3147
- const catchBranch = json.catchBranch ? json.catchBranch.map(fromProtocolJSON) : void 0;
3148
- const finallyBranch = json.finallyBranch ? json.finallyBranch.map(fromProtocolJSON) : void 0;
3149
- const node2 = createTryNode(body, catchBranch, finallyBranch);
3150
- return applyV12Metadata(node2, annotations, diagnostics);
3151
- }
3152
- if (json.asyncVariant) {
3153
- const asyncBody = (json.asyncBody ?? []).map(fromProtocolJSON);
3154
- const node2 = createAsyncNode(json.asyncVariant, asyncBody);
3155
- return applyV12Metadata(node2, annotations, diagnostics);
3156
- }
3157
- if (json.arms && json.arms.length > 0) {
3158
- const arms = json.arms.map((arm) => ({
3159
- pattern: valueFromProtocol(arm.pattern),
3160
- body: arm.body.map(fromProtocolJSON)
3161
- }));
3162
- const defaultArm = json.defaultArm ? json.defaultArm.map(fromProtocolJSON) : void 0;
3163
- const node2 = createMatchNode(roles, arms, defaultArm);
3164
- return applyV12Metadata(node2, annotations, diagnostics);
3165
- }
3166
- if (json.body && json.body.length > 0 && kind === "command") {
3167
- const body = json.body.map(fromProtocolJSON);
3168
- const node2 = createTryNode(body);
3169
- return applyV12Metadata(node2, annotations, diagnostics);
3170
- }
3171
- const node = createCommandNode(json.action, roles);
3172
- return applyV12Metadata(node, annotations, diagnostics);
3173
- }
3174
- function applyV12Metadata(node, annotations, diagnostics) {
3175
- if ((!annotations || annotations.length === 0) && (!diagnostics || diagnostics.length === 0)) {
3176
- return node;
3177
- }
3178
- return {
3179
- ...node,
3180
- ...annotations && annotations.length > 0 ? { annotations } : {},
3181
- ...diagnostics && diagnostics.length > 0 ? { diagnostics } : {}
3182
- };
3183
- }
3184
- function valueFromProtocol(value) {
3185
- switch (value.type) {
3186
- case "selector":
3187
- return createSelector(String(value.value ?? ""), value.selectorKind);
3188
- case "literal":
3189
- return createLiteral(
3190
- value.value !== void 0 ? value.value : "",
3191
- value.dataType
3192
- );
3193
- case "reference":
3194
- return createReference(String(value.value ?? ""));
3195
- case "expression":
3196
- return createExpression(value.raw ?? String(value.value ?? ""));
3197
- case "flag":
3198
- return createFlag(
3199
- value.name ?? String(value.value ?? ""),
3200
- value.enabled ?? (typeof value.value === "boolean" ? value.value : true)
3201
- );
3202
- case "property-path":
3203
- return createExpression(String(value.value ?? value.raw ?? ""));
3204
- }
3205
- }
3206
- function toEnvelopeJSON(envelope) {
3207
- const result = {
3208
- lseVersion: envelope.lseVersion,
3209
- nodes: envelope.nodes.map(toProtocolJSON)
3210
- };
3211
- if (envelope.features && envelope.features.length > 0) {
3212
- result.features = [...envelope.features];
3213
- }
3214
- return result;
3215
- }
3216
- function fromEnvelopeJSON(json) {
3217
- return {
3218
- lseVersion: json.lseVersion,
3219
- ...json.features && json.features.length > 0 ? { features: json.features } : {},
3220
- nodes: json.nodes.map(fromProtocolJSON)
3221
- };
3222
- }
3223
- function isEnvelope(json) {
3224
- return typeof json === "object" && json !== null && "lseVersion" in json && "nodes" in json && Array.isArray(json.nodes);
3225
- }
3226
- var VALID_KINDS = /* @__PURE__ */ new Set(["command", "event-handler", "compound"]);
3227
- var VALID_VALUE_TYPES2 = /* @__PURE__ */ new Set([
3228
- "selector",
3229
- "literal",
3230
- "reference",
3231
- "expression",
3232
- "property-path",
3233
- "flag"
3234
- ]);
3235
- var VALID_CHAIN_TYPES = /* @__PURE__ */ new Set(["then", "and", "async", "sequential", "pipe"]);
3236
- var VALID_ASYNC_VARIANTS = /* @__PURE__ */ new Set(["all", "race"]);
3237
- var VALID_DIAGNOSTIC_LEVELS = /* @__PURE__ */ new Set(["error", "warning", "info"]);
3238
- function validateProtocolJSON(json) {
3239
- const diagnostics = [];
3240
- if (typeof json !== "object" || json === null) {
3241
- return [{ severity: "error", code: "INVALID_ROOT", message: "Root must be a JSON object" }];
3242
- }
3243
- const node = json;
3244
- const kind = "kind" in node ? String(node.kind) : "command";
3245
- if ("kind" in node && !VALID_KINDS.has(kind)) {
3246
- diagnostics.push({
3247
- severity: "error",
3248
- code: "INVALID_KIND",
3249
- message: `Invalid kind "${node.kind}". Must be one of: command, event-handler, compound`
3250
- });
3251
- }
3252
- if (!("action" in node)) {
3253
- diagnostics.push({
3254
- severity: "error",
3255
- code: "MISSING_ACTION",
3256
- message: "Missing required field: action"
3257
- });
3258
- } else if (typeof node.action !== "string" || node.action.length === 0) {
3259
- diagnostics.push({
3260
- severity: "error",
3261
- code: "INVALID_ACTION",
3262
- message: "action must be a non-empty string"
3263
- });
3264
- }
3265
- if (!("roles" in node) && kind !== "compound") {
3266
- diagnostics.push({
3267
- severity: "error",
3268
- code: "MISSING_ROLES",
3269
- message: "Missing required field: roles"
3270
- });
3271
- } else if ("roles" in node && (typeof node.roles !== "object" || node.roles === null || Array.isArray(node.roles))) {
3272
- diagnostics.push({
3273
- severity: "error",
3274
- code: "INVALID_ROLES",
3275
- message: "roles must be a plain object"
3276
- });
3277
- } else if ("roles" in node && node.roles) {
3278
- for (const [role, value] of Object.entries(node.roles)) {
3279
- if (typeof value !== "object" || value === null) {
3280
- diagnostics.push({
3281
- severity: "error",
3282
- code: "INVALID_ROLE_VALUE",
3283
- message: `Role "${role}" value must be an object`
3284
- });
3285
- continue;
3286
- }
3287
- const v = value;
3288
- if (!("type" in v) || !VALID_VALUE_TYPES2.has(String(v.type))) {
3289
- diagnostics.push({
3290
- severity: "error",
3291
- code: "INVALID_VALUE_TYPE",
3292
- message: `Role "${role}" has invalid type "${v.type}"`
3293
- });
3294
- }
3295
- if (v.type === "flag") {
3296
- const hasName = typeof v.name === "string";
3297
- const hasEnabled = typeof v.enabled === "boolean";
3298
- const hasValue = "value" in v;
3299
- if (!hasName && !hasValue) {
3300
- diagnostics.push({
3301
- severity: "error",
3302
- code: "MISSING_FLAG_NAME",
3303
- message: `Flag role "${role}" missing required field: name (or value)`
3304
- });
3305
- }
3306
- if (!hasEnabled && !hasValue) {
3307
- diagnostics.push({
3308
- severity: "error",
3309
- code: "MISSING_FLAG_ENABLED",
3310
- message: `Flag role "${role}" missing required field: enabled (or value)`
3311
- });
3312
- }
3313
- }
3314
- if (v.type === "expression" && typeof v.raw !== "string" && !("value" in v)) {
3315
- diagnostics.push({
3316
- severity: "error",
3317
- code: "MISSING_EXPRESSION_RAW",
3318
- message: `Expression role "${role}" missing required field: raw (or value)`
3319
- });
3320
- }
3321
- }
3322
- }
3323
- if ("trigger" in node && node.trigger) {
3324
- const trigger = node.trigger;
3325
- if (typeof trigger !== "object" || trigger === null) {
3326
- diagnostics.push({
3327
- severity: "error",
3328
- code: "INVALID_TRIGGER",
3329
- message: "trigger must be an object"
3330
- });
3331
- } else if (!trigger.event || typeof trigger.event !== "string") {
3332
- diagnostics.push({
3333
- severity: "error",
3334
- code: "INVALID_TRIGGER",
3335
- message: "trigger.event is required and must be a non-empty string"
3336
- });
3337
- }
3338
- }
3339
- if (kind === "event-handler" && !("trigger" in node)) {
3340
- if (!("body" in node) || !Array.isArray(node.body)) {
3341
- diagnostics.push({
3342
- severity: "error",
3343
- code: "MISSING_BODY",
3344
- message: "event-handler node requires a body array"
3345
- });
3346
- }
3347
- }
3348
- if (kind === "compound") {
3349
- if (!("statements" in node) || !Array.isArray(node.statements)) {
3350
- diagnostics.push({
3351
- severity: "error",
3352
- code: "MISSING_STATEMENTS",
3353
- message: "compound node requires a statements array"
3354
- });
3355
- }
3356
- if ("chainType" in node && !VALID_CHAIN_TYPES.has(String(node.chainType))) {
3357
- diagnostics.push({
3358
- severity: "error",
3359
- code: "INVALID_CHAIN_TYPE",
3360
- message: `Invalid chainType "${node.chainType}". Must be one of: then, and, async, sequential, pipe`
3361
- });
3362
- }
3363
- }
3364
- if ("diagnostics" in node) {
3365
- if (!Array.isArray(node.diagnostics)) {
3366
- diagnostics.push({
3367
- severity: "error",
3368
- code: "INVALID_DIAGNOSTICS",
3369
- message: "diagnostics must be an array"
3370
- });
3371
- } else {
3372
- for (let i = 0; i < node.diagnostics.length; i++) {
3373
- const d = node.diagnostics[i];
3374
- if (!d || typeof d !== "object") {
3375
- diagnostics.push({
3376
- severity: "error",
3377
- code: "INVALID_DIAGNOSTIC_ENTRY",
3378
- message: `diagnostics[${i}] must be an object`
3379
- });
3380
- continue;
3381
- }
3382
- if (!VALID_DIAGNOSTIC_LEVELS.has(String(d.level))) {
3383
- diagnostics.push({
3384
- severity: "error",
3385
- code: "INVALID_DIAGNOSTIC_LEVEL",
3386
- message: `diagnostics[${i}].level must be "error", "warning", or "info"`
3387
- });
3388
- }
3389
- if (typeof d.message !== "string") {
3390
- diagnostics.push({
3391
- severity: "error",
3392
- code: "MISSING_DIAGNOSTIC_MESSAGE",
3393
- message: `diagnostics[${i}] missing required field: message`
3394
- });
3395
- }
3396
- if ("code" in d && typeof d.code !== "string") {
3397
- diagnostics.push({
3398
- severity: "warning",
3399
- code: "INVALID_DIAGNOSTIC_CODE",
3400
- message: `diagnostics[${i}].code must be a string if present`
3401
- });
3402
- }
3403
- }
3404
- }
3405
- }
3406
- if ("annotations" in node) {
3407
- if (!Array.isArray(node.annotations)) {
3408
- diagnostics.push({
3409
- severity: "error",
3410
- code: "INVALID_ANNOTATIONS",
3411
- message: "annotations must be an array"
3412
- });
3413
- } else {
3414
- for (let i = 0; i < node.annotations.length; i++) {
3415
- const a = node.annotations[i];
3416
- if (!a || typeof a !== "object") {
3417
- diagnostics.push({
3418
- severity: "error",
3419
- code: "INVALID_ANNOTATION_ENTRY",
3420
- message: `annotations[${i}] must be an object`
3421
- });
3422
- continue;
3423
- }
3424
- if (typeof a.name !== "string" || a.name.length === 0) {
3425
- diagnostics.push({
3426
- severity: "error",
3427
- code: "MISSING_ANNOTATION_NAME",
3428
- message: `annotations[${i}] missing required field: name`
3429
- });
3430
- }
3431
- }
3432
- }
3433
- }
3434
- if ("asyncVariant" in node && !VALID_ASYNC_VARIANTS.has(String(node.asyncVariant))) {
3435
- diagnostics.push({
3436
- severity: "error",
3437
- code: "INVALID_ASYNC_VARIANT",
3438
- message: `Invalid asyncVariant "${node.asyncVariant}". Must be "all" or "race"`
3439
- });
3440
- }
3441
- if ("arms" in node) {
3442
- if (!Array.isArray(node.arms)) {
3443
- diagnostics.push({
3444
- severity: "error",
3445
- code: "INVALID_ARMS",
3446
- message: "arms must be an array"
3447
- });
3448
- } else {
3449
- for (let i = 0; i < node.arms.length; i++) {
3450
- const arm = node.arms[i];
3451
- if (!arm || typeof arm !== "object") {
3452
- diagnostics.push({
3453
- severity: "error",
3454
- code: "INVALID_ARM_ENTRY",
3455
- message: `arms[${i}] must be an object`
3456
- });
3457
- continue;
3458
- }
3459
- if (!arm.pattern || typeof arm.pattern !== "object") {
3460
- diagnostics.push({
3461
- severity: "error",
3462
- code: "MISSING_ARM_PATTERN",
3463
- message: `arms[${i}] missing required field: pattern`
3464
- });
3465
- }
3466
- if (!Array.isArray(arm.body)) {
3467
- diagnostics.push({
3468
- severity: "error",
3469
- code: "MISSING_ARM_BODY",
3470
- message: `arms[${i}] missing required field: body (array)`
3471
- });
3472
- }
3473
- }
3474
- }
3475
- }
3476
- return diagnostics;
3477
- }
2241
+ var import_intent5 = require("@lokascript/intent");
3478
2242
 
3479
2243
  // src/ir/from-interchange.ts
3480
2244
  function fromInterchangeNode(node) {
3481
2245
  if (!node || typeof node !== "object") {
3482
- return createCommandNode("unknown", {});
2246
+ return (0, import_intent.createCommandNode)("unknown", {});
3483
2247
  }
3484
2248
  switch (node.type) {
3485
2249
  case "event":
@@ -3496,7 +2260,7 @@ function fromInterchangeNode(node) {
3496
2260
  return convertWhile(node);
3497
2261
  // Expression nodes — wrap as `get` command with patient role
3498
2262
  default:
3499
- return createCommandNode("get", { patient: convertValue(node) });
2263
+ return (0, import_intent.createCommandNode)("get", { patient: convertValue(node) });
3500
2264
  }
3501
2265
  }
3502
2266
  function convertEvent(node) {
@@ -3504,7 +2268,7 @@ function convertEvent(node) {
3504
2268
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
3505
2269
  const body = bodyNodes.map(fromInterchangeNode);
3506
2270
  const roles = {
3507
- event: createLiteral(event)
2271
+ event: (0, import_intent.createLiteral)(event)
3508
2272
  };
3509
2273
  if (node.target && typeof node.target === "object") {
3510
2274
  roles.source = convertValue(node.target);
@@ -3513,12 +2277,12 @@ function convertEvent(node) {
3513
2277
  let eventModifiers;
3514
2278
  if (modifiers) {
3515
2279
  eventModifiers = bridgeEventModifiers(modifiers);
3516
- if (modifiers.prevent) roles.prevent = createLiteral(true);
3517
- if (modifiers.stop) roles.stop = createLiteral(true);
3518
- if (modifiers.passive) roles.passive = createLiteral(true);
3519
- if (modifiers.capture) roles.capture = createLiteral(true);
2280
+ if (modifiers.prevent) roles.prevent = (0, import_intent.createLiteral)(true);
2281
+ if (modifiers.stop) roles.stop = (0, import_intent.createLiteral)(true);
2282
+ if (modifiers.passive) roles.passive = (0, import_intent.createLiteral)(true);
2283
+ if (modifiers.capture) roles.capture = (0, import_intent.createLiteral)(true);
3520
2284
  }
3521
- return createEventHandlerNode("on", roles, body, void 0, eventModifiers);
2285
+ return (0, import_intent.createEventHandlerNode)("on", roles, body, void 0, eventModifiers);
3522
2286
  }
3523
2287
  function convertCommand(node) {
3524
2288
  const name = String(node.name ?? "unknown");
@@ -3537,10 +2301,10 @@ function convertCommand(node) {
3537
2301
  } else {
3538
2302
  roles = inferRoles(name, args, modifiers, target);
3539
2303
  }
3540
- return createCommandNode(name, roles);
2304
+ return (0, import_intent.createCommandNode)(name, roles);
3541
2305
  }
3542
2306
  function convertIf(node) {
3543
- const condition = node.condition && typeof node.condition === "object" ? convertValue(node.condition) : createExpression("true");
2307
+ const condition = node.condition && typeof node.condition === "object" ? convertValue(node.condition) : (0, import_intent.createExpression)("true");
3544
2308
  const thenBody = Array.isArray(node.thenBranch) ? node.thenBranch : [];
3545
2309
  const thenBranch = thenBody.map(fromInterchangeNode);
3546
2310
  let elseBranch;
@@ -3551,7 +2315,7 @@ function convertIf(node) {
3551
2315
  elseBranch = node.elseBranch.map(fromInterchangeNode);
3552
2316
  }
3553
2317
  const roles = { condition };
3554
- return createConditionalNode("if", roles, thenBranch, elseBranch);
2318
+ return (0, import_intent.createConditionalNode)("if", roles, thenBranch, elseBranch);
3555
2319
  }
3556
2320
  function chainElseIfs(branches, finalElse) {
3557
2321
  const [first, ...rest] = branches;
@@ -3563,7 +2327,7 @@ function chainElseIfs(branches, finalElse) {
3563
2327
  } else if (finalElse && finalElse.length > 0) {
3564
2328
  elseBranch = finalElse.map(fromInterchangeNode);
3565
2329
  }
3566
- return createConditionalNode("if", { condition }, thenBranch, elseBranch);
2330
+ return (0, import_intent.createConditionalNode)("if", { condition }, thenBranch, elseBranch);
3567
2331
  }
3568
2332
  function convertRepeat(node) {
3569
2333
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
@@ -3573,7 +2337,7 @@ function convertRepeat(node) {
3573
2337
  if (node.count !== void 0 && node.count !== null) {
3574
2338
  variant = "times";
3575
2339
  if (typeof node.count === "number") {
3576
- roles.quantity = createLiteral(node.count, "number");
2340
+ roles.quantity = (0, import_intent.createLiteral)(node.count, "number");
3577
2341
  } else if (typeof node.count === "object") {
3578
2342
  roles.quantity = convertValue(node.count);
3579
2343
  }
@@ -3582,11 +2346,11 @@ function convertRepeat(node) {
3582
2346
  roles.condition = convertValue(node.whileCondition);
3583
2347
  } else if (typeof node.untilEvent === "string") {
3584
2348
  variant = "until";
3585
- roles.condition = createLiteral(node.untilEvent);
2349
+ roles.condition = (0, import_intent.createLiteral)(node.untilEvent);
3586
2350
  } else {
3587
2351
  variant = "forever";
3588
2352
  }
3589
- return createLoopNode("repeat", roles, variant, body);
2353
+ return (0, import_intent.createLoopNode)("repeat", roles, variant, body);
3590
2354
  }
3591
2355
  function convertForEach(node) {
3592
2356
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
@@ -3597,7 +2361,7 @@ function convertForEach(node) {
3597
2361
  }
3598
2362
  const itemName = typeof node.itemName === "string" ? node.itemName : void 0;
3599
2363
  const indexName = typeof node.indexName === "string" ? node.indexName : void 0;
3600
- return createLoopNode("repeat", roles, "for", body, itemName, indexName);
2364
+ return (0, import_intent.createLoopNode)("repeat", roles, "for", body, itemName, indexName);
3601
2365
  }
3602
2366
  function convertWhile(node) {
3603
2367
  const bodyNodes = Array.isArray(node.body) ? node.body : [];
@@ -3606,21 +2370,21 @@ function convertWhile(node) {
3606
2370
  if (node.condition && typeof node.condition === "object") {
3607
2371
  roles.condition = convertValue(node.condition);
3608
2372
  }
3609
- return createLoopNode("repeat", roles, "while", body);
2373
+ return (0, import_intent.createLoopNode)("repeat", roles, "while", body);
3610
2374
  }
3611
2375
  function convertValue(node) {
3612
2376
  switch (node.type) {
3613
2377
  case "literal":
3614
2378
  return convertLiteral(node);
3615
2379
  case "selector":
3616
- return createSelector(String(node.value ?? ""), inferSelectorKind2(String(node.value ?? "")));
2380
+ return (0, import_intent.createSelector)(String(node.value ?? ""), inferSelectorKind(String(node.value ?? "")));
3617
2381
  case "identifier":
3618
2382
  return convertIdentifier(node);
3619
2383
  case "variable":
3620
2384
  return convertVariable(node);
3621
2385
  case "possessive":
3622
- return createPropertyPath(
3623
- node.object && typeof node.object === "object" ? convertValue(node.object) : createReference("me"),
2386
+ return (0, import_intent.createPropertyPath)(
2387
+ node.object && typeof node.object === "object" ? convertValue(node.object) : (0, import_intent.createReference)("me"),
3624
2388
  String(node.property ?? "")
3625
2389
  );
3626
2390
  // Complex expressions → collapse to raw string
@@ -3629,35 +2393,35 @@ function convertValue(node) {
3629
2393
  case "member":
3630
2394
  case "call":
3631
2395
  case "positional":
3632
- return createExpression(renderExpr(node));
2396
+ return (0, import_intent.createExpression)(renderExpr(node));
3633
2397
  default:
3634
- if ("value" in node) return createLiteral(String(node.value ?? ""));
3635
- return createExpression(renderExpr(node));
2398
+ if ("value" in node) return (0, import_intent.createLiteral)(String(node.value ?? ""));
2399
+ return (0, import_intent.createExpression)(renderExpr(node));
3636
2400
  }
3637
2401
  }
3638
2402
  function convertLiteral(node) {
3639
2403
  const value = node.value;
3640
- if (value === null || value === void 0) return createLiteral("null");
2404
+ if (value === null || value === void 0) return (0, import_intent.createLiteral)("null");
3641
2405
  const dataType = typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : void 0;
3642
- return createLiteral(value, dataType);
2406
+ return (0, import_intent.createLiteral)(value, dataType);
3643
2407
  }
3644
2408
  function convertIdentifier(node) {
3645
2409
  const value = String(node.value ?? "");
3646
- if (DEFAULT_REFERENCES.has(value)) {
3647
- return createReference(value);
2410
+ if (import_intent2.DEFAULT_REFERENCES.has(value)) {
2411
+ return (0, import_intent.createReference)(value);
3648
2412
  }
3649
- return createLiteral(value);
2413
+ return (0, import_intent.createLiteral)(value);
3650
2414
  }
3651
2415
  function convertVariable(node) {
3652
2416
  const name = String(node.name ?? "");
3653
2417
  const scope = String(node.scope ?? "local");
3654
2418
  switch (scope) {
3655
2419
  case "element":
3656
- return createExpression(`:${name}`);
2420
+ return (0, import_intent.createExpression)(`:${name}`);
3657
2421
  case "global":
3658
- return createExpression(`$${name}`);
2422
+ return (0, import_intent.createExpression)(`$${name}`);
3659
2423
  default:
3660
- return createExpression(name);
2424
+ return (0, import_intent.createExpression)(name);
3661
2425
  }
3662
2426
  }
3663
2427
  function renderExpr(node) {
@@ -3715,6 +2479,33 @@ function renderExpr(node) {
3715
2479
  return "";
3716
2480
  }
3717
2481
  }
2482
+ var SCROLL_MARKERS = /* @__PURE__ */ new Set([
2483
+ "to",
2484
+ "of",
2485
+ "the",
2486
+ "top",
2487
+ "bottom",
2488
+ "middle",
2489
+ "center",
2490
+ "nearest",
2491
+ "left",
2492
+ "right",
2493
+ "smoothly",
2494
+ "instantly"
2495
+ ]);
2496
+ var URL_MARKERS = /* @__PURE__ */ new Set(["url"]);
2497
+ var PARTIALS_IN_MARKERS = /* @__PURE__ */ new Set(["partials", "in"]);
2498
+ function firstNonMarkerArg(args, markers) {
2499
+ for (const a of args) {
2500
+ if (a.type === "identifier") {
2501
+ const ident = a;
2502
+ const word = typeof ident.name === "string" ? ident.name : ident.value;
2503
+ if (typeof word === "string" && markers.has(word)) continue;
2504
+ }
2505
+ return a;
2506
+ }
2507
+ return void 0;
2508
+ }
3718
2509
  function inferRoles(name, args, modifiers, target) {
3719
2510
  const roles = {};
3720
2511
  switch (name) {
@@ -3735,7 +2526,7 @@ function inferRoles(name, args, modifiers, target) {
3735
2526
  const val = modifiers[key];
3736
2527
  if (val && typeof val === "object" && "type" in val) {
3737
2528
  roles.destination = convertValue(val);
3738
- roles.method = createLiteral(key);
2529
+ roles.method = (0, import_intent.createLiteral)(key);
3739
2530
  break;
3740
2531
  }
3741
2532
  }
@@ -3762,7 +2553,7 @@ function inferRoles(name, args, modifiers, target) {
3762
2553
  if (asVal && typeof asVal === "object" && "type" in asVal) {
3763
2554
  roles.responseType = convertValue(asVal);
3764
2555
  } else if (typeof asVal === "string") {
3765
- roles.responseType = createLiteral(asVal);
2556
+ roles.responseType = (0, import_intent.createLiteral)(asVal);
3766
2557
  }
3767
2558
  break;
3768
2559
  }
@@ -3794,6 +2585,25 @@ function inferRoles(name, args, modifiers, target) {
3794
2585
  if (args[0]) roles.patient = convertValue(args[0]);
3795
2586
  break;
3796
2587
  }
2588
+ // scroll [to] [position] target [smoothly|instantly] → destination=target
2589
+ case "scroll": {
2590
+ const t = firstNonMarkerArg(args, SCROLL_MARKERS);
2591
+ if (t) roles.destination = convertValue(t);
2592
+ break;
2593
+ }
2594
+ // push|replace url <X> → patient=X
2595
+ case "push":
2596
+ case "replace": {
2597
+ const t = firstNonMarkerArg(args, URL_MARKERS);
2598
+ if (t) roles.patient = convertValue(t);
2599
+ break;
2600
+ }
2601
+ // process partials in <X> → patient=X
2602
+ case "process": {
2603
+ const t = firstNonMarkerArg(args, PARTIALS_IN_MARKERS);
2604
+ if (t) roles.patient = convertValue(t);
2605
+ break;
2606
+ }
3797
2607
  default: {
3798
2608
  if (args[0]) roles.patient = convertValue(args[0]);
3799
2609
  if (target) roles.destination = convertValue(target);
@@ -3802,7 +2612,7 @@ function inferRoles(name, args, modifiers, target) {
3802
2612
  }
3803
2613
  return roles;
3804
2614
  }
3805
- function inferSelectorKind2(value) {
2615
+ function inferSelectorKind(value) {
3806
2616
  if (!value) return void 0;
3807
2617
  if (value.startsWith("#")) return "id";
3808
2618
  if (value.startsWith(".")) return "class";
@@ -3812,10 +2622,10 @@ function inferSelectorKind2(value) {
3812
2622
  return void 0;
3813
2623
  }
3814
2624
  function inferValueFromString(value) {
3815
- if (DEFAULT_REFERENCES.has(value)) return createReference(value);
3816
- const kind = inferSelectorKind2(value);
3817
- if (kind) return createSelector(value, kind);
3818
- return createLiteral(value);
2625
+ if (import_intent2.DEFAULT_REFERENCES.has(value)) return (0, import_intent.createReference)(value);
2626
+ const kind = inferSelectorKind(value);
2627
+ if (kind) return (0, import_intent.createSelector)(value, kind);
2628
+ return (0, import_intent.createLiteral)(value);
3819
2629
  }
3820
2630
  function bridgeEventModifiers(mods) {
3821
2631
  const once = mods.once === true ? true : void 0;
@@ -3997,8 +2807,8 @@ var MultilingualDSLImpl = class {
3997
2807
  return result.node;
3998
2808
  }
3999
2809
  parseWithConfidence(input, language) {
4000
- if (isExplicitSyntax(input)) {
4001
- const node = parseExplicit(input, { schemaLookup: this.schemaLookup });
2810
+ if ((0, import_intent3.isExplicitSyntax)(input)) {
2811
+ const node = (0, import_intent3.parseExplicit)(input, { schemaLookup: this.schemaLookup });
4002
2812
  if (!this.schemaLookup.getSchema(node.action)) {
4003
2813
  throw new Error(`No schema for action "${node.action}" in this DSL`);
4004
2814
  }
@@ -4047,7 +2857,7 @@ var MultilingualDSLImpl = class {
4047
2857
  }
4048
2858
  }
4049
2859
  translate(input, fromLanguage, toLanguage) {
4050
- if (isExplicitSyntax(input)) return input;
2860
+ if ((0, import_intent3.isExplicitSyntax)(input)) return input;
4051
2861
  return this.transformer.transform(input, fromLanguage, toLanguage);
4052
2862
  }
4053
2863
  compile(input, language) {
@@ -4153,8 +2963,8 @@ function generateExamples(schema, count = 2) {
4153
2963
  for (const [roleName, sample] of roles) {
4154
2964
  nodeRoles.set(roleName, toSemanticValue(sample));
4155
2965
  }
4156
- const node = createCommandNode(schema.action, nodeRoles);
4157
- const explicit = renderExplicit(node);
2966
+ const node = (0, import_intent.createCommandNode)(schema.action, nodeRoles);
2967
+ const explicit = (0, import_intent4.renderExplicit)(node);
4158
2968
  const jsonRoles = {};
4159
2969
  for (const [roleName, sample] of roles) {
4160
2970
  jsonRoles[roleName] = sample;
@@ -4551,8 +3361,8 @@ function buildTrainingPair(schema, roles, language, domain, id) {
4551
3361
  for (const [name, sample] of sampledRoles) {
4552
3362
  nodeRoles.set(name, toSemanticValue2(sample));
4553
3363
  }
4554
- const node = createCommandNode(schema.action, nodeRoles);
4555
- const explicit = renderExplicit(node);
3364
+ const node = (0, import_intent.createCommandNode)(schema.action, nodeRoles);
3365
+ const explicit = (0, import_intent4.renderExplicit)(node);
4556
3366
  const jsonRoles = {};
4557
3367
  for (const [name, sample] of sampledRoles) {
4558
3368
  jsonRoles[name] = sample;
@@ -4803,8 +3613,8 @@ function generateCorrectedExample(schema) {
4803
3613
  roles.set(role.role, toSemanticValue3(sample));
4804
3614
  jsonRoles[role.role] = sample;
4805
3615
  }
4806
- const node = createCommandNode(schema.action, roles);
4807
- const explicit = renderExplicit(node);
3616
+ const node = (0, import_intent.createCommandNode)(schema.action, roles);
3617
+ const explicit = (0, import_intent4.renderExplicit)(node);
4808
3618
  const json = { action: schema.action, roles: jsonRoles };
4809
3619
  return { explicit, json };
4810
3620
  }
@@ -4973,7 +3783,7 @@ var DomainRegistry = class {
4973
3783
  let action;
4974
3784
  try {
4975
3785
  if (inputFormat === "explicit") {
4976
- const node = parseExplicit(input, { schemaLookup });
3786
+ const node = (0, import_intent3.parseExplicit)(input, { schemaLookup });
4977
3787
  action = node.action;
4978
3788
  }
4979
3789
  } catch {
@@ -5631,25 +4441,7 @@ async function registryToAOTBackends(registry) {
5631
4441
  }
5632
4442
 
5633
4443
  // src/schema/command-schema.ts
5634
- function defineCommand(schema) {
5635
- return {
5636
- description: schema.description || `${schema.action} command`,
5637
- category: schema.category || "general",
5638
- primaryRole: schema.primaryRole || schema.roles[0]?.role || "patient",
5639
- ...schema,
5640
- action: schema.action,
5641
- roles: schema.roles
5642
- };
5643
- }
5644
- function defineRole(role) {
5645
- return {
5646
- description: role.description || `${role.role} role`,
5647
- ...role,
5648
- role: role.role,
5649
- required: role.required,
5650
- expectedTypes: role.expectedTypes
5651
- };
5652
- }
4444
+ var import_intent6 = require("@lokascript/intent");
5653
4445
 
5654
4446
  // src/generation/renderer.ts
5655
4447
  function lookupKeyword(keywords, action, language) {
@@ -5713,7 +4505,7 @@ function createSchemaRenderer(schemas, profiles) {
5713
4505
  const isSOV = sovLanguages.has(language);
5714
4506
  const roleParts = [];
5715
4507
  for (const role of schema.roles) {
5716
- const value = extractRoleValue(node, role.role);
4508
+ const value = (0, import_intent.extractRoleValue)(node, role.role);
5717
4509
  if (!value && !role.required) continue;
5718
4510
  const markerText = role.markerOverride?.[language] ?? markers[role.role]?.[language] ?? void 0;
5719
4511
  roleParts.push({
@@ -5742,71 +4534,7 @@ function createSchemaRenderer(schemas, profiles) {
5742
4534
  }
5743
4535
 
5744
4536
  // src/generation/diagnostics.ts
5745
- function createDiagnosticCollector() {
5746
- const diagnostics = [];
5747
- function addWithSeverity(severity, message, options) {
5748
- const diag = {
5749
- message,
5750
- severity,
5751
- ...options?.code != null && { code: options.code },
5752
- ...options?.line != null && { line: options.line },
5753
- ...options?.column != null && { column: options.column },
5754
- ...options?.source != null && { source: options.source },
5755
- ...options?.suggestions != null && options.suggestions.length > 0 && { suggestions: options.suggestions }
5756
- };
5757
- diagnostics.push(diag);
5758
- }
5759
- return {
5760
- error(message, options) {
5761
- addWithSeverity("error", message, options);
5762
- },
5763
- warning(message, options) {
5764
- addWithSeverity("warning", message, options);
5765
- },
5766
- info(message, options) {
5767
- addWithSeverity("info", message, options);
5768
- },
5769
- add(diagnostic) {
5770
- diagnostics.push(diagnostic);
5771
- },
5772
- hasErrors() {
5773
- return diagnostics.some((d) => d.severity === "error");
5774
- },
5775
- getDiagnostics() {
5776
- return diagnostics;
5777
- },
5778
- toResult() {
5779
- let errors = 0;
5780
- let warnings = 0;
5781
- let infos = 0;
5782
- for (const d of diagnostics) {
5783
- if (d.severity === "error") errors++;
5784
- else if (d.severity === "warning") warnings++;
5785
- else infos++;
5786
- }
5787
- return {
5788
- ok: errors === 0,
5789
- diagnostics,
5790
- summary: { errors, warnings, infos }
5791
- };
5792
- }
5793
- };
5794
- }
5795
- function fromError(error, options) {
5796
- const message = error instanceof Error ? error.message : String(error);
5797
- return {
5798
- message,
5799
- severity: "error",
5800
- ...options?.code != null && { code: options.code },
5801
- ...options?.line != null && { line: options.line },
5802
- ...options?.column != null && { column: options.column },
5803
- ...options?.source != null && { source: options.source },
5804
- ...options?.suggestions != null && options.suggestions.length > 0 && { suggestions: options.suggestions }
5805
- };
5806
- }
5807
- function filterBySeverity(diagnostics, severity) {
5808
- return diagnostics.filter((d) => d.severity === severity);
5809
- }
4537
+ var import_intent7 = require("@lokascript/intent");
5810
4538
 
5811
4539
  // src/core/tokenization/token-utils.ts
5812
4540
  var TokenStreamImpl = class {
@@ -7085,7 +5813,7 @@ function buildDisambiguation(input, candidates) {
7085
5813
  const disambiguationCandidates = sortedCandidates.map((c, i) => ({
7086
5814
  action: c.action,
7087
5815
  confidence: c.confidence,
7088
- explicit: renderExplicit(c.node),
5816
+ explicit: (0, import_intent4.renderExplicit)(c.node),
7089
5817
  description: c.description || `${c.action} (option ${String.fromCharCode(97 + i)})`
7090
5818
  }));
7091
5819
  const optionLines = disambiguationCandidates.map(
@@ -7462,6 +6190,7 @@ function accumulateIndented(statements, config) {
7462
6190
  IdentifierExtractor,
7463
6191
  InMemoryDictionary,
7464
6192
  InMemoryProfileProvider,
6193
+ LatinExtendedIdentifierExtractor,
7465
6194
  NullDictionary,
7466
6195
  NullProfileProvider,
7467
6196
  NumberExtractor,
@@ -7526,6 +6255,8 @@ function accumulateIndented(statements, config) {
7526
6255
  getAllPossessiveKeywords,
7527
6256
  getDefaultExtractors,
7528
6257
  getPossessiveReference,
6258
+ getRoleSpec,
6259
+ getRoleValue,
7529
6260
  insertMarkers,
7530
6261
  isAsciiIdentifierChar,
7531
6262
  isAsciiLetter,