dirac-lang 0.1.23 → 0.1.25

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 (226) hide show
  1. package/dist/{chunk-APWJJXNI.js → chunk-7OUYWIZV.js} +55 -14
  2. package/dist/{chunk-RGS2XK6T.js → chunk-OUMUIBK3.js} +1 -1
  3. package/dist/cli.js +15 -3
  4. package/dist/index.js +2 -2
  5. package/dist/{interpreter-UZDVASAW.js → interpreter-MTIIHIIQ.js} +1 -1
  6. package/dist/test-runner.js +1 -1
  7. package/lib/index.di +9 -0
  8. package/package.json +13 -1
  9. package/.env.example +0 -8
  10. package/COMMUNITY.md +0 -465
  11. package/CONDITIONAL-TAGS.md +0 -172
  12. package/EXCEPTION-HANDLING.md +0 -156
  13. package/LIBRARIES.md +0 -172
  14. package/LLM-VALIDATION.md +0 -128
  15. package/NAMESPACES.md +0 -366
  16. package/PROMOTION.md +0 -257
  17. package/QUICKSTART-LIBRARY.md +0 -93
  18. package/TEST-COVERAGE.md +0 -113
  19. package/TESTING.md +0 -162
  20. package/config.test.yml +0 -5
  21. package/dirac-http/examples/demo.di +0 -9
  22. package/dirac-http/lib/index.di +0 -12
  23. package/examples/add-demo.di +0 -74
  24. package/examples/add.bk +0 -11
  25. package/examples/advanced-math-demo.di +0 -53
  26. package/examples/calculator.di +0 -32
  27. package/examples/compact-test.di +0 -6
  28. package/examples/comprehensive.bk +0 -29
  29. package/examples/defvar-variable-demo.di +0 -18
  30. package/examples/direct-call.di +0 -17
  31. package/examples/disk-analysis.di +0 -16
  32. package/examples/exception-demo.di +0 -82
  33. package/examples/executable-hello.di +0 -7
  34. package/examples/execute-demo.di +0 -38
  35. package/examples/file-manager.di +0 -77
  36. package/examples/file-stats.di +0 -18
  37. package/examples/hello.bk +0 -1
  38. package/examples/hello.di +0 -5
  39. package/examples/if-comparison.di +0 -91
  40. package/examples/if-cstyle-test.di +0 -149
  41. package/examples/if-vs-testif.di +0 -56
  42. package/examples/import-demo.di +0 -31
  43. package/examples/inline-test.bk +0 -7
  44. package/examples/llm-agent.di +0 -32
  45. package/examples/llm-basic.di +0 -12
  46. package/examples/llm-command-more.di +0 -6
  47. package/examples/llm-command-no-exec.di +0 -13
  48. package/examples/llm-command.di +0 -6
  49. package/examples/llm-complex.di +0 -141
  50. package/examples/llm-feedback-debug.di +0 -30
  51. package/examples/llm-feedback-demo.di +0 -19
  52. package/examples/llm-feedback-math.di +0 -22
  53. package/examples/llm-feedback-simple.di +0 -16
  54. package/examples/llm-feedback-sub.di +0 -22
  55. package/examples/llm-no-feedback.di +0 -10
  56. package/examples/llm-recursive.di +0 -31
  57. package/examples/llm-reflection-test.di +0 -19
  58. package/examples/llm-simple-test.di +0 -12
  59. package/examples/llm-subs.di +0 -132
  60. package/examples/llm-use-subs.di +0 -6
  61. package/examples/llm-validate-test.di +0 -18
  62. package/examples/loop.di +0 -12
  63. package/examples/math-test.di +0 -22
  64. package/examples/minimal-test.di +0 -13
  65. package/examples/mongodb-context-test.di +0 -27
  66. package/examples/mongodb-count-events.di +0 -8
  67. package/examples/mongodb-import-demo.di +0 -25
  68. package/examples/mongodb-simple-test.di +0 -18
  69. package/examples/nl-agent.di +0 -47
  70. package/examples/parameters-demo.di +0 -68
  71. package/examples/params-meta-test.di +0 -17
  72. package/examples/params-test.di +0 -10
  73. package/examples/recipe-chain.di +0 -38
  74. package/examples/recursive-llm.di +0 -44
  75. package/examples/sample-library/README.md +0 -152
  76. package/examples/sample-library/examples/demo.di +0 -34
  77. package/examples/sample-library/lib/index.di +0 -65
  78. package/examples/sample-library/package.json +0 -31
  79. package/examples/scope-test-nested.di +0 -60
  80. package/examples/scope-test.di +0 -55
  81. package/examples/seamless.di +0 -45
  82. package/examples/shell-test.bk +0 -10
  83. package/examples/simple-import.di +0 -13
  84. package/examples/simple-recursive.di +0 -26
  85. package/examples/story-builder.di +0 -45
  86. package/examples/subroutine.di +0 -23
  87. package/examples/system-llm.di +0 -21
  88. package/examples/system-simple.di +0 -3
  89. package/examples/system-test.di +0 -8
  90. package/examples/tag-check-test.di +0 -139
  91. package/examples/task-assistant.di +0 -27
  92. package/examples/test-if-demo.di +0 -110
  93. package/examples/test-parameters.di +0 -50
  94. package/examples/try-catch-test.di +0 -118
  95. package/examples/two-styles.di +0 -28
  96. package/examples/var-debug.di +0 -6
  97. package/examples/var-inline.di +0 -4
  98. package/examples/var-test2.di +0 -6
  99. package/examples/variable-replace.di +0 -25
  100. package/examples/variable-simple.di +0 -16
  101. package/examples/variable-test.di +0 -22
  102. package/examples/whitespace-test.di +0 -24
  103. package/filePath +0 -1
  104. package/greeting.txt +0 -1
  105. package/src/cli.ts +0 -140
  106. package/src/index.ts +0 -33
  107. package/src/llm/ollama.ts +0 -58
  108. package/src/runtime/braket-parser.ts +0 -234
  109. package/src/runtime/interpreter.ts +0 -203
  110. package/src/runtime/parser.ts +0 -155
  111. package/src/runtime/session.ts +0 -325
  112. package/src/tags/assign.ts +0 -37
  113. package/src/tags/attr.ts +0 -64
  114. package/src/tags/available-subroutines.ts +0 -70
  115. package/src/tags/call.ts +0 -259
  116. package/src/tags/catch.ts +0 -24
  117. package/src/tags/defvar.ts +0 -115
  118. package/src/tags/environment.ts +0 -21
  119. package/src/tags/eval.ts +0 -71
  120. package/src/tags/exception.ts +0 -20
  121. package/src/tags/execute.ts +0 -52
  122. package/src/tags/expr.ts +0 -128
  123. package/src/tags/foreach.ts +0 -170
  124. package/src/tags/if.ts +0 -191
  125. package/src/tags/import.ts +0 -66
  126. package/src/tags/index.ts +0 -41
  127. package/src/tags/input.ts +0 -182
  128. package/src/tags/llm.ts +0 -415
  129. package/src/tags/loop.ts +0 -43
  130. package/src/tags/mongodb.ts +0 -70
  131. package/src/tags/output.ts +0 -53
  132. package/src/tags/parameters.ts +0 -81
  133. package/src/tags/require_module.ts +0 -19
  134. package/src/tags/subroutine.ts +0 -75
  135. package/src/tags/system.ts +0 -93
  136. package/src/tags/tag-check.ts +0 -176
  137. package/src/tags/test-if.ts +0 -112
  138. package/src/tags/throw.ts +0 -26
  139. package/src/tags/try.ts +0 -19
  140. package/src/tags/variable.ts +0 -25
  141. package/src/test-runner.ts +0 -300
  142. package/src/types/index.ts +0 -128
  143. package/src/utils/llm-adapter.ts +0 -113
  144. package/src/utils/tag-validator.ts +0 -231
  145. package/test-available-extends.di +0 -28
  146. package/test-available-simple.di +0 -12
  147. package/test-available-subroutines.di +0 -16
  148. package/test-call.di +0 -9
  149. package/test-extend-basic.di +0 -17
  150. package/test-extend-chain.di +0 -26
  151. package/test-extend-debug.di +0 -17
  152. package/test-extend-debug2.di +0 -15
  153. package/test-extend-person.di +0 -17
  154. package/test-extend-simple.di +0 -11
  155. package/test-extend-zhi.di +0 -23
  156. package/test-extend.di +0 -19
  157. package/test-extend2.di +0 -26
  158. package/test-extend3-fixed.di +0 -23
  159. package/test-extend3-trouble.di +0 -23
  160. package/test-extend3.di +0 -21
  161. package/test-factorial.di +0 -19
  162. package/test-input-debug.di +0 -19
  163. package/test-nested-debug.di +0 -7
  164. package/test-nested-debug2.di +0 -8
  165. package/test-no-extend.di +0 -16
  166. package/test-simple-call.di +0 -7
  167. package/test-simple.di +0 -6
  168. package/tests/README.md +0 -69
  169. package/tests/assign-basic.test.di +0 -7
  170. package/tests/assign-from-eval.test.di +0 -7
  171. package/tests/available-subroutines-foreach.test.di +0 -32
  172. package/tests/basic-output.test.di +0 -5
  173. package/tests/call-basic.test.di +0 -11
  174. package/tests/call-with-output.test.di +0 -10
  175. package/tests/comments-before-content.test.di +0 -6
  176. package/tests/defvar-multiple.test.di +0 -8
  177. package/tests/environment-basic.test.di +0 -22
  178. package/tests/environment-nonexistent.test.di +0 -5
  179. package/tests/environment-with-defvar.test.di +0 -15
  180. package/tests/eval-basic.test.di +0 -6
  181. package/tests/eval-with-variables.test.di +0 -8
  182. package/tests/exception-basic.test.di +0 -10
  183. package/tests/expr-basic.test.di +0 -11
  184. package/tests/extend-basic.test.di +0 -19
  185. package/tests/extend-inheritance-chain.test.di +0 -26
  186. package/tests/extend-multiple-nested.test.di +0 -24
  187. package/tests/extend-self.test.di +0 -19
  188. package/tests/extend-with-parameters.test.di +0 -14
  189. package/tests/generate-dirac.test.di +0 -22
  190. package/tests/if-conditional.test.di +0 -17
  191. package/tests/if-else.test.di +0 -11
  192. package/tests/if-with-variables.test.di +0 -8
  193. package/tests/import-basic.test.di +0 -6
  194. package/tests/input-file-all.test.di +0 -5
  195. package/tests/input-file-line.test.di +0 -15
  196. package/tests/input-file-loop.test.di +0 -12
  197. package/tests/input-stdin-all.test.di +0 -8
  198. package/tests/input-stdin-all.txt +0 -1
  199. package/tests/llm-validate.test.di +0 -17
  200. package/tests/loop-basic.test.di +0 -9
  201. package/tests/loop-nested.test.di +0 -10
  202. package/tests/loop-with-eval.test.di +0 -8
  203. package/tests/no-root-element.test.di +0 -6
  204. package/tests/output-file.test.di +0 -19
  205. package/tests/output-multiple.test.di +0 -9
  206. package/tests/parameters-basic.test.di +0 -6
  207. package/tests/require-module-basic.test.di +0 -7
  208. package/tests/subroutine-basic.test.di +0 -9
  209. package/tests/subroutine-multiple-params.test.di +0 -10
  210. package/tests/subroutine-nested-calls.test.di +0 -32
  211. package/tests/subroutine-sequential-calls.test.di +0 -36
  212. package/tests/system-background.test.di +0 -39
  213. package/tests/system-basic.test.di +0 -5
  214. package/tests/tag-check.test.di +0 -27
  215. package/tests/test-if-basic.test.di +0 -8
  216. package/tests/test-input.txt +0 -3
  217. package/tests/try-catch-basic.test.di +0 -10
  218. package/tests/try-catch-eval-error.test.di +0 -10
  219. package/tests/variable-basic.test.di +0 -6
  220. package/tests/variable-interpolation.test.di +0 -7
  221. package/tools/create-library.sh +0 -175
  222. package/tsconfig.json +0 -19
  223. /package/{examples/lib → lib}/advanced-math.di +0 -0
  224. /package/{examples/lib → lib}/fileops.di +0 -0
  225. /package/{examples/lib → lib}/math.di +0 -0
  226. /package/{examples/lib → lib}/mongodb.di +0 -0
