@aexol/spectral 0.9.220 → 0.9.222

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 (153) hide show
  1. package/dist/agent/index.d.ts +7 -3
  2. package/dist/agent/index.d.ts.map +1 -1
  3. package/dist/agent/index.js +35 -8
  4. package/dist/extensions/aexol-backend-client.d.ts +85 -0
  5. package/dist/extensions/aexol-backend-client.d.ts.map +1 -0
  6. package/dist/extensions/aexol-backend-client.js +159 -0
  7. package/dist/extensions/aexol-mcp.d.ts +10 -6
  8. package/dist/extensions/aexol-mcp.d.ts.map +1 -1
  9. package/dist/extensions/aexol-mcp.js +21 -106
  10. package/dist/extensions/logic-trace-backend-draft.d.ts +68 -0
  11. package/dist/extensions/logic-trace-backend-draft.d.ts.map +1 -0
  12. package/dist/extensions/logic-trace-backend-draft.js +171 -0
  13. package/dist/extensions/logic-trace-validate.d.ts +33 -0
  14. package/dist/extensions/logic-trace-validate.d.ts.map +1 -0
  15. package/dist/extensions/logic-trace-validate.js +73 -0
  16. package/dist/extensions/logic-trace.d.ts +213 -0
  17. package/dist/extensions/logic-trace.d.ts.map +1 -0
  18. package/dist/extensions/logic-trace.js +1098 -0
  19. package/dist/generated/parser/lexer.d.ts +148 -0
  20. package/dist/generated/parser/lexer.d.ts.map +1 -0
  21. package/dist/generated/parser/lexer.js +877 -0
  22. package/dist/generated/parser/mod.d.ts +26 -0
  23. package/dist/generated/parser/mod.d.ts.map +1 -0
  24. package/dist/generated/parser/mod.js +30 -0
  25. package/dist/generated/parser/parser.d.ts +161 -0
  26. package/dist/generated/parser/parser.d.ts.map +1 -0
  27. package/dist/generated/parser/parser.js +754 -0
  28. package/dist/generated/parser/tokenizer.d.ts +107 -0
  29. package/dist/generated/parser/tokenizer.d.ts.map +1 -0
  30. package/dist/generated/parser/tokenizer.js +202 -0
  31. package/dist/generated/parser/validator.d.ts +45 -0
  32. package/dist/generated/parser/validator.d.ts.map +1 -0
  33. package/dist/generated/parser/validator.js +202 -0
  34. package/dist/generated/zeus/const.d.ts.map +1 -1
  35. package/dist/generated/zeus/const.js +4 -170
  36. package/dist/generated/zeus/index.d.ts +8 -873
  37. package/dist/generated/zeus/index.d.ts.map +1 -1
  38. package/dist/generated/zeus/index.js +0 -7
  39. package/dist/mcp/ui-stream-types.d.ts +2 -2
  40. package/dist/memory/tools/share-project-observation.js +1 -1
  41. package/dist/memory/tools/write-project-observation.d.ts.map +1 -1
  42. package/dist/memory/tools/write-project-observation.js +4 -3
  43. package/dist/sdk/agent-core/harness/types.d.ts +0 -1
  44. package/dist/sdk/agent-core/harness/types.d.ts.map +1 -1
  45. package/dist/sdk/agent-core/index.d.ts +0 -8
  46. package/dist/sdk/agent-core/index.d.ts.map +1 -1
  47. package/dist/sdk/agent-core/index.js +0 -9
  48. package/dist/sdk/coding-agent/core/extensions/index.d.ts +1 -1
  49. package/dist/sdk/coding-agent/core/extensions/index.d.ts.map +1 -1
  50. package/dist/sdk/coding-agent/core/extensions/native-extensions.js +2 -2
  51. package/dist/sdk/coding-agent/core/extensions/types.d.ts +20 -1
  52. package/dist/sdk/coding-agent/core/extensions/types.d.ts.map +1 -1
  53. package/dist/sdk/coding-agent/core/tools/tool-definition-wrapper.d.ts +9 -4
  54. package/dist/sdk/coding-agent/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  55. package/dist/sdk/coding-agent/core/tools/tool-definition-wrapper.js +15 -2
  56. package/dist/sdk/coding-agent/index.d.ts +1 -1
  57. package/dist/sdk/coding-agent/index.d.ts.map +1 -1
  58. package/dist/server/agent-bridge/headless-ui.d.ts +20 -0
  59. package/dist/server/agent-bridge/headless-ui.d.ts.map +1 -0
  60. package/dist/server/agent-bridge/headless-ui.js +85 -0
  61. package/dist/server/agent-bridge/pricing.d.ts +37 -0
  62. package/dist/server/agent-bridge/pricing.d.ts.map +1 -0
  63. package/dist/server/agent-bridge/pricing.js +202 -0
  64. package/dist/server/agent-bridge/rehydrate.d.ts +35 -0
  65. package/dist/server/agent-bridge/rehydrate.d.ts.map +1 -0
  66. package/dist/server/agent-bridge/rehydrate.js +122 -0
  67. package/dist/server/agent-bridge/synthetic-model.d.ts +27 -0
  68. package/dist/server/agent-bridge/synthetic-model.d.ts.map +1 -0
  69. package/dist/server/agent-bridge/synthetic-model.js +92 -0
  70. package/dist/server/agent-bridge.d.ts +11 -1
  71. package/dist/server/agent-bridge.d.ts.map +1 -1
  72. package/dist/server/agent-bridge.js +42 -481
  73. package/dist/server/session-stream/compaction-events.d.ts +13 -0
  74. package/dist/server/session-stream/compaction-events.d.ts.map +1 -0
  75. package/dist/server/session-stream/compaction-events.js +32 -0
  76. package/dist/server/session-stream/history-prune.d.ts +35 -0
  77. package/dist/server/session-stream/history-prune.d.ts.map +1 -0
  78. package/dist/server/session-stream/history-prune.js +182 -0
  79. package/dist/server/session-stream/memory.d.ts +48 -0
  80. package/dist/server/session-stream/memory.d.ts.map +1 -0
  81. package/dist/server/session-stream/memory.js +136 -0
  82. package/dist/server/session-stream/replay-tail.d.ts +4 -0
  83. package/dist/server/session-stream/replay-tail.d.ts.map +1 -0
  84. package/dist/server/session-stream/replay-tail.js +39 -0
  85. package/dist/server/session-stream/turn-events.d.ts +33 -0
  86. package/dist/server/session-stream/turn-events.d.ts.map +1 -0
  87. package/dist/server/session-stream/turn-events.js +65 -0
  88. package/dist/server/session-stream/turn-silence.d.ts +8 -0
  89. package/dist/server/session-stream/turn-silence.d.ts.map +1 -0
  90. package/dist/server/session-stream/turn-silence.js +72 -0
  91. package/dist/server/session-stream.d.ts +137 -36
  92. package/dist/server/session-stream.d.ts.map +1 -1
  93. package/dist/server/session-stream.js +18 -509
  94. package/dist/server/storage/observation-ranking.d.ts +14 -0
  95. package/dist/server/storage/observation-ranking.d.ts.map +1 -0
  96. package/dist/server/storage/observation-ranking.js +37 -0
  97. package/dist/server/storage/preflight.d.ts +20 -0
  98. package/dist/server/storage/preflight.d.ts.map +1 -0
  99. package/dist/server/storage/preflight.js +22 -0
  100. package/dist/server/storage/project-binding.d.ts +5 -0
  101. package/dist/server/storage/project-binding.d.ts.map +1 -0
  102. package/dist/server/storage/project-binding.js +32 -0
  103. package/dist/server/storage/rows.d.ts +104 -0
  104. package/dist/server/storage/rows.d.ts.map +1 -0
  105. package/dist/server/storage/rows.js +2 -0
  106. package/dist/server/storage/schema.d.ts +20 -0
  107. package/dist/server/storage/schema.d.ts.map +1 -0
  108. package/dist/server/storage/schema.js +134 -0
  109. package/dist/server/storage/types.d.ts +66 -0
  110. package/dist/server/storage/types.d.ts.map +1 -0
  111. package/dist/server/storage/types.js +1 -0
  112. package/dist/server/storage.d.ts +7 -94
  113. package/dist/server/storage.d.ts.map +1 -1
  114. package/dist/server/storage.js +6 -224
  115. package/dist/server/wire.d.ts +6 -0
  116. package/dist/server/wire.d.ts.map +1 -1
  117. package/package.json +2 -1
  118. package/dist/sdk/agent-core/harness/agent-harness.d.ts +0 -92
  119. package/dist/sdk/agent-core/harness/agent-harness.d.ts.map +0 -1
  120. package/dist/sdk/agent-core/harness/agent-harness.js +0 -899
  121. package/dist/sdk/agent-core/harness/env/nodejs.d.ts +0 -51
  122. package/dist/sdk/agent-core/harness/env/nodejs.d.ts.map +0 -1
  123. package/dist/sdk/agent-core/harness/env/nodejs.js +0 -485
  124. package/dist/sdk/agent-core/harness/prompt-templates.d.ts +0 -48
  125. package/dist/sdk/agent-core/harness/prompt-templates.d.ts.map +0 -1
  126. package/dist/sdk/agent-core/harness/prompt-templates.js +0 -229
  127. package/dist/sdk/agent-core/harness/session/jsonl-repo.d.ts +0 -26
  128. package/dist/sdk/agent-core/harness/session/jsonl-repo.d.ts.map +0 -1
  129. package/dist/sdk/agent-core/harness/session/jsonl-repo.js +0 -100
  130. package/dist/sdk/agent-core/harness/session/jsonl-storage.d.ts +0 -33
  131. package/dist/sdk/agent-core/harness/session/jsonl-storage.d.ts.map +0 -1
  132. package/dist/sdk/agent-core/harness/session/jsonl-storage.js +0 -230
  133. package/dist/sdk/agent-core/harness/session/memory-repo.d.ts +0 -18
  134. package/dist/sdk/agent-core/harness/session/memory-repo.d.ts.map +0 -1
  135. package/dist/sdk/agent-core/harness/session/memory-repo.js +0 -41
  136. package/dist/sdk/agent-core/harness/session/memory-storage.d.ts +0 -25
  137. package/dist/sdk/agent-core/harness/session/memory-storage.d.ts.map +0 -1
  138. package/dist/sdk/agent-core/harness/session/memory-storage.js +0 -113
  139. package/dist/sdk/agent-core/harness/session/repo-utils.d.ts +0 -11
  140. package/dist/sdk/agent-core/harness/session/repo-utils.d.ts.map +0 -1
  141. package/dist/sdk/agent-core/harness/session/repo-utils.js +0 -38
  142. package/dist/sdk/agent-core/harness/skills.d.ts +0 -44
  143. package/dist/sdk/agent-core/harness/skills.d.ts.map +0 -1
  144. package/dist/sdk/agent-core/harness/skills.js +0 -310
  145. package/dist/sdk/agent-core/harness/utils/shell-output.d.ts +0 -14
  146. package/dist/sdk/agent-core/harness/utils/shell-output.d.ts.map +0 -1
  147. package/dist/sdk/agent-core/harness/utils/shell-output.js +0 -125
  148. package/dist/sdk/agent-core/node.d.ts +0 -3
  149. package/dist/sdk/agent-core/node.d.ts.map +0 -1
  150. package/dist/sdk/agent-core/node.js +0 -2
  151. package/dist/sdk/agent-core/proxy.d.ts +0 -69
  152. package/dist/sdk/agent-core/proxy.d.ts.map +0 -1
  153. package/dist/sdk/agent-core/proxy.js +0 -297
