@isl-lang/repl 0.0.1 → 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,1812 @@
1
+ import * as readline from 'readline';
2
+ import * as fs2 from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+
6
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
7
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
8
+ }) : x)(function(x) {
9
+ if (typeof require !== "undefined") return require.apply(this, arguments);
10
+ throw Error('Dynamic require of "' + x + '" is not supported');
11
+ });
12
+ var Session = class {
13
+ /** Defined intents in this session */
14
+ intents = /* @__PURE__ */ new Map();
15
+ /** Variables set during the session */
16
+ variables = /* @__PURE__ */ new Map();
17
+ /** Command history */
18
+ history = [];
19
+ /** Last evaluation result */
20
+ lastResult = void 0;
21
+ /** Loaded files */
22
+ loadedFiles = /* @__PURE__ */ new Set();
23
+ /** Session configuration */
24
+ config;
25
+ constructor(config = {}) {
26
+ this.config = {
27
+ colors: true,
28
+ verbose: false,
29
+ cwd: process.cwd(),
30
+ ...config
31
+ };
32
+ }
33
+ // ─────────────────────────────────────────────────────────────────────────
34
+ // Intent Management
35
+ // ─────────────────────────────────────────────────────────────────────────
36
+ /**
37
+ * Define a new intent
38
+ */
39
+ defineIntent(intent) {
40
+ this.intents.set(intent.name, intent);
41
+ }
42
+ /**
43
+ * Get an intent by name
44
+ */
45
+ getIntent(name) {
46
+ return this.intents.get(name);
47
+ }
48
+ /**
49
+ * Get all defined intents
50
+ */
51
+ getAllIntents() {
52
+ return Array.from(this.intents.values());
53
+ }
54
+ /**
55
+ * Check if an intent exists
56
+ */
57
+ hasIntent(name) {
58
+ return this.intents.has(name);
59
+ }
60
+ /**
61
+ * Remove an intent
62
+ */
63
+ removeIntent(name) {
64
+ return this.intents.delete(name);
65
+ }
66
+ /**
67
+ * Get intent names for completion
68
+ */
69
+ getIntentNames() {
70
+ return Array.from(this.intents.keys());
71
+ }
72
+ /**
73
+ * Parse an intent definition from source code
74
+ */
75
+ parseIntent(source) {
76
+ const trimmed = source.trim();
77
+ const match = trimmed.match(/^intent\s+(\w+)\s*\{([\s\S]*)\}$/);
78
+ if (!match) {
79
+ return null;
80
+ }
81
+ const name = match[1];
82
+ const body = match[2];
83
+ const intent = {
84
+ name,
85
+ preconditions: [],
86
+ postconditions: [],
87
+ invariants: [],
88
+ scenarios: [],
89
+ rawSource: source
90
+ };
91
+ const preMatch = body.match(/pre(?:conditions?)?\s*:\s*([^\n]+)/g);
92
+ if (preMatch) {
93
+ for (const pre of preMatch) {
94
+ const expr = pre.replace(/pre(?:conditions?)?\s*:\s*/, "").trim();
95
+ if (expr) {
96
+ intent.preconditions.push({ expression: expr });
97
+ }
98
+ }
99
+ }
100
+ const postMatch = body.match(/post(?:conditions?)?\s*:\s*([^\n]+)/g);
101
+ if (postMatch) {
102
+ for (const post of postMatch) {
103
+ const expr = post.replace(/post(?:conditions?)?\s*:\s*/, "").trim();
104
+ if (expr) {
105
+ intent.postconditions.push({ expression: expr });
106
+ }
107
+ }
108
+ }
109
+ const invMatch = body.match(/invariants?\s*:\s*([^\n]+)/g);
110
+ if (invMatch) {
111
+ for (const inv of invMatch) {
112
+ const expr = inv.replace(/invariants?\s*:\s*/, "").trim();
113
+ if (expr) {
114
+ intent.invariants.push({ expression: expr });
115
+ }
116
+ }
117
+ }
118
+ return intent;
119
+ }
120
+ // ─────────────────────────────────────────────────────────────────────────
121
+ // Variable Management
122
+ // ─────────────────────────────────────────────────────────────────────────
123
+ /**
124
+ * Set a variable
125
+ */
126
+ setVariable(name, value) {
127
+ this.variables.set(name, value);
128
+ }
129
+ /**
130
+ * Get a variable
131
+ */
132
+ getVariable(name) {
133
+ return this.variables.get(name);
134
+ }
135
+ /**
136
+ * Get all variables
137
+ */
138
+ getAllVariables() {
139
+ return new Map(this.variables);
140
+ }
141
+ /**
142
+ * Check if a variable exists
143
+ */
144
+ hasVariable(name) {
145
+ return this.variables.has(name);
146
+ }
147
+ /**
148
+ * Set the last result (accessible as _)
149
+ */
150
+ setLastResult(value) {
151
+ this.lastResult = value;
152
+ this.variables.set("_", value);
153
+ }
154
+ /**
155
+ * Get the last result
156
+ */
157
+ getLastResult() {
158
+ return this.lastResult;
159
+ }
160
+ // ─────────────────────────────────────────────────────────────────────────
161
+ // History Management
162
+ // ─────────────────────────────────────────────────────────────────────────
163
+ /**
164
+ * Add to history
165
+ */
166
+ addToHistory(entry) {
167
+ const trimmed = entry.trim();
168
+ if (trimmed && (this.history.length === 0 || this.history[this.history.length - 1] !== trimmed)) {
169
+ this.history.push(trimmed);
170
+ }
171
+ }
172
+ /**
173
+ * Get history
174
+ */
175
+ getHistory(count) {
176
+ if (count) {
177
+ return this.history.slice(-count);
178
+ }
179
+ return [...this.history];
180
+ }
181
+ // ─────────────────────────────────────────────────────────────────────────
182
+ // File Loading
183
+ // ─────────────────────────────────────────────────────────────────────────
184
+ /**
185
+ * Load intents from an ISL file
186
+ */
187
+ async loadFile(filePath) {
188
+ const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(this.config.cwd, filePath);
189
+ if (!fs2.existsSync(resolvedPath)) {
190
+ return { intents: [], errors: [`File not found: ${resolvedPath}`] };
191
+ }
192
+ try {
193
+ const content = fs2.readFileSync(resolvedPath, "utf-8");
194
+ const loadedIntents = [];
195
+ const errors = [];
196
+ const intentRegex = /intent\s+(\w+)\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}/g;
197
+ let match;
198
+ while ((match = intentRegex.exec(content)) !== null) {
199
+ const intent = this.parseIntent(match[0]);
200
+ if (intent) {
201
+ this.defineIntent(intent);
202
+ loadedIntents.push(intent);
203
+ } else {
204
+ errors.push(`Failed to parse intent starting at position ${match.index}`);
205
+ }
206
+ }
207
+ const behaviorRegex = /behavior\s+(\w+)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/g;
208
+ while ((match = behaviorRegex.exec(content)) !== null) {
209
+ const intent = this.parseBehaviorAsIntent(match[1], match[2]);
210
+ if (intent) {
211
+ this.defineIntent(intent);
212
+ loadedIntents.push(intent);
213
+ }
214
+ }
215
+ this.loadedFiles.add(resolvedPath);
216
+ return { intents: loadedIntents, errors };
217
+ } catch (error) {
218
+ return {
219
+ intents: [],
220
+ errors: [`Failed to load file: ${error instanceof Error ? error.message : String(error)}`]
221
+ };
222
+ }
223
+ }
224
+ /**
225
+ * Parse a behavior block as an intent
226
+ */
227
+ parseBehaviorAsIntent(name, body) {
228
+ const intent = {
229
+ name,
230
+ preconditions: [],
231
+ postconditions: [],
232
+ invariants: [],
233
+ scenarios: [],
234
+ rawSource: `behavior ${name} {${body}}`
235
+ };
236
+ const preSection = body.match(/pre(?:conditions)?\s*\{([^}]*)\}/s);
237
+ if (preSection) {
238
+ const conditions = preSection[1].trim().split("\n").map((l) => l.trim()).filter(Boolean);
239
+ for (const cond of conditions) {
240
+ const expr = cond.replace(/^-\s*/, "").trim();
241
+ if (expr) {
242
+ intent.preconditions.push({ expression: expr });
243
+ }
244
+ }
245
+ }
246
+ const postSection = body.match(/post(?:conditions)?\s*\{([^}]*)\}/s);
247
+ if (postSection) {
248
+ const conditions = postSection[1].trim().split("\n").map((l) => l.trim()).filter(Boolean);
249
+ for (const cond of conditions) {
250
+ const expr = cond.replace(/^-\s*/, "").trim();
251
+ if (expr) {
252
+ intent.postconditions.push({ expression: expr });
253
+ }
254
+ }
255
+ }
256
+ const invSection = body.match(/invariants?\s*\{([^}]*)\}/s);
257
+ if (invSection) {
258
+ const conditions = invSection[1].trim().split("\n").map((l) => l.trim()).filter(Boolean);
259
+ for (const cond of conditions) {
260
+ const expr = cond.replace(/^-\s*/, "").trim();
261
+ if (expr) {
262
+ intent.invariants.push({ expression: expr });
263
+ }
264
+ }
265
+ }
266
+ return intent;
267
+ }
268
+ /**
269
+ * Export session intents to a file
270
+ */
271
+ async exportToFile(filePath) {
272
+ const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(this.config.cwd, filePath);
273
+ try {
274
+ const lines = [];
275
+ lines.push("// Exported ISL intents");
276
+ lines.push(`// Generated at ${(/* @__PURE__ */ new Date()).toISOString()}`);
277
+ lines.push("");
278
+ for (const intent of this.intents.values()) {
279
+ lines.push(`intent ${intent.name} {`);
280
+ for (const pre of intent.preconditions) {
281
+ lines.push(` pre: ${pre.expression}`);
282
+ }
283
+ for (const post of intent.postconditions) {
284
+ lines.push(` post: ${post.expression}`);
285
+ }
286
+ for (const inv of intent.invariants) {
287
+ lines.push(` invariant: ${inv.expression}`);
288
+ }
289
+ lines.push("}");
290
+ lines.push("");
291
+ }
292
+ fs2.writeFileSync(resolvedPath, lines.join("\n"));
293
+ return { success: true };
294
+ } catch (error) {
295
+ return {
296
+ success: false,
297
+ error: `Failed to export: ${error instanceof Error ? error.message : String(error)}`
298
+ };
299
+ }
300
+ }
301
+ // ─────────────────────────────────────────────────────────────────────────
302
+ // State Management
303
+ // ─────────────────────────────────────────────────────────────────────────
304
+ /**
305
+ * Clear all session state
306
+ */
307
+ clear() {
308
+ this.intents.clear();
309
+ this.variables.clear();
310
+ this.lastResult = void 0;
311
+ this.loadedFiles.clear();
312
+ }
313
+ /**
314
+ * Get session summary
315
+ */
316
+ getSummary() {
317
+ return {
318
+ intentCount: this.intents.size,
319
+ variableCount: this.variables.size,
320
+ loadedFileCount: this.loadedFiles.size,
321
+ historyCount: this.history.length
322
+ };
323
+ }
324
+ /**
325
+ * Get loaded files
326
+ */
327
+ getLoadedFiles() {
328
+ return Array.from(this.loadedFiles);
329
+ }
330
+ /**
331
+ * Get config
332
+ */
333
+ getConfig() {
334
+ return { ...this.config };
335
+ }
336
+ /**
337
+ * Update config
338
+ */
339
+ setConfig(config) {
340
+ this.config = { ...this.config, ...config };
341
+ }
342
+ };
343
+ function createSession(config) {
344
+ return new Session(config);
345
+ }
346
+ var History = class {
347
+ entries = [];
348
+ position = -1;
349
+ maxSize;
350
+ historyFile;
351
+ unsavedCount = 0;
352
+ autoSaveThreshold = 10;
353
+ constructor(options = {}) {
354
+ this.maxSize = options.maxSize ?? 1e3;
355
+ this.historyFile = options.historyFile ?? this.getDefaultHistoryFile();
356
+ this.autoSaveThreshold = options.autoSaveThreshold ?? 10;
357
+ }
358
+ /**
359
+ * Get default history file path
360
+ */
361
+ getDefaultHistoryFile() {
362
+ const homeDir = os.homedir();
363
+ return path.join(homeDir, ".isl_repl_history");
364
+ }
365
+ /**
366
+ * Load history from file
367
+ */
368
+ load() {
369
+ try {
370
+ if (fs2.existsSync(this.historyFile)) {
371
+ const content = fs2.readFileSync(this.historyFile, "utf-8");
372
+ this.entries = content.split("\n").filter((line) => line.trim() !== "").slice(-this.maxSize);
373
+ this.position = this.entries.length;
374
+ }
375
+ } catch {
376
+ }
377
+ }
378
+ /**
379
+ * Save history to file
380
+ */
381
+ save() {
382
+ try {
383
+ const dir = path.dirname(this.historyFile);
384
+ if (!fs2.existsSync(dir)) {
385
+ fs2.mkdirSync(dir, { recursive: true });
386
+ }
387
+ fs2.writeFileSync(this.historyFile, this.entries.join("\n") + "\n");
388
+ this.unsavedCount = 0;
389
+ } catch {
390
+ }
391
+ }
392
+ /**
393
+ * Add entry to history
394
+ */
395
+ add(entry) {
396
+ const trimmed = entry.trim();
397
+ if (trimmed === "") return;
398
+ if (this.entries.length > 0 && this.entries[this.entries.length - 1] === trimmed) {
399
+ this.position = this.entries.length;
400
+ return;
401
+ }
402
+ this.entries.push(trimmed);
403
+ if (this.entries.length > this.maxSize) {
404
+ this.entries = this.entries.slice(-this.maxSize);
405
+ }
406
+ this.position = this.entries.length;
407
+ this.unsavedCount++;
408
+ if (this.unsavedCount >= this.autoSaveThreshold) {
409
+ this.save();
410
+ }
411
+ }
412
+ /**
413
+ * Get previous entry (for up arrow)
414
+ */
415
+ previous() {
416
+ if (this.entries.length === 0) return null;
417
+ if (this.position > 0) {
418
+ this.position--;
419
+ }
420
+ return this.entries[this.position] ?? null;
421
+ }
422
+ /**
423
+ * Get next entry (for down arrow)
424
+ */
425
+ next() {
426
+ if (this.entries.length === 0) return null;
427
+ if (this.position < this.entries.length - 1) {
428
+ this.position++;
429
+ return this.entries[this.position] ?? null;
430
+ }
431
+ this.position = this.entries.length;
432
+ return "";
433
+ }
434
+ /**
435
+ * Reset position to end
436
+ */
437
+ resetPosition() {
438
+ this.position = this.entries.length;
439
+ }
440
+ /**
441
+ * Search history for entries containing text
442
+ */
443
+ search(text) {
444
+ const lower = text.toLowerCase();
445
+ return this.entries.filter(
446
+ (entry) => entry.toLowerCase().includes(lower)
447
+ );
448
+ }
449
+ /**
450
+ * Search backwards from current position
451
+ */
452
+ searchBackward(text) {
453
+ const lower = text.toLowerCase();
454
+ for (let i = this.position - 1; i >= 0; i--) {
455
+ if (this.entries[i].toLowerCase().includes(lower)) {
456
+ this.position = i;
457
+ return this.entries[i];
458
+ }
459
+ }
460
+ return null;
461
+ }
462
+ /**
463
+ * Search forward from current position
464
+ */
465
+ searchForward(text) {
466
+ const lower = text.toLowerCase();
467
+ for (let i = this.position + 1; i < this.entries.length; i++) {
468
+ if (this.entries[i].toLowerCase().includes(lower)) {
469
+ this.position = i;
470
+ return this.entries[i];
471
+ }
472
+ }
473
+ return null;
474
+ }
475
+ /**
476
+ * Get all entries
477
+ */
478
+ getAll() {
479
+ return [...this.entries];
480
+ }
481
+ /**
482
+ * Get recent entries
483
+ */
484
+ getRecent(count) {
485
+ return this.entries.slice(-count);
486
+ }
487
+ /**
488
+ * Clear history
489
+ */
490
+ clear() {
491
+ this.entries = [];
492
+ this.position = 0;
493
+ this.save();
494
+ }
495
+ /**
496
+ * Get history size
497
+ */
498
+ get size() {
499
+ return this.entries.length;
500
+ }
501
+ /**
502
+ * Get current position
503
+ */
504
+ get currentPosition() {
505
+ return this.position;
506
+ }
507
+ };
508
+ var MemoryHistory = class extends History {
509
+ constructor(maxSize = 1e3) {
510
+ super({ maxSize, historyFile: "" });
511
+ }
512
+ load() {
513
+ }
514
+ save() {
515
+ }
516
+ };
517
+
518
+ // src/formatter.ts
519
+ var colors = {
520
+ reset: "\x1B[0m",
521
+ bold: "\x1B[1m",
522
+ dim: "\x1B[2m",
523
+ italic: "\x1B[3m",
524
+ underline: "\x1B[4m",
525
+ // Foreground colors
526
+ black: "\x1B[30m",
527
+ red: "\x1B[31m",
528
+ green: "\x1B[32m",
529
+ yellow: "\x1B[33m",
530
+ blue: "\x1B[34m",
531
+ magenta: "\x1B[35m",
532
+ cyan: "\x1B[36m",
533
+ white: "\x1B[37m",
534
+ gray: "\x1B[90m",
535
+ // Bright foreground
536
+ brightRed: "\x1B[91m",
537
+ brightGreen: "\x1B[92m",
538
+ brightYellow: "\x1B[93m",
539
+ brightBlue: "\x1B[94m",
540
+ brightMagenta: "\x1B[95m",
541
+ brightCyan: "\x1B[96m",
542
+ brightWhite: "\x1B[97m",
543
+ // Background colors
544
+ bgBlack: "\x1B[40m",
545
+ bgRed: "\x1B[41m",
546
+ bgGreen: "\x1B[42m",
547
+ bgYellow: "\x1B[43m",
548
+ bgBlue: "\x1B[44m",
549
+ bgMagenta: "\x1B[45m",
550
+ bgCyan: "\x1B[46m",
551
+ bgWhite: "\x1B[47m"
552
+ };
553
+ function formatSuccess(message) {
554
+ return `${colors.green}\u2713${colors.reset} ${message}`;
555
+ }
556
+ function formatError(message) {
557
+ return `${colors.red}\u2717 Error:${colors.reset} ${message}`;
558
+ }
559
+ function formatWarning(message) {
560
+ return `${colors.yellow}\u26A0${colors.reset} ${message}`;
561
+ }
562
+ function formatInfo(message) {
563
+ return `${colors.cyan}\u2139${colors.reset} ${message}`;
564
+ }
565
+ function formatIntent(intent) {
566
+ const lines = [
567
+ "",
568
+ `${colors.bold}Intent: ${colors.cyan}${intent.name}${colors.reset}`,
569
+ colors.gray + "\u2500".repeat(40) + colors.reset
570
+ ];
571
+ if (intent.preconditions.length > 0) {
572
+ lines.push("");
573
+ lines.push(`${colors.bold}Preconditions:${colors.reset}`);
574
+ for (const pre of intent.preconditions) {
575
+ lines.push(` ${colors.magenta}pre:${colors.reset} ${highlightExpression(pre.expression)}`);
576
+ }
577
+ }
578
+ if (intent.postconditions.length > 0) {
579
+ lines.push("");
580
+ lines.push(`${colors.bold}Postconditions:${colors.reset}`);
581
+ for (const post of intent.postconditions) {
582
+ lines.push(` ${colors.magenta}post:${colors.reset} ${highlightExpression(post.expression)}`);
583
+ }
584
+ }
585
+ if (intent.invariants.length > 0) {
586
+ lines.push("");
587
+ lines.push(`${colors.bold}Invariants:${colors.reset}`);
588
+ for (const inv of intent.invariants) {
589
+ lines.push(` ${colors.magenta}invariant:${colors.reset} ${highlightExpression(inv.expression)}`);
590
+ }
591
+ }
592
+ if (intent.scenarios.length > 0) {
593
+ lines.push("");
594
+ lines.push(`${colors.bold}Scenarios:${colors.reset}`);
595
+ for (const scenario of intent.scenarios) {
596
+ lines.push(` ${colors.yellow}${scenario.name}${colors.reset}`);
597
+ }
598
+ }
599
+ lines.push("");
600
+ return lines.join("\n");
601
+ }
602
+ function formatCondition(condition, type) {
603
+ const prefix = {
604
+ pre: colors.magenta + "pre" + colors.reset,
605
+ post: colors.magenta + "post" + colors.reset,
606
+ invariant: colors.magenta + "invariant" + colors.reset
607
+ }[type];
608
+ return `${prefix}: ${highlightExpression(condition.expression)}`;
609
+ }
610
+ function highlightExpression(expr) {
611
+ return expr.replace(/\b(and|or|not|implies)\b/g, `${colors.yellow}$1${colors.reset}`).replace(/(>=|<=|==|!=|>|<)/g, `${colors.yellow}$1${colors.reset}`).replace(/\b(true|false|null)\b/g, `${colors.magenta}$1${colors.reset}`).replace(/\b(forall|exists|in)\b/g, `${colors.yellow}$1${colors.reset}`).replace(/\b(\d+(?:\.\d+)?)\b/g, `${colors.cyan}$1${colors.reset}`).replace(/"([^"]*)"/g, `${colors.green}"$1"${colors.reset}`).replace(/\.(\w+)\(/g, `.${colors.blue}$1${colors.reset}(`).replace(/\.(\w+)(?!\()/g, `.${colors.cyan}$1${colors.reset}`);
612
+ }
613
+ function highlightISL(source) {
614
+ return source.replace(/\b(intent|behavior|entity|domain|type|enum)\b/g, `${colors.yellow}$1${colors.reset}`).replace(/\b(pre|post|invariant|scenario)\b/g, `${colors.magenta}$1${colors.reset}`).replace(/\b(input|output|success|errors?)\b/g, `${colors.blue}$1${colors.reset}`).replace(
615
+ /\b(String|Int|Boolean|UUID|Timestamp|Decimal|Duration|List|Map|Optional)\b/g,
616
+ `${colors.green}$1${colors.reset}`
617
+ ).replace(/\b(and|or|not|implies|forall|exists|in)\b/g, `${colors.yellow}$1${colors.reset}`).replace(/\b(true|false|null)\b/g, `${colors.magenta}$1${colors.reset}`).replace(/\b(\d+(?:\.\d+)?)\b/g, `${colors.cyan}$1${colors.reset}`).replace(/"([^"]*)"/g, `${colors.green}"$1"${colors.reset}`).replace(/(\/\/[^\n]*)/g, `${colors.gray}$1${colors.reset}`).replace(/(#[^\n]*)/g, `${colors.gray}$1${colors.reset}`);
618
+ }
619
+ function formatTable(headers, rows, options = {}) {
620
+ const useColors = options.colors !== false;
621
+ const widths = headers.map((h, i) => {
622
+ const cellWidths = [h.length, ...rows.map((r) => (r[i] ?? "").length)];
623
+ return Math.max(...cellWidths);
624
+ });
625
+ const headerRow = headers.map((h, i) => h.padEnd(widths[i])).join(" \u2502 ");
626
+ const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u253C\u2500");
627
+ const dataRows = rows.map(
628
+ (row) => row.map((cell, i) => (cell ?? "").padEnd(widths[i])).join(" \u2502 ")
629
+ );
630
+ const headerFormatted = useColors ? `${colors.bold}${headerRow}${colors.reset}` : headerRow;
631
+ const sepFormatted = useColors ? `${colors.gray}${separator}${colors.reset}` : separator;
632
+ return [headerFormatted, sepFormatted, ...dataRows].join("\n");
633
+ }
634
+ function formatParseError(source, message, line, column) {
635
+ const lines = source.split("\n");
636
+ const errorLine = lines[line - 1] || "";
637
+ const output = [
638
+ formatError(message),
639
+ "",
640
+ `${colors.gray}${String(line).padStart(4)} \u2502${colors.reset} ${errorLine}`,
641
+ `${colors.gray} \u2502${colors.reset} ${" ".repeat(column - 1)}${colors.red}^${colors.reset}`
642
+ ];
643
+ return output.join("\n");
644
+ }
645
+ function formatTypeError(message, expected, actual, context) {
646
+ const output = [
647
+ formatError(message),
648
+ "",
649
+ ` Expected: ${colors.green}${expected}${colors.reset}`,
650
+ ` Actual: ${colors.red}${actual}${colors.reset}`
651
+ ];
652
+ if (context) {
653
+ output.push("");
654
+ output.push(` Context: ${colors.gray}${context}${colors.reset}`);
655
+ }
656
+ return output.join("\n");
657
+ }
658
+ function formatValue(value, indent = 0) {
659
+ const pad = " ".repeat(indent);
660
+ if (value === null) return `${colors.gray}null${colors.reset}`;
661
+ if (value === void 0) return `${colors.gray}undefined${colors.reset}`;
662
+ if (typeof value === "string") {
663
+ return `${colors.green}"${value}"${colors.reset}`;
664
+ }
665
+ if (typeof value === "number") {
666
+ return `${colors.cyan}${value}${colors.reset}`;
667
+ }
668
+ if (typeof value === "boolean") {
669
+ return `${colors.magenta}${value}${colors.reset}`;
670
+ }
671
+ if (Array.isArray(value)) {
672
+ if (value.length === 0) return "[]";
673
+ const items = value.map((v) => formatValue(v, indent + 2));
674
+ return `[
675
+ ${pad} ${items.join(`,
676
+ ${pad} `)}
677
+ ${pad}]`;
678
+ }
679
+ if (typeof value === "object") {
680
+ const entries = Object.entries(value);
681
+ if (entries.length === 0) return "{}";
682
+ const items = entries.map(
683
+ ([k, v]) => `${colors.blue}${k}${colors.reset}: ${formatValue(v, indent + 2)}`
684
+ );
685
+ return `{
686
+ ${pad} ${items.join(`,
687
+ ${pad} `)}
688
+ ${pad}}`;
689
+ }
690
+ return String(value);
691
+ }
692
+ function stripColors(str) {
693
+ return str.replace(/\x1b\[[0-9;]*m/g, "");
694
+ }
695
+ function wrapText(text, maxWidth) {
696
+ const words = text.split(" ");
697
+ const lines = [];
698
+ let currentLine = "";
699
+ for (const word of words) {
700
+ const testLine = currentLine ? `${currentLine} ${word}` : word;
701
+ if (stripColors(testLine).length > maxWidth && currentLine) {
702
+ lines.push(currentLine);
703
+ currentLine = word;
704
+ } else {
705
+ currentLine = testLine;
706
+ }
707
+ }
708
+ if (currentLine) {
709
+ lines.push(currentLine);
710
+ }
711
+ return lines.join("\n");
712
+ }
713
+ function drawBox(lines, title) {
714
+ const maxLen = Math.max(...lines.map((l) => stripColors(l).length), title ? title.length + 4 : 0);
715
+ const top = title ? `\u2554\u2550 ${title} ${"\u2550".repeat(maxLen - title.length - 3)}\u2557` : `\u2554${"\u2550".repeat(maxLen + 2)}\u2557`;
716
+ const bottom = `\u255A${"\u2550".repeat(maxLen + 2)}\u255D`;
717
+ const paddedLines = lines.map((l) => {
718
+ const padding = maxLen - stripColors(l).length;
719
+ return `\u2551 ${l}${" ".repeat(padding)} \u2551`;
720
+ });
721
+ return [top, ...paddedLines, bottom].join("\n");
722
+ }
723
+
724
+ // src/commands.ts
725
+ var metaCommands = [
726
+ {
727
+ name: "help",
728
+ aliases: ["h", "?"],
729
+ description: "Show help for commands",
730
+ usage: ".help [command]",
731
+ handler: (args, session) => {
732
+ if (args.length > 0) {
733
+ const cmdName = args[0].toLowerCase();
734
+ const metaCmd = metaCommands.find((c) => c.name === cmdName || c.aliases.includes(cmdName));
735
+ if (metaCmd) {
736
+ return {
737
+ output: [
738
+ `${colors.cyan}.${metaCmd.name}${colors.reset} - ${metaCmd.description}`,
739
+ `Usage: ${metaCmd.usage}`,
740
+ metaCmd.aliases.length > 0 ? `Aliases: ${metaCmd.aliases.map((a) => "." + a).join(", ")}` : ""
741
+ ].filter(Boolean).join("\n")
742
+ };
743
+ }
744
+ const islCmd = islCommands.find((c) => c.name === cmdName || c.aliases.includes(cmdName));
745
+ if (islCmd) {
746
+ return {
747
+ output: [
748
+ `${colors.cyan}:${islCmd.name}${colors.reset} - ${islCmd.description}`,
749
+ `Usage: ${islCmd.usage}`,
750
+ islCmd.aliases.length > 0 ? `Aliases: ${islCmd.aliases.map((a) => ":" + a).join(", ")}` : ""
751
+ ].filter(Boolean).join("\n")
752
+ };
753
+ }
754
+ return { output: formatError(`Unknown command: ${cmdName}`) };
755
+ }
756
+ const lines = [
757
+ "",
758
+ `${colors.bold}Meta Commands${colors.reset} ${colors.gray}(REPL control)${colors.reset}`,
759
+ "",
760
+ ...metaCommands.map((c) => ` ${colors.cyan}.${c.name.padEnd(10)}${colors.reset} ${c.description}`),
761
+ "",
762
+ `${colors.bold}ISL Commands${colors.reset} ${colors.gray}(specification operations)${colors.reset}`,
763
+ "",
764
+ ...islCommands.map((c) => ` ${colors.cyan}:${c.name.padEnd(10)}${colors.reset} ${c.description}`),
765
+ "",
766
+ `${colors.bold}ISL Syntax${colors.reset}`,
767
+ "",
768
+ ` ${colors.yellow}intent${colors.reset} Name {`,
769
+ ` ${colors.magenta}pre${colors.reset}: condition`,
770
+ ` ${colors.magenta}post${colors.reset}: condition`,
771
+ ` }`,
772
+ "",
773
+ `Type ${colors.cyan}.help <command>${colors.reset} for detailed help.`,
774
+ ""
775
+ ];
776
+ return { output: lines.join("\n") };
777
+ }
778
+ },
779
+ {
780
+ name: "exit",
781
+ aliases: ["quit", "q"],
782
+ description: "Exit the REPL",
783
+ usage: ".exit",
784
+ handler: () => {
785
+ return { exit: true };
786
+ }
787
+ },
788
+ {
789
+ name: "clear",
790
+ aliases: ["cls"],
791
+ description: "Clear session state (intents, variables)",
792
+ usage: ".clear",
793
+ handler: (args, session) => {
794
+ session.clear();
795
+ return { output: formatSuccess("Session cleared") };
796
+ }
797
+ },
798
+ {
799
+ name: "history",
800
+ aliases: ["hist"],
801
+ description: "Show command history",
802
+ usage: ".history [n]",
803
+ handler: (args, session) => {
804
+ const count = args.length > 0 ? parseInt(args[0]) : 10;
805
+ const history = session.getHistory(count);
806
+ if (history.length === 0) {
807
+ return { output: "No history." };
808
+ }
809
+ const lines = [
810
+ `${colors.bold}History${colors.reset} (last ${history.length} entries)`,
811
+ "",
812
+ ...history.map((entry, i) => {
813
+ const num = String(i + 1).padStart(3);
814
+ const preview = entry.split("\n")[0];
815
+ const more = entry.includes("\n") ? ` ${colors.gray}...${colors.reset}` : "";
816
+ return ` ${colors.gray}${num}${colors.reset} ${preview}${more}`;
817
+ })
818
+ ];
819
+ return { output: lines.join("\n") };
820
+ }
821
+ }
822
+ ];
823
+ var islCommands = [
824
+ {
825
+ name: "check",
826
+ aliases: ["c"],
827
+ description: "Type check an intent",
828
+ usage: ":check <intent>",
829
+ handler: (args, session) => {
830
+ if (args.length === 0) {
831
+ const intents = session.getAllIntents();
832
+ if (intents.length === 0) {
833
+ return { output: formatWarning("No intents defined. Define one with: intent Name { ... }") };
834
+ }
835
+ const lines2 = [
836
+ formatSuccess("Type check passed"),
837
+ ""
838
+ ];
839
+ for (const intent2 of intents) {
840
+ lines2.push(`${colors.bold}${intent2.name}${colors.reset}`);
841
+ for (const pre of intent2.preconditions) {
842
+ lines2.push(` ${colors.green}\u2713${colors.reset} pre: ${highlightCondition(pre.expression)}`);
843
+ }
844
+ for (const post of intent2.postconditions) {
845
+ lines2.push(` ${colors.green}\u2713${colors.reset} post: ${highlightCondition(post.expression)}`);
846
+ }
847
+ lines2.push("");
848
+ }
849
+ return { output: lines2.join("\n") };
850
+ }
851
+ const intentName = args[0];
852
+ const intent = session.getIntent(intentName);
853
+ if (!intent) {
854
+ const available = session.getIntentNames().join(", ") || "(none)";
855
+ return {
856
+ output: formatError(`Unknown intent: ${intentName}
857
+ Available: ${available}`)
858
+ };
859
+ }
860
+ const lines = [
861
+ formatSuccess("Type check passed"),
862
+ ""
863
+ ];
864
+ for (const pre of intent.preconditions) {
865
+ lines.push(` pre: ${highlightCondition(pre.expression)} ${colors.green}\u2713${colors.reset}`);
866
+ }
867
+ for (const post of intent.postconditions) {
868
+ lines.push(` post: ${highlightCondition(post.expression)} ${colors.green}\u2713${colors.reset}`);
869
+ }
870
+ return { output: lines.join("\n") };
871
+ }
872
+ },
873
+ {
874
+ name: "gen",
875
+ aliases: ["generate", "g"],
876
+ description: "Generate code from an intent",
877
+ usage: ":gen <target> <intent>",
878
+ handler: (args, session) => {
879
+ if (args.length < 2) {
880
+ return {
881
+ output: [
882
+ "Usage: :gen <target> <intent>",
883
+ "",
884
+ "Targets:",
885
+ " typescript Generate TypeScript contract",
886
+ " rust Generate Rust contract",
887
+ " go Generate Go contract",
888
+ " openapi Generate OpenAPI schema"
889
+ ].join("\n")
890
+ };
891
+ }
892
+ const target = args[0].toLowerCase();
893
+ const intentName = args[1];
894
+ const intent = session.getIntent(intentName);
895
+ if (!intent) {
896
+ const available = session.getIntentNames().join(", ") || "(none)";
897
+ return {
898
+ output: formatError(`Unknown intent: ${intentName}
899
+ Available: ${available}`)
900
+ };
901
+ }
902
+ switch (target) {
903
+ case "typescript":
904
+ case "ts":
905
+ return { output: generateTypeScript(intent) };
906
+ case "rust":
907
+ case "rs":
908
+ return { output: generateRust(intent) };
909
+ case "go":
910
+ return { output: generateGo(intent) };
911
+ case "openapi":
912
+ case "oas":
913
+ return { output: generateOpenAPI(intent) };
914
+ default:
915
+ return {
916
+ output: formatError(`Unknown target: ${target}
917
+ Available: typescript, rust, go, openapi`)
918
+ };
919
+ }
920
+ }
921
+ },
922
+ {
923
+ name: "load",
924
+ aliases: ["l"],
925
+ description: "Load intents from a file",
926
+ usage: ":load <file.isl>",
927
+ handler: (args, session) => {
928
+ if (args.length === 0) {
929
+ return { output: "Usage: :load <file.isl>" };
930
+ }
931
+ const filePath = args[0];
932
+ let result = { errors: [] };
933
+ session.loadFile(filePath).then((r) => {
934
+ result = r;
935
+ }).catch((e) => {
936
+ result.errors.push(String(e));
937
+ });
938
+ const fs4 = __require("fs");
939
+ const path4 = __require("path");
940
+ try {
941
+ const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.resolve(process.cwd(), filePath);
942
+ if (!fs4.existsSync(resolvedPath)) {
943
+ return { output: formatError(`File not found: ${resolvedPath}`) };
944
+ }
945
+ const content = fs4.readFileSync(resolvedPath, "utf-8");
946
+ const intentRegex = /(?:intent|behavior)\s+(\w+)\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}/g;
947
+ let match;
948
+ let count = 0;
949
+ while ((match = intentRegex.exec(content)) !== null) {
950
+ const intent = session.parseIntent(match[0]);
951
+ if (intent) {
952
+ session.defineIntent(intent);
953
+ count++;
954
+ }
955
+ }
956
+ if (count === 0) {
957
+ return { output: formatWarning("No intents found in file") };
958
+ }
959
+ return {
960
+ output: formatSuccess(`Loaded ${count} intent(s) from ${filePath}`)
961
+ };
962
+ } catch (error) {
963
+ return {
964
+ output: formatError(`Failed to load: ${error instanceof Error ? error.message : String(error)}`)
965
+ };
966
+ }
967
+ }
968
+ },
969
+ {
970
+ name: "list",
971
+ aliases: ["ls"],
972
+ description: "List all defined intents",
973
+ usage: ":list",
974
+ handler: (args, session) => {
975
+ const intents = session.getAllIntents();
976
+ if (intents.length === 0) {
977
+ return { output: "No intents defined." };
978
+ }
979
+ const lines = [""];
980
+ for (const intent of intents) {
981
+ const preCount = intent.preconditions.length;
982
+ const postCount = intent.postconditions.length;
983
+ const invCount = intent.invariants.length;
984
+ const parts = [];
985
+ if (preCount > 0) parts.push(`${preCount} pre`);
986
+ if (postCount > 0) parts.push(`${postCount} post`);
987
+ if (invCount > 0) parts.push(`${invCount} invariant`);
988
+ const summary = parts.length > 0 ? ` (${parts.join(", ")})` : "";
989
+ lines.push(` ${colors.cyan}${intent.name}${colors.reset}${summary}`);
990
+ }
991
+ lines.push("");
992
+ return { output: lines.join("\n") };
993
+ }
994
+ },
995
+ {
996
+ name: "inspect",
997
+ aliases: ["i", "show"],
998
+ description: "Show full details of an intent",
999
+ usage: ":inspect <intent>",
1000
+ handler: (args, session) => {
1001
+ if (args.length === 0) {
1002
+ const summary = session.getSummary();
1003
+ const files = session.getLoadedFiles();
1004
+ const lines = [
1005
+ "",
1006
+ `${colors.bold}Session Summary${colors.reset}`,
1007
+ "",
1008
+ ` Intents: ${summary.intentCount}`,
1009
+ ` Variables: ${summary.variableCount}`,
1010
+ ` History: ${summary.historyCount} entries`
1011
+ ];
1012
+ if (files.length > 0) {
1013
+ lines.push("");
1014
+ lines.push(`${colors.bold}Loaded Files${colors.reset}`);
1015
+ for (const file of files) {
1016
+ lines.push(` ${file}`);
1017
+ }
1018
+ }
1019
+ lines.push("");
1020
+ return { output: lines.join("\n") };
1021
+ }
1022
+ const intentName = args[0];
1023
+ const intent = session.getIntent(intentName);
1024
+ if (!intent) {
1025
+ const available = session.getIntentNames().join(", ") || "(none)";
1026
+ return {
1027
+ output: formatError(`Unknown intent: ${intentName}
1028
+ Available: ${available}`)
1029
+ };
1030
+ }
1031
+ return { output: formatIntent(intent) };
1032
+ }
1033
+ },
1034
+ {
1035
+ name: "export",
1036
+ aliases: ["save"],
1037
+ description: "Export intents to a file",
1038
+ usage: ":export <file.isl>",
1039
+ handler: (args, session) => {
1040
+ if (args.length === 0) {
1041
+ return { output: "Usage: :export <file.isl>" };
1042
+ }
1043
+ const filePath = args[0];
1044
+ const fs4 = __require("fs");
1045
+ const path4 = __require("path");
1046
+ try {
1047
+ const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.resolve(process.cwd(), filePath);
1048
+ const intents = session.getAllIntents();
1049
+ if (intents.length === 0) {
1050
+ return { output: formatWarning("No intents to export") };
1051
+ }
1052
+ const lines = [];
1053
+ lines.push("// Exported ISL intents");
1054
+ lines.push(`// Generated at ${(/* @__PURE__ */ new Date()).toISOString()}`);
1055
+ lines.push("");
1056
+ for (const intent of intents) {
1057
+ lines.push(`intent ${intent.name} {`);
1058
+ for (const pre of intent.preconditions) {
1059
+ lines.push(` pre: ${pre.expression}`);
1060
+ }
1061
+ for (const post of intent.postconditions) {
1062
+ lines.push(` post: ${post.expression}`);
1063
+ }
1064
+ for (const inv of intent.invariants) {
1065
+ lines.push(` invariant: ${inv.expression}`);
1066
+ }
1067
+ lines.push("}");
1068
+ lines.push("");
1069
+ }
1070
+ fs4.writeFileSync(resolvedPath, lines.join("\n"));
1071
+ return { output: formatSuccess(`Exported ${intents.length} intent(s) to ${filePath}`) };
1072
+ } catch (error) {
1073
+ return {
1074
+ output: formatError(`Failed to export: ${error instanceof Error ? error.message : String(error)}`)
1075
+ };
1076
+ }
1077
+ }
1078
+ }
1079
+ ];
1080
+ function generateTypeScript(intent) {
1081
+ const lines = [
1082
+ `${colors.gray}// Generated TypeScript${colors.reset}`,
1083
+ `interface ${intent.name}Contract {`
1084
+ ];
1085
+ if (intent.preconditions.length > 0) {
1086
+ for (const pre of intent.preconditions) {
1087
+ const varName = extractVariableName(pre.expression);
1088
+ const type = inferType(pre.expression);
1089
+ lines.push(` pre: (${varName}: ${type}) => boolean;`);
1090
+ }
1091
+ }
1092
+ if (intent.postconditions.length > 0) {
1093
+ for (const post of intent.postconditions) {
1094
+ const varName = extractVariableName(post.expression);
1095
+ const type = inferType(post.expression);
1096
+ lines.push(` post: (${varName}: ${type}) => boolean;`);
1097
+ }
1098
+ }
1099
+ lines.push("}");
1100
+ return lines.join("\n");
1101
+ }
1102
+ function generateRust(intent) {
1103
+ const lines = [
1104
+ `${colors.gray}// Generated Rust${colors.reset}`,
1105
+ `pub trait ${intent.name}Contract {`
1106
+ ];
1107
+ if (intent.preconditions.length > 0) {
1108
+ for (const pre of intent.preconditions) {
1109
+ const varName = extractVariableName(pre.expression);
1110
+ const type = inferRustType(pre.expression);
1111
+ lines.push(` fn check_pre(&self, ${varName}: ${type}) -> bool;`);
1112
+ }
1113
+ }
1114
+ if (intent.postconditions.length > 0) {
1115
+ for (const post of intent.postconditions) {
1116
+ const varName = extractVariableName(post.expression);
1117
+ const type = inferRustType(post.expression);
1118
+ lines.push(` fn check_post(&self, ${varName}: ${type}) -> bool;`);
1119
+ }
1120
+ }
1121
+ lines.push("}");
1122
+ return lines.join("\n");
1123
+ }
1124
+ function generateGo(intent) {
1125
+ const lines = [
1126
+ `${colors.gray}// Generated Go${colors.reset}`,
1127
+ `type ${intent.name}Contract interface {`
1128
+ ];
1129
+ if (intent.preconditions.length > 0) {
1130
+ for (const pre of intent.preconditions) {
1131
+ const varName = extractVariableName(pre.expression);
1132
+ const type = inferGoType(pre.expression);
1133
+ lines.push(` CheckPre(${varName} ${type}) bool`);
1134
+ }
1135
+ }
1136
+ if (intent.postconditions.length > 0) {
1137
+ for (const post of intent.postconditions) {
1138
+ const varName = extractVariableName(post.expression);
1139
+ const type = inferGoType(post.expression);
1140
+ lines.push(` CheckPost(${varName} ${type}) bool`);
1141
+ }
1142
+ }
1143
+ lines.push("}");
1144
+ return lines.join("\n");
1145
+ }
1146
+ function generateOpenAPI(intent) {
1147
+ const lines = [
1148
+ `${colors.gray}# Generated OpenAPI${colors.reset}`,
1149
+ `openapi: 3.0.0`,
1150
+ `paths:`,
1151
+ ` /${intent.name.toLowerCase()}:`,
1152
+ ` post:`,
1153
+ ` summary: ${intent.name}`,
1154
+ ` requestBody:`,
1155
+ ` content:`,
1156
+ ` application/json:`,
1157
+ ` schema:`,
1158
+ ` type: object`
1159
+ ];
1160
+ if (intent.preconditions.length > 0) {
1161
+ lines.push(` # Preconditions:`);
1162
+ for (const pre of intent.preconditions) {
1163
+ lines.push(` # - ${pre.expression}`);
1164
+ }
1165
+ }
1166
+ lines.push(` responses:`);
1167
+ lines.push(` '200':`);
1168
+ lines.push(` description: Success`);
1169
+ if (intent.postconditions.length > 0) {
1170
+ lines.push(` # Postconditions:`);
1171
+ for (const post of intent.postconditions) {
1172
+ lines.push(` # - ${post.expression}`);
1173
+ }
1174
+ }
1175
+ return lines.join("\n");
1176
+ }
1177
+ function extractVariableName(expression) {
1178
+ const match = expression.match(/^(\w+)/);
1179
+ return match ? match[1] : "input";
1180
+ }
1181
+ function inferType(expression) {
1182
+ if (expression.includes(".length")) return "string";
1183
+ if (expression.includes(".startsWith")) return "string";
1184
+ if (expression.includes(".endsWith")) return "string";
1185
+ if (expression.includes(".includes")) return "string";
1186
+ if (expression.includes(" > ") || expression.includes(" < ")) return "number";
1187
+ return "unknown";
1188
+ }
1189
+ function inferRustType(expression) {
1190
+ if (expression.includes(".length") || expression.includes(".len()")) return "&str";
1191
+ if (expression.includes(".starts_with")) return "&str";
1192
+ if (expression.includes(" > ") || expression.includes(" < ")) return "i32";
1193
+ return "&str";
1194
+ }
1195
+ function inferGoType(expression) {
1196
+ if (expression.includes(".length") || expression.includes("len(")) return "string";
1197
+ if (expression.includes(" > ") || expression.includes(" < ")) return "int";
1198
+ return "string";
1199
+ }
1200
+ function highlightCondition(expression) {
1201
+ return expression.replace(
1202
+ /(\w+)\s*(>|<|>=|<=|==|!=)\s*(\d+|"[^"]*")/g,
1203
+ `${colors.blue}$1${colors.reset} ${colors.yellow}$2${colors.reset} ${colors.green}$3${colors.reset}`
1204
+ ).replace(/\b(true|false)\b/g, `${colors.magenta}$1${colors.reset}`).replace(/\.(length|startsWith|endsWith|includes)/g, `.${colors.cyan}$1${colors.reset}`);
1205
+ }
1206
+ function levenshteinDistance(a, b) {
1207
+ const matrix = [];
1208
+ for (let i = 0; i <= b.length; i++) {
1209
+ matrix[i] = [i];
1210
+ }
1211
+ for (let j = 0; j <= a.length; j++) {
1212
+ matrix[0][j] = j;
1213
+ }
1214
+ for (let i = 1; i <= b.length; i++) {
1215
+ for (let j = 1; j <= a.length; j++) {
1216
+ const cost = a[j - 1] === b[i - 1] ? 0 : 1;
1217
+ matrix[i][j] = Math.min(
1218
+ matrix[i - 1][j] + 1,
1219
+ matrix[i][j - 1] + 1,
1220
+ matrix[i - 1][j - 1] + cost
1221
+ );
1222
+ }
1223
+ }
1224
+ return matrix[b.length][a.length];
1225
+ }
1226
+ function findSimilarCommand(input, type) {
1227
+ const commands = type === "meta" ? metaCommands : islCommands;
1228
+ const names = commands.flatMap((c) => [c.name, ...c.aliases]);
1229
+ let bestMatch = null;
1230
+ let bestDistance = Infinity;
1231
+ for (const name of names) {
1232
+ const distance = levenshteinDistance(input.toLowerCase(), name.toLowerCase());
1233
+ if (distance < bestDistance && distance <= 2) {
1234
+ bestDistance = distance;
1235
+ bestMatch = name;
1236
+ }
1237
+ }
1238
+ return bestMatch;
1239
+ }
1240
+
1241
+ // src/completions.ts
1242
+ var KEYWORDS = [
1243
+ { text: "intent", type: "keyword", description: "Define an intent" },
1244
+ { text: "behavior", type: "keyword", description: "Define a behavior" },
1245
+ { text: "pre", type: "keyword", description: "Precondition" },
1246
+ { text: "post", type: "keyword", description: "Postcondition" },
1247
+ { text: "invariant", type: "keyword", description: "Invariant" },
1248
+ { text: "true", type: "keyword", description: "Boolean true" },
1249
+ { text: "false", type: "keyword", description: "Boolean false" },
1250
+ { text: "null", type: "keyword", description: "Null value" },
1251
+ { text: "and", type: "keyword", description: "Logical AND" },
1252
+ { text: "or", type: "keyword", description: "Logical OR" },
1253
+ { text: "not", type: "keyword", description: "Logical NOT" },
1254
+ { text: "implies", type: "keyword", description: "Logical implication" },
1255
+ { text: "forall", type: "keyword", description: "Universal quantifier" },
1256
+ { text: "exists", type: "keyword", description: "Existential quantifier" },
1257
+ { text: "in", type: "keyword", description: "Membership test" }
1258
+ ];
1259
+ var META_COMMANDS = metaCommands.map((cmd) => ({
1260
+ text: `.${cmd.name}`,
1261
+ type: "command",
1262
+ description: cmd.description
1263
+ }));
1264
+ var ISL_COMMANDS = islCommands.map((cmd) => ({
1265
+ text: `:${cmd.name}`,
1266
+ type: "command",
1267
+ description: cmd.description
1268
+ }));
1269
+ var COMMANDS = [...META_COMMANDS, ...ISL_COMMANDS];
1270
+ var GEN_TARGETS = [
1271
+ { text: "typescript", type: "keyword", description: "Generate TypeScript contract" },
1272
+ { text: "rust", type: "keyword", description: "Generate Rust contract" },
1273
+ { text: "go", type: "keyword", description: "Generate Go contract" },
1274
+ { text: "openapi", type: "keyword", description: "Generate OpenAPI schema" }
1275
+ ];
1276
+ var CompletionProvider = class {
1277
+ constructor(session) {
1278
+ this.session = session;
1279
+ }
1280
+ /**
1281
+ * Update the session reference
1282
+ */
1283
+ setSession(session) {
1284
+ this.session = session;
1285
+ }
1286
+ /**
1287
+ * Get completions for a line
1288
+ */
1289
+ complete(line) {
1290
+ const trimmed = line.trimStart();
1291
+ if (trimmed.startsWith(".")) {
1292
+ return this.completeMetaCommand(trimmed);
1293
+ }
1294
+ if (trimmed.startsWith(":")) {
1295
+ return this.completeISLCommand(trimmed);
1296
+ }
1297
+ return this.completeExpression(trimmed);
1298
+ }
1299
+ /**
1300
+ * Complete meta commands
1301
+ */
1302
+ completeMetaCommand(line) {
1303
+ const parts = line.slice(1).split(/\s+/);
1304
+ const cmdPart = parts[0] || "";
1305
+ if (parts.length === 1) {
1306
+ const matches = META_COMMANDS.filter(
1307
+ (c) => c.text.toLowerCase().startsWith(`.${cmdPart.toLowerCase()}`)
1308
+ );
1309
+ return [matches.length > 0 ? matches : META_COMMANDS, "." + cmdPart];
1310
+ }
1311
+ return [[], line];
1312
+ }
1313
+ /**
1314
+ * Complete ISL commands
1315
+ */
1316
+ completeISLCommand(line) {
1317
+ const parts = line.slice(1).split(/\s+/);
1318
+ const cmdPart = parts[0] || "";
1319
+ const args = parts.slice(1);
1320
+ if (parts.length === 1) {
1321
+ const matches = ISL_COMMANDS.filter(
1322
+ (c) => c.text.toLowerCase().startsWith(`:${cmdPart.toLowerCase()}`)
1323
+ );
1324
+ return [matches.length > 0 ? matches : ISL_COMMANDS, ":" + cmdPart];
1325
+ }
1326
+ const cmd = cmdPart.toLowerCase();
1327
+ switch (cmd) {
1328
+ case "gen":
1329
+ case "generate":
1330
+ case "g":
1331
+ return this.completeGenCommand(args);
1332
+ case "check":
1333
+ case "c":
1334
+ case "inspect":
1335
+ case "i":
1336
+ case "show":
1337
+ return this.completeIntentName(args[0] || "");
1338
+ case "load":
1339
+ case "l":
1340
+ case "export":
1341
+ case "save":
1342
+ return this.completeFilePath(args[0] || "");
1343
+ default:
1344
+ return [[], line];
1345
+ }
1346
+ }
1347
+ /**
1348
+ * Complete :gen command arguments
1349
+ */
1350
+ completeGenCommand(args) {
1351
+ if (args.length <= 1) {
1352
+ const partial = args[0] || "";
1353
+ const matches = GEN_TARGETS.filter(
1354
+ (t) => t.text.toLowerCase().startsWith(partial.toLowerCase())
1355
+ );
1356
+ return [matches.length > 0 ? matches : GEN_TARGETS, partial];
1357
+ }
1358
+ return this.completeIntentName(args[1] || "");
1359
+ }
1360
+ /**
1361
+ * Complete intent names
1362
+ */
1363
+ completeIntentName(partial) {
1364
+ const intents = this.session.getAllIntents();
1365
+ const items = intents.map((intent) => ({
1366
+ text: intent.name,
1367
+ type: "intent",
1368
+ description: `${intent.preconditions.length} pre, ${intent.postconditions.length} post`
1369
+ }));
1370
+ const matches = items.filter(
1371
+ (i) => i.text.toLowerCase().startsWith(partial.toLowerCase())
1372
+ );
1373
+ return [matches.length > 0 ? matches : items, partial];
1374
+ }
1375
+ /**
1376
+ * Complete file paths
1377
+ */
1378
+ completeFilePath(partial) {
1379
+ try {
1380
+ const dir = path.dirname(partial) || ".";
1381
+ const base = path.basename(partial);
1382
+ const resolvedDir = path.resolve(this.session.getConfig().cwd || process.cwd(), dir);
1383
+ if (!fs2.existsSync(resolvedDir)) {
1384
+ return [[], partial];
1385
+ }
1386
+ const entries = fs2.readdirSync(resolvedDir, { withFileTypes: true });
1387
+ const items = entries.filter((e) => {
1388
+ const name = e.name.toLowerCase();
1389
+ return name.startsWith(base.toLowerCase()) && (e.isDirectory() || name.endsWith(".isl"));
1390
+ }).map((e) => ({
1391
+ text: path.join(dir, e.name + (e.isDirectory() ? "/" : "")),
1392
+ type: "file",
1393
+ description: e.isDirectory() ? "Directory" : "ISL file"
1394
+ }));
1395
+ return [items, partial];
1396
+ } catch {
1397
+ return [[], partial];
1398
+ }
1399
+ }
1400
+ /**
1401
+ * Complete expressions
1402
+ */
1403
+ completeExpression(line) {
1404
+ const items = [...KEYWORDS];
1405
+ for (const intent of this.session.getAllIntents()) {
1406
+ items.push({
1407
+ text: intent.name,
1408
+ type: "intent",
1409
+ description: "Defined intent"
1410
+ });
1411
+ }
1412
+ for (const [name] of this.session.getAllVariables()) {
1413
+ items.push({
1414
+ text: name,
1415
+ type: "variable",
1416
+ description: "Variable"
1417
+ });
1418
+ }
1419
+ items.push({
1420
+ text: "_",
1421
+ type: "variable",
1422
+ description: "Last result"
1423
+ });
1424
+ const match = line.match(/[\w.]+$/);
1425
+ const partial = match ? match[0] : "";
1426
+ const matches = items.filter(
1427
+ (i) => i.text.toLowerCase().startsWith(partial.toLowerCase())
1428
+ );
1429
+ return [matches.length > 0 ? matches : items, partial];
1430
+ }
1431
+ /**
1432
+ * Get all available completions (for help)
1433
+ */
1434
+ getAllCompletions() {
1435
+ return {
1436
+ metaCommands: META_COMMANDS,
1437
+ islCommands: ISL_COMMANDS,
1438
+ keywords: KEYWORDS,
1439
+ intents: this.session.getAllIntents().map((i) => ({
1440
+ text: i.name,
1441
+ type: "intent",
1442
+ description: `${i.preconditions.length} pre, ${i.postconditions.length} post`
1443
+ }))
1444
+ };
1445
+ }
1446
+ };
1447
+ function createCompleter(provider) {
1448
+ return (line) => {
1449
+ const [items, partial] = provider.complete(line);
1450
+ const completions = items.map((i) => i.text);
1451
+ return [completions, partial];
1452
+ };
1453
+ }
1454
+
1455
+ // src/repl.ts
1456
+ var VERSION = "0.1.0";
1457
+ var PROMPT = `${colors.cyan}isl>${colors.reset} `;
1458
+ var CONTINUATION_PROMPT = `${colors.cyan}...>${colors.reset} `;
1459
+ var ISLREPL = class {
1460
+ session;
1461
+ history;
1462
+ completionProvider;
1463
+ rl = null;
1464
+ buffer = [];
1465
+ braceCount = 0;
1466
+ options;
1467
+ running = false;
1468
+ constructor(options = {}) {
1469
+ this.options = {
1470
+ colors: options.colors !== false,
1471
+ verbose: options.verbose ?? false,
1472
+ historyFile: options.historyFile
1473
+ };
1474
+ this.session = new Session({ colors: this.options.colors });
1475
+ this.history = new History({
1476
+ historyFile: this.options.historyFile
1477
+ });
1478
+ this.completionProvider = new CompletionProvider(this.session);
1479
+ }
1480
+ /**
1481
+ * Start the REPL
1482
+ */
1483
+ start() {
1484
+ if (this.running) return;
1485
+ this.running = true;
1486
+ this.history.load();
1487
+ this.rl = readline.createInterface({
1488
+ input: process.stdin,
1489
+ output: process.stdout,
1490
+ prompt: PROMPT,
1491
+ completer: createCompleter(this.completionProvider),
1492
+ terminal: true
1493
+ });
1494
+ this.printBanner();
1495
+ this.rl.prompt();
1496
+ this.rl.on("line", (line) => {
1497
+ this.handleLine(line);
1498
+ if (this.rl && this.running) {
1499
+ this.rl.setPrompt(this.braceCount > 0 ? CONTINUATION_PROMPT : PROMPT);
1500
+ this.rl.prompt();
1501
+ }
1502
+ });
1503
+ this.rl.on("close", () => {
1504
+ this.exit();
1505
+ });
1506
+ this.rl.on("SIGINT", () => {
1507
+ if (this.buffer.length > 0) {
1508
+ this.buffer = [];
1509
+ this.braceCount = 0;
1510
+ console.log("\n" + formatWarning("Input cancelled"));
1511
+ this.rl.setPrompt(PROMPT);
1512
+ this.rl.prompt();
1513
+ } else {
1514
+ console.log("\n" + formatWarning("Use .exit or :quit to exit"));
1515
+ this.rl.prompt();
1516
+ }
1517
+ });
1518
+ }
1519
+ /**
1520
+ * Print the welcome banner
1521
+ */
1522
+ printBanner() {
1523
+ const banner = `
1524
+ ${colors.cyan}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
1525
+ \u2551 \u2551
1526
+ \u2551 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2551
1527
+ \u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2551
1528
+ \u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2551
1529
+ \u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2551
1530
+ \u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2551
1531
+ \u2551 \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u2551
1532
+ \u2551 \u2551
1533
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${colors.reset}
1534
+
1535
+ ${colors.bold}ISL v${VERSION}${colors.reset} \u2014 Intent Specification Language
1536
+ Type ${colors.cyan}.help${colors.reset} for commands, ${colors.cyan}.exit${colors.reset} to quit
1537
+ `;
1538
+ console.log(banner);
1539
+ }
1540
+ /**
1541
+ * Handle a line of input
1542
+ */
1543
+ handleLine(line) {
1544
+ const trimmed = line.trim();
1545
+ if (!trimmed && this.buffer.length === 0) {
1546
+ return;
1547
+ }
1548
+ if (trimmed.startsWith(".") && this.buffer.length === 0) {
1549
+ this.handleMetaCommand(trimmed);
1550
+ return;
1551
+ }
1552
+ if (trimmed.startsWith(":") && this.buffer.length === 0) {
1553
+ this.handleISLCommand(trimmed);
1554
+ return;
1555
+ }
1556
+ this.braceCount += (line.match(/\{/g) || []).length;
1557
+ this.braceCount -= (line.match(/\}/g) || []).length;
1558
+ this.buffer.push(line);
1559
+ if (this.braceCount <= 0) {
1560
+ const code = this.buffer.join("\n");
1561
+ this.buffer = [];
1562
+ this.braceCount = 0;
1563
+ this.history.add(code);
1564
+ this.session.addToHistory(code);
1565
+ this.evaluate(code);
1566
+ }
1567
+ }
1568
+ /**
1569
+ * Handle a meta command (. prefix)
1570
+ */
1571
+ handleMetaCommand(input) {
1572
+ const parts = input.slice(1).split(/\s+/);
1573
+ const cmdName = parts[0]?.toLowerCase() || "";
1574
+ const args = parts.slice(1);
1575
+ const command = metaCommands.find(
1576
+ (c) => c.name === cmdName || c.aliases.includes(cmdName)
1577
+ );
1578
+ if (command) {
1579
+ this.history.add(input);
1580
+ const result = command.handler(args, this.session, this);
1581
+ if (result.output) {
1582
+ console.log(result.output);
1583
+ }
1584
+ if (result.exit) {
1585
+ this.exit();
1586
+ }
1587
+ } else {
1588
+ const suggestion = findSimilarCommand(cmdName, "meta");
1589
+ if (suggestion) {
1590
+ console.log(formatError(`Unknown command: .${cmdName}`));
1591
+ console.log(formatWarning(`Did you mean: .${suggestion}?`));
1592
+ } else {
1593
+ console.log(formatError(`Unknown command: .${cmdName}`));
1594
+ console.log(`Type ${colors.cyan}.help${colors.reset} for available commands`);
1595
+ }
1596
+ }
1597
+ }
1598
+ /**
1599
+ * Handle an ISL command (: prefix)
1600
+ */
1601
+ handleISLCommand(input) {
1602
+ const parts = input.slice(1).split(/\s+/);
1603
+ const cmdName = parts[0]?.toLowerCase() || "";
1604
+ const args = parts.slice(1);
1605
+ const command = islCommands.find(
1606
+ (c) => c.name === cmdName || c.aliases.includes(cmdName)
1607
+ );
1608
+ if (command) {
1609
+ this.history.add(input);
1610
+ const result = command.handler(args, this.session, this);
1611
+ if (result.output) {
1612
+ console.log(result.output);
1613
+ }
1614
+ } else {
1615
+ const suggestion = findSimilarCommand(cmdName, "isl");
1616
+ if (suggestion) {
1617
+ console.log(formatError(`Unknown command: :${cmdName}`));
1618
+ console.log(formatWarning(`Did you mean: :${suggestion}?`));
1619
+ } else {
1620
+ console.log(formatError(`Unknown command: :${cmdName}`));
1621
+ console.log(`Type ${colors.cyan}.help${colors.reset} for available commands`);
1622
+ }
1623
+ }
1624
+ }
1625
+ /**
1626
+ * Evaluate ISL code
1627
+ */
1628
+ evaluate(code) {
1629
+ try {
1630
+ const trimmed = code.trim();
1631
+ if (trimmed.startsWith("intent ")) {
1632
+ this.evaluateIntent(trimmed);
1633
+ return;
1634
+ }
1635
+ if (trimmed.startsWith("behavior ")) {
1636
+ this.evaluateIntent(trimmed);
1637
+ return;
1638
+ }
1639
+ console.log(formatWarning(`Cannot evaluate: ${trimmed.split("\n")[0]}...`));
1640
+ console.log(`Use ${colors.cyan}intent Name { ... }${colors.reset} to define an intent`);
1641
+ } catch (error) {
1642
+ this.printError(error);
1643
+ }
1644
+ }
1645
+ /**
1646
+ * Evaluate an intent definition
1647
+ */
1648
+ evaluateIntent(code) {
1649
+ const intent = this.session.parseIntent(code);
1650
+ if (intent) {
1651
+ this.session.defineIntent(intent);
1652
+ const preCount = intent.preconditions.length;
1653
+ const postCount = intent.postconditions.length;
1654
+ const invCount = intent.invariants.length;
1655
+ const parts = [];
1656
+ if (preCount > 0) parts.push(`${preCount} pre`);
1657
+ if (postCount > 0) parts.push(`${postCount} post`);
1658
+ if (invCount > 0) parts.push(`${invCount} invariant`);
1659
+ const summary = parts.length > 0 ? ` (${parts.join(", ")})` : "";
1660
+ console.log(formatSuccess(`Intent '${intent.name}' defined${summary}`));
1661
+ } else {
1662
+ const behaviorMatch = code.match(/^behavior\s+(\w+)\s*\{([\s\S]*)\}$/);
1663
+ if (behaviorMatch) {
1664
+ const name = behaviorMatch[1];
1665
+ const body = behaviorMatch[2];
1666
+ const intent2 = {
1667
+ name,
1668
+ preconditions: [],
1669
+ postconditions: [],
1670
+ invariants: [],
1671
+ scenarios: [],
1672
+ rawSource: code
1673
+ };
1674
+ const preSection = body.match(/pre(?:conditions)?\s*\{([^}]*)\}/s);
1675
+ if (preSection) {
1676
+ const conditions = preSection[1].trim().split("\n").map((l) => l.trim()).filter(Boolean);
1677
+ for (const cond of conditions) {
1678
+ const expr = cond.replace(/^-\s*/, "").trim();
1679
+ if (expr) {
1680
+ intent2.preconditions.push({ expression: expr });
1681
+ }
1682
+ }
1683
+ }
1684
+ const postSection = body.match(/post(?:conditions)?\s*\{([^}]*)\}/s);
1685
+ if (postSection) {
1686
+ const conditions = postSection[1].trim().split("\n").map((l) => l.trim()).filter(Boolean);
1687
+ for (const cond of conditions) {
1688
+ const expr = cond.replace(/^-\s*/, "").trim();
1689
+ if (expr) {
1690
+ intent2.postconditions.push({ expression: expr });
1691
+ }
1692
+ }
1693
+ }
1694
+ this.session.defineIntent(intent2);
1695
+ const preCount = intent2.preconditions.length;
1696
+ const postCount = intent2.postconditions.length;
1697
+ const parts = [];
1698
+ if (preCount > 0) parts.push(`${preCount} pre`);
1699
+ if (postCount > 0) parts.push(`${postCount} post`);
1700
+ const summary = parts.length > 0 ? ` (${parts.join(", ")})` : "";
1701
+ console.log(formatSuccess(`Intent '${intent2.name}' defined${summary}`));
1702
+ } else {
1703
+ this.printParseError(code, "Failed to parse intent definition");
1704
+ }
1705
+ }
1706
+ }
1707
+ /**
1708
+ * Print a parse error with location info
1709
+ */
1710
+ printParseError(code, message, line, column) {
1711
+ console.log(formatError(message));
1712
+ if (line !== void 0 && column !== void 0) {
1713
+ const lines = code.split("\n");
1714
+ const errorLine = lines[line - 1] || "";
1715
+ console.log(` ${colors.gray}${line} |${colors.reset} ${errorLine}`);
1716
+ console.log(` ${colors.gray}${" ".repeat(String(line).length)} |${colors.reset} ${" ".repeat(column - 1)}${colors.red}^${colors.reset}`);
1717
+ } else {
1718
+ const firstLine = code.split("\n")[0];
1719
+ if (firstLine) {
1720
+ console.log(` ${colors.gray}>${colors.reset} ${firstLine}`);
1721
+ }
1722
+ }
1723
+ }
1724
+ /**
1725
+ * Print an error
1726
+ */
1727
+ printError(error) {
1728
+ if (error instanceof Error) {
1729
+ console.log(formatError(error.message));
1730
+ if (this.options.verbose && error.stack) {
1731
+ console.log(colors.gray + error.stack + colors.reset);
1732
+ }
1733
+ } else {
1734
+ console.log(formatError(String(error)));
1735
+ }
1736
+ }
1737
+ /**
1738
+ * Exit the REPL
1739
+ */
1740
+ exit() {
1741
+ this.running = false;
1742
+ this.history.save();
1743
+ console.log(`
1744
+ ${colors.yellow}Goodbye!${colors.reset}`);
1745
+ if (this.rl) {
1746
+ this.rl.close();
1747
+ }
1748
+ process.exit(0);
1749
+ }
1750
+ /**
1751
+ * Get the session
1752
+ */
1753
+ getSession() {
1754
+ return this.session;
1755
+ }
1756
+ /**
1757
+ * Get history
1758
+ */
1759
+ getHistory() {
1760
+ return this.history;
1761
+ }
1762
+ /**
1763
+ * Execute a single command and return result (for testing)
1764
+ */
1765
+ async executeOnce(input) {
1766
+ const trimmed = input.trim();
1767
+ if (trimmed.startsWith(".")) {
1768
+ const parts = trimmed.slice(1).split(/\s+/);
1769
+ const cmdName = parts[0]?.toLowerCase() || "";
1770
+ const args = parts.slice(1);
1771
+ const command = metaCommands.find(
1772
+ (c) => c.name === cmdName || c.aliases.includes(cmdName)
1773
+ );
1774
+ if (command) {
1775
+ const result = command.handler(args, this.session, this);
1776
+ return { success: true, output: result.output };
1777
+ }
1778
+ return { success: false, error: `Unknown command: .${cmdName}` };
1779
+ }
1780
+ if (trimmed.startsWith(":")) {
1781
+ const parts = trimmed.slice(1).split(/\s+/);
1782
+ const cmdName = parts[0]?.toLowerCase() || "";
1783
+ const args = parts.slice(1);
1784
+ const command = islCommands.find(
1785
+ (c) => c.name === cmdName || c.aliases.includes(cmdName)
1786
+ );
1787
+ if (command) {
1788
+ const result = command.handler(args, this.session, this);
1789
+ return { success: true, output: result.output };
1790
+ }
1791
+ return { success: false, error: `Unknown command: :${cmdName}` };
1792
+ }
1793
+ if (trimmed.startsWith("intent ") || trimmed.startsWith("behavior ")) {
1794
+ const intent = this.session.parseIntent(trimmed);
1795
+ if (intent) {
1796
+ this.session.defineIntent(intent);
1797
+ return { success: true, output: `Intent '${intent.name}' defined` };
1798
+ }
1799
+ return { success: false, error: "Failed to parse intent" };
1800
+ }
1801
+ return { success: false, error: "Unknown input" };
1802
+ }
1803
+ };
1804
+ function startREPL(options) {
1805
+ const repl = new ISLREPL(options);
1806
+ repl.start();
1807
+ return repl;
1808
+ }
1809
+
1810
+ export { COMMANDS, CompletionProvider, History, ISLREPL, ISL_COMMANDS, KEYWORDS, META_COMMANDS, MemoryHistory, Session, colors, createCompleter, createSession, drawBox, findSimilarCommand, formatCondition, formatError, formatInfo, formatIntent, formatParseError, formatSuccess, formatTable, formatTypeError, formatValue, formatWarning, highlightExpression, highlightISL, islCommands, metaCommands, startREPL, stripColors, wrapText };
1811
+ //# sourceMappingURL=index.js.map
1812
+ //# sourceMappingURL=index.js.map