package/src/tags/throw.ts DELETED
@@ -1,26 +0,0 @@
1
- /**
2
- * <throw> tag - throws an exception
3
- * Maps to mask_throw_integrate in MASK
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { throwException } from '../runtime/session.js';
8
-
9
- export async function executeThrow(session: DiracSession, element: DiracElement): Promise<void> {
10
- // Get exception name from 'name' attribute (default to "exception")
11
- const exceptionName = element.attributes?.name || 'exception';
12
-
13
- // Process children to build exception content
14
- const { integrateChildren } = await import('../runtime/interpreter.js');
15
-
16
- // Create a wrapper element to capture the processed content
17
- const exceptionDom: DiracElement = {
18
- tag: 'exception-content',
19
- attributes: { name: exceptionName },
20
- children: element.children,
21
- text: element.text,
22
- };
23
-
24
- // Throw the exception (add to exception stack)
25
- throwException(session, exceptionName, exceptionDom);
26
- }
package/src/tags/try.ts DELETED
@@ -1,19 +0,0 @@
1
- /**
2
- * <try> tag - establishes exception boundary
3
- * Maps to mask_try_integrate in MASK
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { setExceptionBoundary, unsetExceptionBoundary } from '../runtime/session.js';
8
-
9
- export async function executeTry(session: DiracSession, element: DiracElement): Promise<void> {
10
- // Set exception boundary (mark the start of try block)
11
- setExceptionBoundary(session);
12
-
13
- // Execute children (the try block content)
14
- const { integrateChildren } = await import('../runtime/interpreter.js');
15
- await integrateChildren(session, element);
16
-
17
- // Unset boundary after execution
18
- unsetExceptionBoundary(session);
19
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * <variable> tag - retrieve variable value
3
- * Outputs the stored variable content (text or tags)
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { getVariable, emit } from '../runtime/session.js';
8
-
9
- export function executeVariable(session: DiracSession, element: DiracElement): void {
10
- const name = element.attributes.name;
11
- if (!name) {
12
- // Debug: print the full element for diagnosis
13
- console.error('[VariableTagError] <variable> tag missing name attribute:', JSON.stringify(element));
14
- throw new Error('<variable> requires name attribute');
15
- }
16
- const value = getVariable(session, name);
17
- if (value === undefined) {
18
- if (session.debug) {
19
- console.error(`[Warning] Variable '${name}' is undefined`);
20
- }
21
- return;
22
- }
23
- // Output the variable value
24
- emit(session, String(value));
25
- }
@@ -1,300 +0,0 @@
1
- /**
2
- * Simple test runner for Dirac
3
- * Tests are defined as .di files with expected output in comments
4
- */
5
-
6
- import fs from 'fs';
7
- import path from 'path';
8
- import { DiracParser } from './runtime/parser.js';
9
- import { createSession, getOutput } from './runtime/session.js';
10
- import { integrate } from './runtime/interpreter.js';
11
- import yaml from 'js-yaml';
12
-
13
- interface TestCase {
14
- name: string;
15
- file: string;
16
- expectedOutput?: string;
17
- expectedError?: string;
18
- config?: any;
19
- }
20
-
21
- interface TestResult {
22
- name: string;
23
- passed: boolean;
24
- error?: string;
25
- actualOutput?: string;
26
- expectedOutput?: string;
27
- }
28
-
29
- export class TestRunner {
30
- private testDir: string;
31
- private config: any;
32
-
33
- constructor(testDir: string = 'tests', configPath?: string) {
34
- this.testDir = testDir;
35
-
36
- // For tests, always use ollama as the default provider (no API keys needed)
37
- // Unless a specific test config is provided
38
- if (configPath && fs.existsSync(configPath)) {
39
- this.config = yaml.load(fs.readFileSync(configPath, 'utf8')) || {};
40
- } else {
41
- this.config = { llmProvider: 'ollama', llmModel: 'llama2' };
42
- }
43
- }
44
-
45
- /**
46
- * Parse test metadata from comments in .di file
47
- * Format:
48
- * <!-- TEST: test_name -->
49
- * <!-- EXPECT: expected output -->
50
- * <!-- EXPECT_ERROR: expected error message -->
51
- */
52
- private parseTestMetadata(content: string): { name?: string; expected?: string; expectError?: string } {
53
- const nameMatch = content.match(/<!--\s*TEST:\s*(.+?)\s*-->/);
54
- const expectMatch = content.match(/<!--\s*EXPECT:\s*(.+?)\s*-->/s);
55
- const errorMatch = content.match(/<!--\s*EXPECT_ERROR:\s*(.+?)\s*-->/s);
56
-
57
- return {
58
- name: nameMatch?.[1],
59
- expected: expectMatch?.[1]?.trim(),
60
- expectError: errorMatch?.[1]?.trim(),
61
- };
62
- }
63
-
64
- /**
65
- * Run a single test file
66
- */
67
- async runTest(filePath: string): Promise<TestResult> {
68
- const content = fs.readFileSync(filePath, 'utf-8');
69
- const metadata = this.parseTestMetadata(content);
70
- const testName = metadata.name || path.basename(filePath);
71
-
72
- // Remove test comments before execution
73
- const cleanContent = content
74
- .replace(/<!--\s*TEST:.*?-->/gs, '')
75
- .replace(/<!--\s*EXPECT:.*?-->/gs, '')
76
- .replace(/<!--\s*EXPECT_ERROR:.*?-->/gs, '');
77
-
78
- const result: TestResult = {
79
- name: testName,
80
- passed: false,
81
- };
82
-
83
- try {
84
- // Check if there's a stdin input file for this test
85
- const stdinFile = filePath.replace('.test.di', '.txt');
86
- let stdinData: string | undefined;
87
- if (fs.existsSync(stdinFile)) {
88
- stdinData = fs.readFileSync(stdinFile, 'utf-8');
89
- }
90
-
91
- // If stdin data exists, we need to mock stdin
92
- // Since we can't replace process.stdin directly, we'll use a workaround:
93
- // temporarily store data in a place the input tag can access it
94
- if (stdinData !== undefined) {
95
- // Save original methods
96
- const originalOn = process.stdin.on.bind(process.stdin);
97
- const originalResume = process.stdin.resume.bind(process.stdin);
98
- const originalRemoveAllListeners = process.stdin.removeAllListeners.bind(process.stdin);
99
- const originalRemoveListener = process.stdin.removeListener.bind(process.stdin);
100
-
101
- // Mock stdin methods
102
- const listeners: { [key: string]: Function[] } = {};
103
-
104
- (process.stdin as any).on = function(event: string, callback: Function) {
105
- if (!listeners[event]) listeners[event] = [];
106
- listeners[event].push(callback);
107
- return this;
108
- };
109
-
110
- (process.stdin as any).removeAllListeners = function(event?: string) {
111
- if (event) {
112
- delete listeners[event];
113
- } else {
114
- Object.keys(listeners).forEach(k => delete listeners[k]);
115
- }
116
- return this;
117
- };
118
-
119
- (process.stdin as any).removeListener = function(event: string, callback: Function) {
120
- if (listeners[event]) {
121
- listeners[event] = listeners[event].filter(fn => fn !== callback);
122
- }
123
- return this;
124
- };
125
-
126
- (process.stdin as any).resume = function() {
127
- // Simulate data event
128
- setImmediate(() => {
129
- if (listeners['data']) {
130
- listeners['data'].forEach(fn => fn(Buffer.from(stdinData!, 'utf-8')));
131
- }
132
- // Simulate end event
133
- setImmediate(() => {
134
- if (listeners['end']) {
135
- listeners['end'].forEach(fn => fn());
136
- }
137
- });
138
- });
139
- return this;
140
- };
141
-
142
- try {
143
- const parser = new DiracParser();
144
- const ast = parser.parse(cleanContent);
145
- const session = createSession({ ...this.config, filePath });
146
- await integrate(session, ast);
147
- const output = getOutput(session);
148
- result.actualOutput = output;
149
- } finally {
150
- // Restore original methods
151
- (process.stdin as any).on = originalOn;
152
- (process.stdin as any).resume = originalResume;
153
- (process.stdin as any).removeAllListeners = originalRemoveAllListeners;
154
- (process.stdin as any).removeListener = originalRemoveListener;
155
- }
156
- } else {
157
- // Normal test without stdin
158
- const parser = new DiracParser();
159
- const ast = parser.parse(cleanContent);
160
- const session = createSession({ ...this.config, filePath });
161
- await integrate(session, ast);
162
- const output = getOutput(session);
163
- result.actualOutput = output;
164
- }
165
-
166
- if (metadata.expectError) {
167
- // Expected an error but got success
168
- result.passed = false;
169
- result.error = `Expected error but test succeeded. Output: ${result.actualOutput}`;
170
- } else if (metadata.expected !== undefined) {
171
- // Check if output matches expected
172
- // Normalize whitespace for comparison (collapse multiple spaces/newlines)
173
- const normalizedActual = result.actualOutput!.replace(/\s+/g, ' ').trim();
174
- const normalizedExpected = metadata.expected.replace(/\s+/g, ' ').trim();
175
-
176
- if (normalizedActual === normalizedExpected) {
177
- result.passed = true;
178
- } else {
179
- result.passed = false;
180
- result.error = `Output mismatch`;
181
- result.expectedOutput = normalizedExpected;
182
- result.actualOutput = normalizedActual;
183
- }
184
- } else {
185
- // No expected output specified, just check it runs without error
186
- result.passed = true;
187
- }
188
- } catch (error) {
189
- const errorMessage = error instanceof Error ? error.message : String(error);
190
-
191
- if (metadata.expectError) {
192
- // Check if error matches expected
193
- if (errorMessage.includes(metadata.expectError)) {
194
- result.passed = true;
195
- } else {
196
- result.passed = false;
197
- result.error = `Error mismatch. Expected: "${metadata.expectError}", Got: "${errorMessage}"`;
198
- }
199
- } else {
200
- // Unexpected error
201
- result.passed = false;
202
- result.error = errorMessage;
203
- }
204
- }
205
-
206
- return result;
207
- }
208
-
209
- /**
210
- * Run all tests in the test directory
211
- */
212
- async runAll(pattern: string = '*.test.di'): Promise<TestResult[]> {
213
- const testFiles = this.findTestFiles(this.testDir, pattern);
214
- const results: TestResult[] = [];
215
-
216
- console.log(`Running ${testFiles.length} tests...\n`);
217
-
218
- for (const file of testFiles) {
219
- const result = await this.runTest(file);
220
- results.push(result);
221
-
222
- // Print result immediately
223
- if (result.passed) {
224
- console.log(`✓ ${result.name}`);
225
- } else {
226
- console.log(`✗ ${result.name}`);
227
- if (result.error) {
228
- console.log(` Error: ${result.error}`);
229
- }
230
- if (result.expectedOutput !== undefined && result.actualOutput !== undefined) {
231
- console.log(` Expected: ${JSON.stringify(result.expectedOutput)}`);
232
- console.log(` Actual: ${JSON.stringify(result.actualOutput)}`);
233
- }
234
- }
235
- }
236
-
237
- return results;
238
- }
239
-
240
- /**
241
- * Find test files matching pattern
242
- */
243
- private findTestFiles(dir: string, pattern: string): string[] {
244
- if (!fs.existsSync(dir)) {
245
- return [];
246
- }
247
-
248
- const files: string[] = [];
249
- const entries = fs.readdirSync(dir, { withFileTypes: true });
250
-
251
- for (const entry of entries) {
252
- const fullPath = path.join(dir, entry.name);
253
-
254
- if (entry.isDirectory()) {
255
- files.push(...this.findTestFiles(fullPath, pattern));
256
- } else if (entry.isFile() && entry.name.endsWith('.test.di')) {
257
- files.push(fullPath);
258
- }
259
- }
260
-
261
- return files;
262
- }
263
-
264
- /**
265
- * Print summary of test results
266
- */
267
- printSummary(results: TestResult[]): void {
268
- const passed = results.filter(r => r.passed).length;
269
- const failed = results.filter(r => !r.passed).length;
270
-
271
- console.log('\n' + '='.repeat(50));
272
- console.log(`Tests: ${passed} passed, ${failed} failed, ${results.length} total`);
273
-
274
- if (failed > 0) {
275
- console.log('\nFailed tests:');
276
- results.filter(r => !r.passed).forEach(r => {
277
- console.log(` - ${r.name}`);
278
- });
279
- }
280
-
281
- console.log('='.repeat(50));
282
- }
283
- }
284
-
285
- // CLI interface
286
- if (import.meta.url === `file://${process.argv[1]}`) {
287
- const testDir = process.argv[2] || 'tests';
288
- const runner = new TestRunner(testDir);
289
-
290
- runner.runAll().then(results => {
291
- runner.printSummary(results);
292
-
293
- // Exit with error code if any tests failed
294
- const failed = results.filter(r => !r.passed).length;
295
- process.exit(failed > 0 ? 1 : 0);
296
- }).catch(error => {
297
- console.error('Test runner error:', error);
298
- process.exit(1);
299
- });
300
- }
@@ -1,128 +0,0 @@
1
- /**
2
- * Core types for Dirac interpreter
3
- * Directly based on MASK C implementation
4
- */
5
-
6
- export interface DiracElement {
7
- tag: string;
8
- attributes: Record<string, string>;
9
- children: DiracElement[];
10
- text?: string;
11
- }
12
-
13
- /**
14
- * Variable info - maps to VarInfo in MASK
15
- */
16
- export interface Variable {
17
- name: string;
18
- value: any;
19
- visible: boolean;
20
- boundary: number; // scope boundary marker
21
- passby: 'value' | 'ref';
22
- refName?: string; // for pass-by-reference
23
- }
24
-
25
- /**
26
- * Parameter metadata for introspection
27
- */
28
- export interface ParameterMetadata {
29
- name: string;
30
- type?: string;
31
- required?: boolean;
32
- description?: string;
33
- enum?: string[];
34
- example?: string;
35
- }
36
-
37
- /**
38
- * Exception info - maps to Exception in MASK
39
- */
40
- export interface Exception {
41
- name: string;
42
- dom: DiracElement; // The exception content as a DOM element
43
- isBoundary: number; // Boundary marker for try/catch scope
44
- }
45
-
46
- /**
47
- * Current exception container - maps to CurrentException in MASK
48
- */
49
- export interface CurrentException {
50
- size: number;
51
- exceptions: DiracElement[]; // List of caught exception DOM elements
52
- }
53
-
54
- /**
55
- * Subroutine info - maps to Subroutine in MASK
56
- */
57
- export interface Subroutine {
58
- name: string;
59
- element: DiracElement;
60
- boundary: number; // scope boundary marker
61
- extends?: string; // parent subroutine
62
- // Metadata for reflection/introspection
63
- description?: string;
64
- parameters?: ParameterMetadata[];
65
- meta?: Record<string, string>;
66
- }
67
-
68
- /**
69
- * Execution context - maps to MaskSession in MASK
70
- */
71
- export interface DiracSession {
72
- // Variable stack (all variables are on stack)
73
- variables: Variable[];
74
-
75
- // Subroutine registry
76
- subroutines: Subroutine[];
77
-
78
- // Scope boundaries (for cleanup)
79
- varBoundary: number;
80
- subBoundary: number;
81
-
82
- // Parameter stack (for subroutine calls)
83
- parameterStack: DiracElement[][];
84
-
85
- // Exception handling (for try/catch/throw)
86
- exceptions: Exception[]; // Exception stack
87
- currentException: CurrentException; // Currently caught exceptions
88
-
89
- // Output buffer
90
- output: string[];
91
-
92
- // LLM client
93
- llmClient?: any;
94
-
95
- // Execution limits
96
- limits: {
97
- maxLLMCalls: number;
98
- currentLLMCalls: number;
99
- maxDepth: number;
100
- currentDepth: number;
101
- };
102
-
103
- // Control flow
104
- isReturn: boolean;
105
- isBreak: boolean;
106
-
107
- // Extend mechanism
108
- skipSubroutineRegistration: boolean;
109
- currentSubroutineName?: string; // Track currently executing subroutine for available-subroutines
110
-
111
- // Debugging
112
- debug: boolean;
113
-
114
- // Import tracking
115
- currentFile?: string;
116
- importedFiles?: Set<string>;
117
- }
118
-
119
- export interface DiracConfig {
120
- apiKey?: string;
121
- model?: string;
122
- debug?: boolean;
123
- maxLLMCalls?: number;
124
- maxDepth?: number;
125
- filePath?: string; // Current file path for imports
126
- llmProvider?: string;
127
- llmModel?: string;
128
- }
@@ -1,113 +0,0 @@
1
- /**
2
- * LLM Adapter - Auto-generate prompts and JSON→XML converters
3
- * from Dirac subroutine definitions
4
- */
5
-
6
- import type { DiracSession } from '../types/index.js';
7
- import { getAvailableSubroutines } from '../runtime/session.js';
8
-
9
- export interface LLMPromptGenerator {
10
- generatePrompt(userInput: string): string;
11
- intentToXML(intent: any): string | null;
12
- }
13
-
14
- /**
15
- * Create LLM adapter from session's registered subroutines
16
- */
17
- export function createLLMAdapter(session: DiracSession): LLMPromptGenerator {
18
- const subroutines = getAvailableSubroutines(session);
19
-
20
- // Build JSON schema from subroutines
21
- const actions = subroutines.map(s => `"${s.name}"`).join('|');
22
-
23
- // Build examples
24
- const examples = subroutines.slice(0, 3).map(sub => {
25
- if (!sub.parameters || sub.parameters.length === 0) {
26
- return `"${sub.name}" → {"action":"${sub.name}","params":{}}`;
27
- }
28
-
29
- const firstParam = sub.parameters[0];
30
- const exampleValue = firstParam.enum?.[0] || 'value';
31
- return `"call ${sub.name}" → {"action":"${sub.name}","params":{"${firstParam.name}":"${exampleValue}"}}`;
32
- }).join('\n');
33
-
34
- return {
35
- generatePrompt(userInput: string): string {
36
- return `You are a command parser. Convert user input to JSON.
37
- Return ONLY valid JSON, no other text.
38
-
39
- Format: {"action": ${actions}, "params": {}}
40
-
41
- Examples:
42
- ${examples}
43
-
44
- User: ${userInput}
45
- JSON:`;
46
- },
47
-
48
- intentToXML(intent: any): string | null {
49
- if (!intent || !intent.action) return null;
50
-
51
- const sub = subroutines.find(s => s.name === intent.action);
52
- if (!sub) return null;
53
-
54
- const attrs: string[] = [`name="${sub.name}"`];
55
-
56
- // Map params to XML attributes
57
- if (sub.parameters) {
58
- for (const param of sub.parameters) {
59
- const value = intent.params?.[param.name];
60
-
61
- if (value != null) {
62
- // Validate enum if present
63
- if (param.enum && !param.enum.includes(value)) {
64
- return null;
65
- }
66
- attrs.push(`${param.name}="${value}"`);
67
- } else if (param.required) {
68
- return null; // Missing required parameter
69
- }
70
- }
71
- }
72
-
73
- return `<call ${attrs.join(' ')}/>`;
74
- }
75
- };
76
- }
77
-
78
- /**
79
- * Higher-level helper: execute user command via LLM
80
- */
81
- export async function executeUserCommand(
82
- session: DiracSession,
83
- userInput: string,
84
- llmExecuteFn: (prompt: string) => Promise<string>
85
- ): Promise<{ success: boolean; xml?: string; error?: string }> {
86
- try {
87
- const adapter = createLLMAdapter(session);
88
- const prompt = adapter.generatePrompt(userInput);
89
-
90
- // Call LLM
91
- const llmResponse = await llmExecuteFn(prompt);
92
-
93
- // Parse JSON
94
- let jsonStr = llmResponse.trim();
95
- jsonStr = jsonStr.replace(/```json\s*/g, '').replace(/```\s*/g, '');
96
-
97
- const intent = JSON.parse(jsonStr);
98
-
99
- // Convert to XML
100
- const xml = adapter.intentToXML(intent);
101
-
102
- if (!xml) {
103
- return { success: false, error: 'Could not convert intent to valid command' };
104
- }
105
-
106
- return { success: true, xml };
107
- } catch (error) {
108
- return {
109
- success: false,
110
- error: error instanceof Error ? error.message : String(error)
111
- };
112
- }
113
- }