@@ -0,0 +1,754 @@
1
+ // GENERATED by cli-node/scripts/vendor-parser.mjs — do not edit; regenerate with `node scripts/vendor-parser.mjs`; source: packages/parser/
2
+ /**
3
+ * Aexol Language Parser
4
+ *
5
+ * Builds an Abstract Syntax Tree (AST) from a token stream.
6
+ * Supports the full Aexol language grammar for capability definitions,
7
+ * workflows, and agent structures.
8
+ */
9
+ import { Tokenizer } from "./tokenizer.js";
10
+ import { TokenType } from "./lexer.js";
11
+ export class Parser {
12
+ tokenizer;
13
+ currentToken;
14
+ constructor(source) {
15
+ this.tokenizer = new Tokenizer(source);
16
+ this.currentToken = this.tokenizer.current();
17
+ }
18
+ advance() {
19
+ const token = this.currentToken;
20
+ this.tokenizer.advance();
21
+ this.currentToken = this.tokenizer.current();
22
+ return token;
23
+ }
24
+ check(type) {
25
+ return this.currentToken.type === type;
26
+ }
27
+ checkAny(...types) {
28
+ return types.includes(this.currentToken.type);
29
+ }
30
+ consume(type, message) {
31
+ if (!this.check(type)) {
32
+ throw new SyntaxError(message ||
33
+ `Expected ${type} but got ${this.currentToken.type} at line ${this.currentToken.location.line}:${this.currentToken.location.column}`);
34
+ }
35
+ return this.advance();
36
+ }
37
+ match(...types) {
38
+ if (this.checkAny(...types)) {
39
+ return this.advance();
40
+ }
41
+ return null;
42
+ }
43
+ // Keywords that can be used as identifiers in certain contexts (like field names, enum values)
44
+ consumeIdentifierOrKeyword(message) {
45
+ // Allow any token that has a string value - this includes IDENTIFIER and most keywords
46
+ if (this.currentToken.value && typeof this.currentToken.value === "string") {
47
+ return this.advance();
48
+ }
49
+ throw new SyntaxError(message ||
50
+ `Expected identifier but got ${this.currentToken.type} at line ${this.currentToken.location.line}:${this.currentToken.location.column}`);
51
+ }
52
+ /**
53
+ * Check if the current token is a keyword being used as an identifier in a
54
+ * capability context. Many common English words (import, from, context, etc.)
55
+ * are reserved keywords in the lexer but should be accepted as-is when they
56
+ * appear as unquoted capability names (e.g. "can import catalog").
57
+ */
58
+ isKeywordUsedAsIdentifier() {
59
+ // Structural / top-level keywords that should NOT be treated as identifiers
60
+ const STRUCTURAL_KEYWORDS = new Set([
61
+ TokenType.VISITOR,
62
+ TokenType.TYPE,
63
+ TokenType.ENUM,
64
+ TokenType.INTERFACE,
65
+ TokenType.AGENT,
66
+ TokenType.WORKFLOW,
67
+ TokenType.ROLE,
68
+ TokenType.PERMISSION,
69
+ TokenType.STATE,
70
+ TokenType.EXECUTION_PLAN,
71
+ TokenType.EXECUTION_GRAPH,
72
+ // Structural punctuation / control flow that signal block end
73
+ // are not TokenType keywords, so no need to list them here.
74
+ ]);
75
+ const t = this.currentToken.type;
76
+ // Must be a keyword-type token (not IDENTIFIER/STRING/NUMBER/punctuation)
77
+ // and not a structural top-level keyword.
78
+ return (t !== TokenType.IDENTIFIER &&
79
+ t !== TokenType.STRING &&
80
+ t !== TokenType.NUMBER &&
81
+ t !== TokenType.EOF &&
82
+ t !== TokenType.LBRACE &&
83
+ t !== TokenType.RBRACE &&
84
+ t !== TokenType.NEWLINE &&
85
+ t !== TokenType.INDENT &&
86
+ t !== TokenType.DEDENT &&
87
+ t !== TokenType.COMMA &&
88
+ !STRUCTURAL_KEYWORDS.has(t) &&
89
+ // Ensure the token has an actual word value
90
+ this.currentToken.value.length > 0);
91
+ }
92
+ skipNewlines() {
93
+ while (this.checkAny(TokenType.NEWLINE, TokenType.INDENT, TokenType.DEDENT, TokenType.COMMENT)) {
94
+ this.advance();
95
+ }
96
+ }
97
+ isAtEnd() {
98
+ return this.check(TokenType.EOF);
99
+ }
100
+ /**
101
+ * Check for and consume a description (PROMPT token with triple single-quotes) if present
102
+ */
103
+ parseDescriptionIfPresent() {
104
+ if (this.check(TokenType.PROMPT)) {
105
+ const description = this.advance().value;
106
+ this.skipNewlines();
107
+ return description;
108
+ }
109
+ return undefined;
110
+ }
111
+ throwUnexpectedTopLevelToken(description) {
112
+ const token = this.currentToken;
113
+ const tokenValue = token.value ? ` '${token.value}'` : "";
114
+ const descriptionHint = description ? " after a description block" : "";
115
+ throw new SyntaxError(`Unexpected top-level token ${token.type}${tokenValue}${descriptionHint} at line ${token.location.line}:${token.location.column}. ` +
116
+ "Expected one of: visitor, role, workflow, agent, type, enum, interface.");
117
+ }
118
+ /**
119
+ * Parse the entire program
120
+ */
121
+ parse() {
122
+ const body = [];
123
+ const startLocation = this.currentToken.location;
124
+ this.skipNewlines();
125
+ while (!this.isAtEnd()) {
126
+ // Check for description before any definition
127
+ const description = this.parseDescriptionIfPresent();
128
+ if (this.check(TokenType.VISITOR)) {
129
+ body.push(this.parseVisitor(description));
130
+ }
131
+ else if (this.check(TokenType.ROLE)) {
132
+ body.push(this.parseRole(description));
133
+ }
134
+ else if (this.check(TokenType.WORKFLOW)) {
135
+ body.push(this.parseWorkflow(description));
136
+ }
137
+ else if (this.check(TokenType.AGENT)) {
138
+ body.push(this.parseAgent(description));
139
+ }
140
+ else if (this.check(TokenType.TYPE) || this.check(TokenType.ENUM) ||
141
+ this.check(TokenType.INTERFACE)) {
142
+ body.push(this.parseTypeDefinition(description));
143
+ }
144
+ else {
145
+ this.throwUnexpectedTopLevelToken(description);
146
+ }
147
+ this.skipNewlines();
148
+ }
149
+ return {
150
+ type: "Program",
151
+ body,
152
+ location: {
153
+ start: startLocation.offset,
154
+ end: this.currentToken.location.offset,
155
+ line: startLocation.line,
156
+ column: startLocation.column,
157
+ },
158
+ };
159
+ }
160
+ parseVisitor(description) {
161
+ const startToken = this.consume(TokenType.VISITOR);
162
+ let name;
163
+ if (this.check(TokenType.IDENTIFIER)) {
164
+ name = this.advance().value;
165
+ }
166
+ this.skipNewlines();
167
+ this.consume(TokenType.LBRACE, "Expected '{' after visitor");
168
+ this.skipNewlines();
169
+ const capabilities = [];
170
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
171
+ capabilities.push(this.parseCapability());
172
+ this.skipNewlines();
173
+ }
174
+ this.consume(TokenType.RBRACE, "Expected '}' after visitor body");
175
+ return {
176
+ type: "VisitorDefinition",
177
+ name,
178
+ description,
179
+ capabilities,
180
+ location: {
181
+ start: startToken.location.offset,
182
+ end: this.currentToken.location.offset,
183
+ line: startToken.location.line,
184
+ column: startToken.location.column,
185
+ },
186
+ };
187
+ }
188
+ parseCapability() {
189
+ // Check for description before capability
190
+ const description = this.parseDescriptionIfPresent();
191
+ const startToken = this.currentToken;
192
+ // Accept STRING token (quoted), IDENTIFIER token (unquoted), or any
193
+ // keyword token used as an identifier (e.g. "import", "from", "context").
194
+ // Keywords are context-sensitive: inside a capability list, any word-like
195
+ // token should be treated as a plain identifier.
196
+ let action;
197
+ if (this.check(TokenType.STRING)) {
198
+ action = this.advance().value;
199
+ }
200
+ else if (this.check(TokenType.IDENTIFIER) || this.isKeywordUsedAsIdentifier()) {
201
+ // Single identifier for unquoted capability
202
+ // For multi-word capabilities, use quotes: "browse products"
203
+ action = this.advance().value;
204
+ }
205
+ else {
206
+ throw new SyntaxError(`Expected capability (string or identifier) at line ${this.currentToken.location.line}, got token type ${this.currentToken.type} with value '${this.currentToken.value}'`);
207
+ }
208
+ this.skipNewlines();
209
+ const nested = [];
210
+ const conditions = [];
211
+ // Check for nested capabilities
212
+ if (this.check(TokenType.LBRACE)) {
213
+ this.advance();
214
+ this.skipNewlines();
215
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
216
+ const loopStartPos = this.currentToken.location.offset;
217
+ nested.push(this.parseCapability());
218
+ // Allow optional comma separator
219
+ if (this.check(TokenType.COMMA)) {
220
+ this.advance();
221
+ }
222
+ this.skipNewlines();
223
+ // Safety: ensure outer loop is advancing
224
+ if (this.currentToken.location.offset === loopStartPos &&
225
+ !this.check(TokenType.RBRACE)) {
226
+ throw new SyntaxError(`Parser stuck at line ${this.currentToken.location.line}: unexpected token '${this.currentToken.value}' in nested capabilities`);
227
+ }
228
+ }
229
+ this.consume(TokenType.RBRACE, "Expected '}' after nested capabilities");
230
+ this.skipNewlines();
231
+ }
232
+ // Allow optional comma after capability
233
+ if (this.check(TokenType.COMMA)) {
234
+ this.advance();
235
+ }
236
+ // Check for inline conditions
237
+ if (this.check(TokenType.IF) || this.check(TokenType.WHEN)) {
238
+ this.advance();
239
+ conditions.push(this.parseCondition());
240
+ }
241
+ return {
242
+ type: "Capability",
243
+ verb: undefined,
244
+ action,
245
+ description,
246
+ nested: nested.length > 0 ? nested : undefined,
247
+ conditions: conditions.length > 0 ? conditions : undefined,
248
+ location: {
249
+ start: startToken.location.offset,
250
+ end: this.currentToken.location.offset,
251
+ line: startToken.location.line,
252
+ column: startToken.location.column,
253
+ },
254
+ };
255
+ }
256
+ parseCondition() {
257
+ const startToken = this.currentToken;
258
+ const expression = this.parseExpression();
259
+ return {
260
+ type: "Condition",
261
+ expression,
262
+ location: {
263
+ start: startToken.location.offset,
264
+ end: this.currentToken.location.offset,
265
+ line: startToken.location.line,
266
+ column: startToken.location.column,
267
+ },
268
+ };
269
+ }
270
+ parseExpression() {
271
+ return this.parseOrExpression();
272
+ }
273
+ parseOrExpression() {
274
+ const startToken = this.currentToken;
275
+ let left = this.parseAndExpression();
276
+ while (this.check(TokenType.OR)) {
277
+ this.advance();
278
+ const right = this.parseAndExpression();
279
+ left = {
280
+ type: "Expression",
281
+ operator: "or",
282
+ left,
283
+ right,
284
+ location: {
285
+ start: startToken.location.offset,
286
+ end: this.currentToken.location.offset,
287
+ line: startToken.location.line,
288
+ column: startToken.location.column,
289
+ },
290
+ };
291
+ }
292
+ return left;
293
+ }
294
+ parseAndExpression() {
295
+ const startToken = this.currentToken;
296
+ let left = this.parseComparisonExpression();
297
+ while (this.check(TokenType.AND)) {
298
+ this.advance();
299
+ const right = this.parseComparisonExpression();
300
+ left = {
301
+ type: "Expression",
302
+ operator: "and",
303
+ left,
304
+ right,
305
+ location: {
306
+ start: startToken.location.offset,
307
+ end: this.currentToken.location.offset,
308
+ line: startToken.location.line,
309
+ column: startToken.location.column,
310
+ },
311
+ };
312
+ }
313
+ return left;
314
+ }
315
+ parseComparisonExpression() {
316
+ const startToken = this.currentToken;
317
+ let left = this.parsePrimaryExpression();
318
+ while (this.checkAny(TokenType.EQ, TokenType.NEQ, TokenType.LT, TokenType.LTE, TokenType.GT, TokenType.GTE)) {
319
+ const op = this.advance().value;
320
+ const right = this.parsePrimaryExpression();
321
+ left = {
322
+ type: "Expression",
323
+ operator: op,
324
+ left,
325
+ right,
326
+ location: {
327
+ start: startToken.location.offset,
328
+ end: this.currentToken.location.offset,
329
+ line: startToken.location.line,
330
+ column: startToken.location.column,
331
+ },
332
+ };
333
+ }
334
+ return left;
335
+ }
336
+ parsePrimaryExpression() {
337
+ const startToken = this.currentToken;
338
+ if (this.check(TokenType.TRUE)) {
339
+ this.advance();
340
+ return {
341
+ type: "Expression",
342
+ value: true,
343
+ location: {
344
+ start: startToken.location.offset,
345
+ end: this.currentToken.location.offset,
346
+ line: startToken.location.line,
347
+ column: startToken.location.column,
348
+ },
349
+ };
350
+ }
351
+ if (this.check(TokenType.FALSE)) {
352
+ this.advance();
353
+ return {
354
+ type: "Expression",
355
+ value: false,
356
+ location: {
357
+ start: startToken.location.offset,
358
+ end: this.currentToken.location.offset,
359
+ line: startToken.location.line,
360
+ column: startToken.location.column,
361
+ },
362
+ };
363
+ }
364
+ if (this.check(TokenType.NUMBER)) {
365
+ const value = Number(this.advance().value);
366
+ return {
367
+ type: "Expression",
368
+ value,
369
+ location: {
370
+ start: startToken.location.offset,
371
+ end: this.currentToken.location.offset,
372
+ line: startToken.location.line,
373
+ column: startToken.location.column,
374
+ },
375
+ };
376
+ }
377
+ if (this.check(TokenType.STRING)) {
378
+ const value = this.advance().value;
379
+ return {
380
+ type: "Expression",
381
+ value,
382
+ location: {
383
+ start: startToken.location.offset,
384
+ end: this.currentToken.location.offset,
385
+ line: startToken.location.line,
386
+ column: startToken.location.column,
387
+ },
388
+ };
389
+ }
390
+ if (this.check(TokenType.IDENTIFIER)) {
391
+ const value = this.advance().value;
392
+ return {
393
+ type: "Expression",
394
+ value,
395
+ location: {
396
+ start: startToken.location.offset,
397
+ end: this.currentToken.location.offset,
398
+ line: startToken.location.line,
399
+ column: startToken.location.column,
400
+ },
401
+ };
402
+ }
403
+ if (this.check(TokenType.LPAREN)) {
404
+ this.advance();
405
+ const expr = this.parseExpression();
406
+ this.consume(TokenType.RPAREN, "Expected ')' after expression");
407
+ return expr;
408
+ }
409
+ throw new SyntaxError(`Unexpected token in expression: ${this.currentToken.type}`);
410
+ }
411
+ parseRole(description) {
412
+ const startToken = this.consume(TokenType.ROLE);
413
+ const name = this.consume(TokenType.IDENTIFIER, "Expected role name").value;
414
+ this.skipNewlines();
415
+ this.consume(TokenType.LBRACE, "Expected '{' after role name");
416
+ this.skipNewlines();
417
+ const permissions = [];
418
+ const inherits = [];
419
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
420
+ const loopStart = this.currentToken.location.offset;
421
+ // Check for description before permission
422
+ const permissionDescription = this.parseDescriptionIfPresent();
423
+ if (this.check(TokenType.PERMISSION)) {
424
+ this.advance();
425
+ const resource = this.consume(TokenType.IDENTIFIER, "Expected resource name").value;
426
+ const actions = [];
427
+ if (this.check(TokenType.LBRACE)) {
428
+ this.advance();
429
+ this.skipNewlines();
430
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
431
+ actions.push(this.consume(TokenType.IDENTIFIER, "Expected action name").value);
432
+ if (this.check(TokenType.COMMA)) {
433
+ this.advance();
434
+ this.skipNewlines();
435
+ }
436
+ this.skipNewlines();
437
+ }
438
+ this.consume(TokenType.RBRACE, "Expected '}' after actions");
439
+ }
440
+ permissions.push({
441
+ type: "Permission",
442
+ resource,
443
+ description: permissionDescription,
444
+ actions,
445
+ location: {
446
+ start: startToken.location.offset,
447
+ end: this.currentToken.location.offset,
448
+ line: startToken.location.line,
449
+ column: startToken.location.column,
450
+ },
451
+ });
452
+ }
453
+ else {
454
+ // If we hit an unexpected token, throw an error instead of hanging
455
+ throw new SyntaxError(`Unexpected token '${this.currentToken.value}' (type: ${this.currentToken.type}) at line ${this.currentToken.location.line}. ` +
456
+ `Expected 'permission' keyword or '}' to close role definition. ` +
457
+ `Note: Role definitions use 'permission resource { actions }' syntax, not field syntax with colons.`);
458
+ }
459
+ this.skipNewlines();
460
+ // Safety: ensure we're advancing
461
+ if (this.currentToken.location.offset === loopStart &&
462
+ !this.check(TokenType.RBRACE)) {
463
+ throw new SyntaxError(`Parser stuck in role definition at line ${this.currentToken.location.line}`);
464
+ }
465
+ }
466
+ this.consume(TokenType.RBRACE, "Expected '}' after role body");
467
+ return {
468
+ type: "RoleDefinition",
469
+ name,
470
+ description,
471
+ permissions,
472
+ inherits: inherits.length > 0 ? inherits : undefined,
473
+ location: {
474
+ start: startToken.location.offset,
475
+ end: this.currentToken.location.offset,
476
+ line: startToken.location.line,
477
+ column: startToken.location.column,
478
+ },
479
+ };
480
+ }
481
+ parseWorkflow(description) {
482
+ const startToken = this.consume(TokenType.WORKFLOW);
483
+ const name = this.consume(TokenType.IDENTIFIER, "Expected workflow name").value;
484
+ this.skipNewlines();
485
+ this.consume(TokenType.LBRACE, "Expected '{' after workflow name");
486
+ this.skipNewlines();
487
+ const steps = [];
488
+ let initialState = "";
489
+ const finalStates = [];
490
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
491
+ // Check for description before state
492
+ const stepDescription = this.parseDescriptionIfPresent();
493
+ // Handle 'initial <stateName>' to set the initial state
494
+ if (this.check(TokenType.INITIAL)) {
495
+ this.advance();
496
+ initialState = this.consume(TokenType.IDENTIFIER, "Expected state name after 'initial'").value;
497
+ this.skipNewlines();
498
+ continue;
499
+ }
500
+ if (this.check(TokenType.STATE)) {
501
+ this.advance();
502
+ const stateName = this.consume(TokenType.IDENTIFIER, "Expected state name").value;
503
+ if (this.match(TokenType.ARROW)) {
504
+ const transitions = [];
505
+ while (!this.check(TokenType.NEWLINE) && !this.check(TokenType.RBRACE) &&
506
+ !this.isAtEnd()) {
507
+ const toState = this.consume(TokenType.IDENTIFIER, "Expected target state").value;
508
+ transitions.push({
509
+ type: "Transition",
510
+ from: stateName,
511
+ to: toState,
512
+ location: {
513
+ start: startToken.location.offset,
514
+ end: this.currentToken.location.offset,
515
+ line: startToken.location.line,
516
+ column: startToken.location.column,
517
+ },
518
+ });
519
+ if (this.match(TokenType.COMMA)) {
520
+ // Continue parsing transitions
521
+ }
522
+ else {
523
+ break;
524
+ }
525
+ }
526
+ steps.push({
527
+ type: "WorkflowStep",
528
+ name: stateName,
529
+ description: stepDescription,
530
+ action: "transition",
531
+ transitions,
532
+ location: {
533
+ start: startToken.location.offset,
534
+ end: this.currentToken.location.offset,
535
+ line: startToken.location.line,
536
+ column: startToken.location.column,
537
+ },
538
+ });
539
+ }
540
+ this.skipNewlines();
541
+ continue;
542
+ }
543
+ // If we reach here, we have an unexpected token in the workflow body
544
+ throw new SyntaxError(`Unexpected token '${this.currentToken.type}' in workflow definition at line ${this.currentToken.location.line}:${this.currentToken.location.column}. ` +
545
+ `Workflows should contain 'initial <state>' or 'state <name> -> <transitions>' declarations. ` +
546
+ `Note: Workflows use state machine syntax, not method declarations.`);
547
+ }
548
+ this.consume(TokenType.RBRACE, "Expected '}' after workflow body");
549
+ return {
550
+ type: "WorkflowDefinition",
551
+ name,
552
+ description,
553
+ steps,
554
+ initialState,
555
+ finalStates,
556
+ location: {
557
+ start: startToken.location.offset,
558
+ end: this.currentToken.location.offset,
559
+ line: startToken.location.line,
560
+ column: startToken.location.column,
561
+ },
562
+ };
563
+ }
564
+ parseAgent(description) {
565
+ const startToken = this.consume(TokenType.AGENT);
566
+ const name = this.consume(TokenType.IDENTIFIER, "Expected agent name").value;
567
+ let role = "";
568
+ if (this.match(TokenType.COLON)) {
569
+ role = this.consume(TokenType.IDENTIFIER, "Expected role name").value;
570
+ }
571
+ this.skipNewlines();
572
+ this.consume(TokenType.LBRACE, "Expected '{' after agent name");
573
+ this.skipNewlines();
574
+ const capabilities = [];
575
+ const responsibilities = [];
576
+ let skills;
577
+ let model;
578
+ let maxConcurrent;
579
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
580
+ if (this.check(TokenType.CAPABILITIES)) {
581
+ this.advance();
582
+ this.consume(TokenType.COLON, "Expected ':' after capabilities");
583
+ const capList = this.parseStringArray();
584
+ // Convert to capability nodes
585
+ for (const cap of capList) {
586
+ capabilities.push({
587
+ type: "Capability",
588
+ verb: "can",
589
+ action: cap,
590
+ location: {
591
+ start: startToken.location.offset,
592
+ end: this.currentToken.location.offset,
593
+ line: startToken.location.line,
594
+ column: startToken.location.column,
595
+ },
596
+ });
597
+ }
598
+ }
599
+ else if (this.check(TokenType.SKILLS)) {
600
+ this.advance();
601
+ this.consume(TokenType.COLON, "Expected ':' after skills");
602
+ skills = this.parseStringArray();
603
+ }
604
+ else if (this.check(TokenType.MODEL)) {
605
+ this.advance();
606
+ this.consume(TokenType.COLON, "Expected ':' after model");
607
+ model = this.consume(TokenType.STRING, "Expected string value").value;
608
+ }
609
+ else if (this.check(TokenType.MAX_CONCURRENT)) {
610
+ this.advance();
611
+ this.consume(TokenType.COLON, "Expected ':' after max_concurrent");
612
+ maxConcurrent = parseInt(this.consume(TokenType.NUMBER, "Expected number value").value);
613
+ }
614
+ else if (this.check(TokenType.STRING) || this.check(TokenType.IDENTIFIER) ||
615
+ this.check(TokenType.PROMPT)) {
616
+ // Parse the full capability with nested capabilities support (including descriptions)
617
+ capabilities.push(this.parseCapability());
618
+ }
619
+ else {
620
+ this.advance();
621
+ }
622
+ this.skipNewlines();
623
+ }
624
+ this.consume(TokenType.RBRACE, "Expected '}' after agent body");
625
+ // Determine agent kind based on properties
626
+ // Builder agents have skills, model, or maxConcurrent properties
627
+ // Domain agents have business logic capabilities and may have roles
628
+ const agentKind = (skills !== undefined || model !== undefined ||
629
+ maxConcurrent !== undefined)
630
+ ? "builder"
631
+ : "domain";
632
+ return {
633
+ type: "AgentDefinition",
634
+ name,
635
+ description,
636
+ agentKind,
637
+ role,
638
+ responsibilities,
639
+ capabilities,
640
+ skills,
641
+ model,
642
+ maxConcurrent,
643
+ location: {
644
+ start: startToken.location.offset,
645
+ end: this.currentToken.location.offset,
646
+ line: startToken.location.line,
647
+ column: startToken.location.column,
648
+ },
649
+ };
650
+ }
651
+ parseTypeDefinition(description) {
652
+ const startToken = this.currentToken;
653
+ let kind = "type";
654
+ if (this.check(TokenType.TYPE)) {
655
+ kind = "type";
656
+ this.advance();
657
+ }
658
+ else if (this.check(TokenType.ENUM)) {
659
+ kind = "enum";
660
+ this.advance();
661
+ }
662
+ else if (this.check(TokenType.INTERFACE)) {
663
+ kind = "interface";
664
+ this.advance();
665
+ }
666
+ this.skipNewlines();
667
+ const name = this.consumeIdentifierOrKeyword(`Expected type name after '${kind}' keyword at line ${this.currentToken.location.line}:${this.currentToken.location.column}. Got '${this.currentToken.value || this.currentToken.type}' instead.`).value;
668
+ this.skipNewlines();
669
+ this.consume(TokenType.LBRACE, "Expected '{' after type name");
670
+ this.skipNewlines();
671
+ const fields = [];
672
+ const values = [];
673
+ while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
674
+ if (kind === "enum") {
675
+ // Enum values remain plain strings (no descriptions)
676
+ values.push(this.consumeIdentifierOrKeyword("Expected enum value").value);
677
+ }
678
+ else {
679
+ // Check for description before field
680
+ const fieldDescription = this.parseDescriptionIfPresent();
681
+ const fieldName = this.consumeIdentifierOrKeyword("Expected field name").value;
682
+ this.consume(TokenType.COLON, "Expected ':' after field name");
683
+ // Parse field type with optional array syntax
684
+ let fieldType = this.consumeIdentifierOrKeyword("Expected field type").value;
685
+ // Handle array syntax: string[], TypeName[], TypeName[][]
686
+ while (this.check(TokenType.LBRACKET)) {
687
+ this.advance(); // consume '['
688
+ this.consume(TokenType.RBRACKET, "Expected ']' after '['");
689
+ fieldType += "[]";
690
+ }
691
+ fields.push({
692
+ type: "TypeField",
693
+ name: fieldName,
694
+ description: fieldDescription,
695
+ fieldType,
696
+ required: true,
697
+ location: {
698
+ start: startToken.location.offset,
699
+ end: this.currentToken.location.offset,
700
+ line: startToken.location.line,
701
+ column: startToken.location.column,
702
+ },
703
+ });
704
+ }
705
+ if (this.check(TokenType.COMMA)) {
706
+ this.advance();
707
+ }
708
+ this.skipNewlines();
709
+ }
710
+ this.consume(TokenType.RBRACE, "Expected '}' after type body");
711
+ return {
712
+ type: "TypeDefinition",
713
+ name,
714
+ description,
715
+ kind,
716
+ fields: fields.length > 0 ? fields : undefined,
717
+ values: values.length > 0 ? values : undefined,
718
+ location: {
719
+ start: startToken.location.offset,
720
+ end: this.currentToken.location.offset,
721
+ line: startToken.location.line,
722
+ column: startToken.location.column,
723
+ },
724
+ };
725
+ }
726
+ /**
727
+ * Parse string array: [item1, item2, item3]
728
+ */
729
+ parseStringArray() {
730
+ const items = [];
731
+ this.consume(TokenType.LBRACKET, "Expected '['");
732
+ this.skipNewlines();
733
+ while (!this.check(TokenType.RBRACKET) && !this.isAtEnd()) {
734
+ if (this.check(TokenType.IDENTIFIER)) {
735
+ items.push(this.advance().value);
736
+ }
737
+ else if (this.check(TokenType.STRING)) {
738
+ items.push(this.advance().value);
739
+ }
740
+ else {
741
+ throw new SyntaxError(`Expected identifier or string but got ${this.currentToken.type} at line ${this.currentToken.location.line}:${this.currentToken.location.column}`);
742
+ }
743
+ if (this.check(TokenType.COMMA)) {
744
+ this.advance();
745
+ this.skipNewlines();
746
+ }
747
+ else {
748
+ break;
749
+ }
750
+ }
751
+ this.consume(TokenType.RBRACKET, "Expected ']'");
752
+ return items;
753
+ }
754
+ }