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
@@ -1,203 +0,0 @@
1
- /**
2
- * Core interpreter - maps to mask_integrate in MASK
3
- */
4
-
5
- import type { DiracElement, DiracSession } from '../types/index.js';
6
- import { substituteVariables, emit, getSubroutine } from './session.js';
7
- import { executeDefvar } from '../tags/defvar.js';
8
- import { executeVariable } from '../tags/variable.js';
9
- import { executeAssign } from '../tags/assign.js';
10
- import { executeOutput } from '../tags/output.js';
11
- import { executeSubroutine } from '../tags/subroutine.js';
12
- import { executeCall } from '../tags/call.js';
13
- import { executeLoop } from '../tags/loop.js';
14
- import { executeIf } from '../tags/if.js';
15
- import { executeLLM } from '../tags/llm.js';
16
- import { executeEval } from '../tags/eval.js';
17
- import { executeExecute } from '../tags/execute.js';
18
- import { executeImport } from '../tags/import.js';
19
- import { executeParameters } from '../tags/parameters.js';
20
- import { executeExpr } from '../tags/expr.js';
21
- import { executeSystem } from '../tags/system.js';
22
- import { executeRequireModule } from '../tags/require_module.js';
23
- import { executeTagCheck } from '../tags/tag-check.js';
24
- import { executeThrow } from '../tags/throw.js';
25
- import { executeTry } from '../tags/try.js';
26
- import { executeCatch } from '../tags/catch.js';
27
- import { executeException } from '../tags/exception.js';
28
- import { executeTestIf } from '../tags/test-if.js';
29
- import { executeAvailableSubroutines } from '../tags/available-subroutines.js';
30
- import { executeForeach } from '../tags/foreach.js';
31
- import { executeAttr } from '../tags/attr.js';
32
- import { executeEnvironment } from '../tags/environment.js';
33
- import { executeInput } from '../tags/input.js';
34
-
35
- export async function integrate(session: DiracSession, element: DiracElement): Promise<void> {
36
- // Check execution limits
37
- if (session.limits.currentDepth >= session.limits.maxDepth) {
38
- throw new Error('Maximum execution depth exceeded');
39
- }
40
-
41
- session.limits.currentDepth++;
42
-
43
- try {
44
- // Handle text nodes
45
- if (element.text && !element.tag) {
46
- const substituted = substituteVariables(session, element.text);
47
- emit(session, substituted);
48
- return;
49
- }
50
-
51
- // Check control flow
52
- if (session.isReturn || session.isBreak) {
53
- return;
54
- }
55
-
56
- // Dispatch to tag handlers
57
- switch (element.tag.toLowerCase()) {
58
- case 'defvar':
59
- await executeDefvar(session, element);
60
- break;
61
-
62
- case 'variable':
63
- await executeVariable(session, element);
64
- break;
65
-
66
- case 'assign':
67
- await executeAssign(session, element);
68
- break;
69
-
70
- case 'output':
71
- await executeOutput(session, element);
72
- break;
73
-
74
- case 'subroutine':
75
- await executeSubroutine(session, element);
76
- break;
77
-
78
- case 'call':
79
- await executeCall(session, element);
80
- break;
81
-
82
- case 'loop':
83
- await executeLoop(session, element);
84
- break;
85
-
86
- case 'if':
87
- await executeIf(session, element);
88
- break;
89
-
90
- case 'llm':
91
- await executeLLM(session, element);
92
- break;
93
-
94
- case 'eval':
95
- await executeEval(session, element);
96
- break;
97
-
98
- case 'execute':
99
- await executeExecute(session, element);
100
- break;
101
-
102
- case 'import':
103
- await executeImport(session, element);
104
- break;
105
-
106
- case 'parameters': {
107
- const result = await executeParameters(session, element);
108
- if (typeof result === 'string') {
109
- emit(session, result);
110
- }
111
- break;
112
- }
113
-
114
- case 'expr':
115
- await executeExpr(session, element);
116
- break;
117
-
118
- case 'system':
119
- await executeSystem(session, element);
120
- break;
121
-
122
- case 'tag-check':
123
- await executeTagCheck(session, element);
124
- break;
125
-
126
- case 'throw':
127
- await executeThrow(session, element);
128
- break;
129
-
130
- case 'try':
131
- await executeTry(session, element);
132
- break;
133
-
134
- case 'catch':
135
- await executeCatch(session, element);
136
- break;
137
-
138
- case 'exception':
139
- await executeException(session, element);
140
- break;
141
-
142
- case 'test-if':
143
- await executeTestIf(session, element);
144
- break;
145
-
146
- case 'available-subroutines':
147
- await executeAvailableSubroutines(session, element);
148
- break;
149
-
150
- case 'foreach':
151
- await executeForeach(session, element);
152
- break;
153
-
154
- case 'attr':
155
- await executeAttr(session, element);
156
- break;
157
-
158
- case 'environment':
159
- await executeEnvironment(session, element);
160
- break;
161
-
162
- case 'input':
163
- await executeInput(session, element);
164
- break;
165
-
166
- case 'require_module':
167
- await executeRequireModule(session, element);
168
- break;
169
-
170
- case 'dirac':
171
- case 'DIRAC-ROOT':
172
- // Container tags - just execute children
173
- for (const child of element.children) {
174
- await integrate(session, child);
175
- if (session.isReturn || session.isBreak) break;
176
- }
177
- break;
178
-
179
- default:
180
- // Unknown tag - check if it's a subroutine name
181
- const subroutine = getSubroutine(session, element.tag);
182
- if (subroutine) {
183
- // Treat unknown tag as subroutine call
184
- await executeCall(session, element);
185
- } else {
186
- // Really unknown - just process children
187
- for (const child of element.children) {
188
- await integrate(session, child);
189
- if (session.isReturn || session.isBreak) break;
190
- }
191
- }
192
- }
193
- } finally {
194
- session.limits.currentDepth--;
195
- }
196
- }
197
-
198
- export async function integrateChildren(session: DiracSession, element: DiracElement): Promise<void> {
199
- for (const child of element.children) {
200
- await integrate(session, child);
201
- if (session.isReturn || session.isBreak) break;
202
- }
203
- }
@@ -1,155 +0,0 @@
1
- /**
2
- * XML Parser for Dirac (.di files)
3
- */
4
-
5
- import { XMLParser } from 'fast-xml-parser';
6
- import type { DiracElement } from '../types/index.js';
7
-
8
- export class DiracParser {
9
- private parser: XMLParser;
10
-
11
- constructor() {
12
- this.parser = new XMLParser({
13
- ignoreAttributes: false,
14
- attributeNamePrefix: '@_',
15
- trimValues: false, // Preserve whitespace in mixed content
16
- parseAttributeValue: false,
17
- parseTagValue: false,
18
- textNodeName: '#text',
19
- cdataPropName: '#cdata',
20
- preserveOrder: true, // Preserve element order!
21
- commentPropName: '#comment',
22
- });
23
- }
24
-
25
- parse(source: string): DiracElement {
26
- // Strip shebang line if present
27
- if (source.startsWith('#!')) {
28
- source = source.replace(/^#!.*\n/, '');
29
- }
30
-
31
- // Always wrap in DIRAC-ROOT to ensure valid XML with single root
32
- // This allows files with comments, multiple elements, or no root
33
- source = `<DIRAC-ROOT>\n${source}\n</DIRAC-ROOT>`;
34
-
35
- const result = this.parser.parse(source);
36
- // With preserveOrder, result is an array
37
- if (!Array.isArray(result) || result.length === 0) {
38
- throw new Error('Empty or invalid XML');
39
- }
40
-
41
- // Find the first non-comment element
42
- for (const item of result) {
43
- if (!item['#comment']) {
44
- return this.convertOrderedToElement(item);
45
- }
46
- }
47
-
48
- throw new Error('No root element found');
49
- }
50
-
51
- private convertOrderedToElement(obj: any): DiracElement {
52
- // obj is like { "tagname": [...children], ":@": {...attributes} }
53
- const tagName = Object.keys(obj).find(k => k !== ':@' && k !== '#comment');
54
-
55
- if (!tagName) {
56
- throw new Error('Invalid element structure');
57
- }
58
-
59
- const element: DiracElement = {
60
- tag: tagName,
61
- attributes: {},
62
- children: [],
63
- };
64
-
65
- // Extract attributes
66
- if (obj[':@']) {
67
- for (const [key, value] of Object.entries(obj[':@'])) {
68
- if (key.startsWith('@_')) {
69
- element.attributes[key.slice(2)] = value as string;
70
- }
71
- }
72
- }
73
-
74
- // Extract children
75
- const children = obj[tagName];
76
- if (Array.isArray(children)) {
77
- for (const child of children) {
78
- if (child['#text']) {
79
- // Text node - add as child AND to element.text for backward compat
80
- element.children.push({
81
- tag: '',
82
- text: child['#text'],
83
- attributes: {},
84
- children: []
85
- });
86
- // Also set element.text if not set (for simple text-only elements)
87
- if (!element.text) {
88
- element.text = child['#text'];
89
- } else {
90
- element.text += child['#text'];
91
- }
92
- } else if (child['#comment']) {
93
- // Skip comments
94
- continue;
95
- } else {
96
- // Child element
97
- element.children.push(this.convertOrderedToElement(child));
98
- }
99
- }
100
- }
101
-
102
- return element;
103
- }
104
-
105
- // Old method - no longer used
106
- private convertToElement(obj: any, tagName?: string): DiracElement {
107
- if (!tagName) {
108
- // Root level - find the actual tag
109
- const keys = Object.keys(obj);
110
- if (keys.length === 0) {
111
- throw new Error('Empty XML');
112
- }
113
- tagName = keys[0];
114
- obj = obj[tagName];
115
- }
116
-
117
- const element: DiracElement = {
118
- tag: tagName,
119
- attributes: {},
120
- children: [],
121
- };
122
-
123
- if (typeof obj === 'string') {
124
- element.text = obj;
125
- return element;
126
- }
127
-
128
- if (!obj) {
129
- return element;
130
- }
131
-
132
- // Extract attributes and children
133
- for (const key of Object.keys(obj)) {
134
- const value = obj[key];
135
-
136
- if (key === '#text') {
137
- element.text = value;
138
- } else if (key.startsWith('@_')) {
139
- // Attribute
140
- element.attributes[key.slice(2)] = value;
141
- } else {
142
- // Child element
143
- if (Array.isArray(value)) {
144
- for (const item of value) {
145
- element.children.push(this.convertToElement(item, key));
146
- }
147
- } else {
148
- element.children.push(this.convertToElement(value, key));
149
- }
150
- }
151
- }
152
-
153
- return element;
154
- }
155
- }
@@ -1,325 +0,0 @@
1
- // Substitute both $var and ${var} in a string using session variables
2
- export function substituteAttribute(session: DiracSession, value: any): string {
3
- if (typeof value !== 'string') return value;
4
- return value
5
- .replace(/\$\{(\w+)\}/g, (match, varName) => {
6
- const v = getVariable(session, varName);
7
- return v !== undefined ? String(v) : match;
8
- })
9
- .replace(/\$(\w+)/g, (match, varName) => {
10
- const v = getVariable(session, varName);
11
- return v !== undefined ? String(v) : match;
12
- });
13
- }
14
- /**
15
- * Session management - maps to MASK session functions
16
- */
17
-
18
- import Anthropic from '@anthropic-ai/sdk';
19
- import OpenAI from 'openai';
20
- import { OllamaProvider } from '../llm/ollama.js';
21
- import type { DiracSession, DiracConfig, Variable, Subroutine, DiracElement } from '../types/index.js';
22
-
23
- export function createSession(config: DiracConfig = {}): DiracSession {
24
- const anthropicKey = process.env.ANTHROPIC_API_KEY;
25
- const openaiKey = config.apiKey || process.env.OPENAI_API_KEY;
26
- const llmProvider = config.llmProvider || process.env.LLM_PROVIDER;
27
- const ollamaModel = config.llmModel || process.env.LLM_MODEL || 'llama2';
28
-
29
- let llmClient: any;
30
- switch (llmProvider) {
31
- case 'ollama':
32
- llmClient = new OllamaProvider({ model: ollamaModel });
33
- break;
34
- case 'anthropic':
35
- if (!anthropicKey) throw new Error('ANTHROPIC_API_KEY required for Anthropic provider');
36
- llmClient = new Anthropic({ apiKey: anthropicKey });
37
- break;
38
- case 'openai':
39
- if (!openaiKey) throw new Error('OPENAI_API_KEY required for OpenAI provider');
40
- llmClient = new OpenAI({ apiKey: openaiKey });
41
- break;
42
- default:
43
- throw new Error('No valid LLM provider configured. Set llmProvider in config or LLM_PROVIDER env.');
44
- }
45
- return {
46
- variables: [],
47
- subroutines: [],
48
- varBoundary: 0,
49
- subBoundary: 0,
50
- parameterStack: [],
51
- exceptions: [],
52
- currentException: {
53
- size: 0,
54
- exceptions: [],
55
- },
56
- output: [],
57
- llmClient,
58
- limits: {
59
- maxLLMCalls: config.maxLLMCalls || 100,
60
- currentLLMCalls: 0,
61
- maxDepth: config.maxDepth || 50,
62
- currentDepth: 0,
63
- },
64
- isReturn: false,
65
- isBreak: false,
66
- skipSubroutineRegistration: false,
67
- debug: config.debug || false,
68
- };
69
- }
70
-
71
- // Variable management (maps to var_info functions in MASK)
72
-
73
- export function setVariable(session: DiracSession, name: string, value: any, visible: boolean = false): void {
74
- session.variables.push({
75
- name,
76
- value,
77
- visible,
78
- boundary: session.varBoundary,
79
- passby: 'value',
80
- });
81
- }
82
-
83
- export function getVariable(session: DiracSession, name: string): any {
84
- // Search from end (most recent) to beginning
85
- for (let i = session.variables.length - 1; i >= 0; i--) {
86
- if (session.variables[i].name === name) {
87
- return session.variables[i].value;
88
- }
89
- }
90
- return undefined;
91
- }
92
-
93
- export function hasVariable(session: DiracSession, name: string): boolean {
94
- return session.variables.some(v => v.name === name);
95
- }
96
-
97
- /**
98
- * Set boundary marker for local variables
99
- * Maps to var_info_set_boundary in MASK
100
- */
101
- export function setBoundary(session: DiracSession): number {
102
- const oldBoundary = session.varBoundary;
103
- session.varBoundary = session.variables.length;
104
- return oldBoundary;
105
- }
106
-
107
- /**
108
- * Pop variables back to boundary (cleanup local scope)
109
- * Maps to var_info_pop_to_boundary in MASK
110
- */
111
- export function popToBoundary(session: DiracSession): void {
112
- session.variables = session.variables.slice(0, session.varBoundary);
113
- }
114
-
115
- /**
116
- * Clean private variables but keep visible ones
117
- * Maps to var_info_clean_to_boundary in MASK
118
- */
119
- export function cleanToBoundary(session: DiracSession): void {
120
- const kept: Variable[] = [];
121
-
122
- for (let i = 0; i < session.varBoundary; i++) {
123
- kept.push(session.variables[i]);
124
- }
125
-
126
- for (let i = session.varBoundary; i < session.variables.length; i++) {
127
- if (session.variables[i].visible) {
128
- kept.push(session.variables[i]);
129
- }
130
- }
131
-
132
- session.variables = kept;
133
- session.varBoundary = kept.length;
134
- }
135
-
136
- // Subroutine management (maps to subroutine functions in MASK)
137
-
138
- export function registerSubroutine(
139
- session: DiracSession,
140
- name: string,
141
- element: DiracElement,
142
- description?: string,
143
- parameters?: any[],
144
- meta?: Record<string, string>
145
- ): void {
146
- session.subroutines.push({
147
- name,
148
- element,
149
- boundary: session.subBoundary,
150
- description,
151
- parameters,
152
- meta,
153
- });
154
- }
155
-
156
- export function getSubroutine(session: DiracSession, name: string): DiracElement | undefined {
157
- // Search from end (most recent) to beginning
158
- for (let i = session.subroutines.length - 1; i >= 0; i--) {
159
- if (session.subroutines[i].name === name) {
160
- return session.subroutines[i].element;
161
- }
162
- }
163
- return undefined;
164
- }
165
-
166
- export function getParentSubroutine(
167
- session: DiracSession,
168
- name: string,
169
- currentElement?: DiracElement
170
- ): DiracElement | undefined {
171
- // Search from end, finding parent of currentElement
172
- // If currentElement provided, skip until we find it, then return next match
173
- // If not provided, just return most recent
174
-
175
- let foundCurrent = currentElement === undefined;
176
-
177
- for (let i = session.subroutines.length - 1; i >= 0; i--) {
178
- if (session.subroutines[i].name === name) {
179
- if (!foundCurrent) {
180
- // Check if this is the current element
181
- if (session.subroutines[i].element === currentElement) {
182
- foundCurrent = true;
183
- continue; // Skip current, look for parent
184
- }
185
- continue; // Not current yet, keep searching
186
- }
187
- // Found current, this is the parent
188
- return session.subroutines[i].element;
189
- }
190
- }
191
- return undefined;
192
- }
193
-
194
- export function setSubroutineBoundary(session: DiracSession): number {
195
- const oldBoundary = session.subBoundary;
196
- session.subBoundary = session.subroutines.length;
197
- return oldBoundary;
198
- }
199
-
200
- export function popSubroutinesToBoundary(session: DiracSession): void {
201
- session.subroutines = session.subroutines.slice(0, session.subBoundary);
202
- }
203
-
204
- export function cleanSubroutinesToBoundary(session: DiracSession): void {
205
- // For now, same as pop (visibility not implemented for subroutines yet)
206
- popSubroutinesToBoundary(session);
207
- }
208
-
209
- // Variable substitution (maps to var_replace functions in MASK)
210
-
211
- export function substituteVariables(session: DiracSession, text: string): string {
212
- // Decode HTML entities only; do NOT substitute variables globally
213
- return text
214
- .replace(/&#10;/g, '\n')
215
- .replace(/&#13;/g, '\r')
216
- .replace(/&#9;/g, '\t')
217
- .replace(/&lt;/g, '<')
218
- .replace(/&gt;/g, '>')
219
- .replace(/&amp;/g, '&')
220
- .replace(/&quot;/g, '"')
221
- .replace(/&apos;/g, "'");
222
- }
223
-
224
- // Output management
225
-
226
- export function emit(session: DiracSession, content: string): void {
227
- session.output.push(content);
228
- }
229
-
230
- export function getOutput(session: DiracSession): string {
231
- return session.output.join('');
232
- }
233
-
234
- // Parameter stack (for subroutine calls)
235
-
236
- export function pushParameters(session: DiracSession, params: DiracElement[]): void {
237
- session.parameterStack.push(params);
238
- }
239
-
240
- export function popParameters(session: DiracSession): DiracElement[] | undefined {
241
- return session.parameterStack.pop();
242
- }
243
-
244
- export function getCurrentParameters(session: DiracSession): DiracElement[] | undefined {
245
- return session.parameterStack[session.parameterStack.length - 1];
246
- }
247
-
248
- // Reflection/Introspection API
249
-
250
- export function getAvailableSubroutines(session: DiracSession): Array<{
251
- name: string;
252
- description?: string;
253
- parameters?: Array<{
254
- name: string;
255
- type?: string;
256
- required?: boolean;
257
- description?: string;
258
- enum?: string[];
259
- }>;
260
- }> {
261
- return session.subroutines.map(sub => ({
262
- name: sub.name,
263
- description: sub.description,
264
- parameters: sub.parameters,
265
- meta: sub.meta,
266
- }));
267
- }
268
-
269
- // Exception handling (for try/catch/throw)
270
-
271
- export function throwException(session: DiracSession, name: string, dom: DiracElement): void {
272
- session.exceptions.push({
273
- name,
274
- dom,
275
- isBoundary: 0,
276
- });
277
- }
278
-
279
- export function setExceptionBoundary(session: DiracSession): void {
280
- const size = session.exceptions.length;
281
- if (size === 0) return;
282
- const top = session.exceptions[size - 1];
283
- top.isBoundary++;
284
- }
285
-
286
- export function unsetExceptionBoundary(session: DiracSession): void {
287
- const size = session.exceptions.length;
288
- if (size === 0) return;
289
- for (let i = size - 1; i >= 0; i--) {
290
- const exception = session.exceptions[i];
291
- if (exception.isBoundary > 0) {
292
- exception.isBoundary--;
293
- break;
294
- }
295
- }
296
- }
297
-
298
- export function lookupException(session: DiracSession, name: string): number {
299
- const size = session.exceptions.length;
300
- if (size === 0) return 0;
301
-
302
- let count = 0;
303
- for (let i = size - 1; i >= 0; i--) {
304
- const exception = session.exceptions[i];
305
- if (exception.isBoundary > 0) break; // Stop at boundary
306
-
307
- if (exception.name === name) {
308
- // Add to current exception list
309
- session.currentException.exceptions.push(exception.dom);
310
- session.currentException.size++;
311
- count++;
312
- }
313
- }
314
-
315
- return count;
316
- }
317
-
318
- export function flushCurrentException(session: DiracSession): void {
319
- session.currentException.size = 0;
320
- session.currentException.exceptions = [];
321
- }
322
-
323
- export function getCurrentExceptions(session: DiracSession): DiracElement[] {
324
- return session.currentException.exceptions;
325
- }