dirac-lang 0.1.2

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 (110) hide show
  1. package/.env.example +8 -0
  2. package/COMMUNITY.md +465 -0
  3. package/LIBRARIES.md +172 -0
  4. package/NAMESPACES.md +366 -0
  5. package/PROMOTION.md +257 -0
  6. package/QUICKSTART-LIBRARY.md +93 -0
  7. package/README.md +257 -0
  8. package/config.yml +6 -0
  9. package/config.yml.openai +4 -0
  10. package/dirac-http/examples/demo.di +9 -0
  11. package/dirac-http/lib/index.di +12 -0
  12. package/dist/chunk-NDIRTD3D.js +217 -0
  13. package/dist/chunk-S625X7ME.js +1071 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.js +261 -0
  16. package/dist/index.d.ts +144 -0
  17. package/dist/index.js +22 -0
  18. package/dist/session-4QG7OERD.js +42 -0
  19. package/examples/add-demo.di +74 -0
  20. package/examples/add.bk +11 -0
  21. package/examples/advanced-math-demo.di +53 -0
  22. package/examples/calculator.di +32 -0
  23. package/examples/comprehensive.bk +29 -0
  24. package/examples/defvar-variable-demo.di +18 -0
  25. package/examples/direct-call.di +17 -0
  26. package/examples/disk-analysis.di +16 -0
  27. package/examples/executable-hello.di +7 -0
  28. package/examples/execute-demo.di +38 -0
  29. package/examples/file-manager.di +77 -0
  30. package/examples/file-stats.di +18 -0
  31. package/examples/hello.bk +1 -0
  32. package/examples/hello.di +5 -0
  33. package/examples/import-demo.di +31 -0
  34. package/examples/inline-test.bk +7 -0
  35. package/examples/lib/advanced-math.di +81 -0
  36. package/examples/lib/fileops.di +26 -0
  37. package/examples/lib/math.di +25 -0
  38. package/examples/lib/mongodb.di +96 -0
  39. package/examples/llm-agent.di +32 -0
  40. package/examples/llm-basic.di +12 -0
  41. package/examples/llm-command-no-exec.di +13 -0
  42. package/examples/llm-command.di +13 -0
  43. package/examples/llm-complex.di +141 -0
  44. package/examples/llm-recursive.di +31 -0
  45. package/examples/llm-reflection-test.di +19 -0
  46. package/examples/llm-subs.di +132 -0
  47. package/examples/llm-use-subs.di +6 -0
  48. package/examples/loop.di +12 -0
  49. package/examples/math-test.di +22 -0
  50. package/examples/mongodb-count-events.di +8 -0
  51. package/examples/mongodb-import-demo.di +25 -0
  52. package/examples/mongodb-simple-test.di +18 -0
  53. package/examples/nl-agent.di +47 -0
  54. package/examples/parameters-demo.di +68 -0
  55. package/examples/params-test.di +10 -0
  56. package/examples/recipe-chain.di +38 -0
  57. package/examples/recursive-llm.di +44 -0
  58. package/examples/sample-library/README.md +152 -0
  59. package/examples/sample-library/examples/demo.di +34 -0
  60. package/examples/sample-library/lib/index.di +65 -0
  61. package/examples/sample-library/package.json +31 -0
  62. package/examples/seamless.di +45 -0
  63. package/examples/shell-test.bk +10 -0
  64. package/examples/simple-import.di +13 -0
  65. package/examples/simple-recursive.di +26 -0
  66. package/examples/story-builder.di +45 -0
  67. package/examples/subroutine.di +23 -0
  68. package/examples/system-llm.di +21 -0
  69. package/examples/system-simple.di +3 -0
  70. package/examples/system-test.di +13 -0
  71. package/examples/task-assistant.di +27 -0
  72. package/examples/test-parameters.di +50 -0
  73. package/examples/two-styles.di +28 -0
  74. package/examples/var-debug.di +6 -0
  75. package/examples/var-inline.di +4 -0
  76. package/examples/var-test2.di +6 -0
  77. package/examples/variable-simple.di +16 -0
  78. package/examples/variable-test.di +22 -0
  79. package/filePath +1 -0
  80. package/greeting.txt +1 -0
  81. package/package.json +41 -0
  82. package/src/cli.ts +118 -0
  83. package/src/index.ts +33 -0
  84. package/src/llm/ollama.ts +58 -0
  85. package/src/runtime/braket-parser.ts +234 -0
  86. package/src/runtime/interpreter.ts +135 -0
  87. package/src/runtime/parser.ts +151 -0
  88. package/src/runtime/session.ts +228 -0
  89. package/src/tags/assign.ts +37 -0
  90. package/src/tags/call.ts +156 -0
  91. package/src/tags/defvar.ts +56 -0
  92. package/src/tags/eval.ts +68 -0
  93. package/src/tags/execute.ts +52 -0
  94. package/src/tags/expr.ts +128 -0
  95. package/src/tags/if.ts +58 -0
  96. package/src/tags/import.ts +66 -0
  97. package/src/tags/index.ts +37 -0
  98. package/src/tags/llm.ts +207 -0
  99. package/src/tags/loop.ts +43 -0
  100. package/src/tags/mongodb.ts +70 -0
  101. package/src/tags/output.ts +23 -0
  102. package/src/tags/parameters.ts +79 -0
  103. package/src/tags/require_module.ts +19 -0
  104. package/src/tags/subroutine.ts +52 -0
  105. package/src/tags/system.ts +70 -0
  106. package/src/tags/variable.ts +25 -0
  107. package/src/types/index.ts +101 -0
  108. package/src/utils/llm-adapter.ts +113 -0
  109. package/tools/create-library.sh +175 -0
  110. package/tsconfig.json +19 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Session management - maps to MASK session functions
3
+ */
4
+
5
+ import Anthropic from '@anthropic-ai/sdk';
6
+ import OpenAI from 'openai';
7
+ import { OllamaProvider } from '../llm/ollama.js';
8
+ import type { DiracSession, DiracConfig, Variable, Subroutine, DiracElement } from '../types/index.js';
9
+
10
+ export function createSession(config: DiracConfig = {}): DiracSession {
11
+ const anthropicKey = process.env.ANTHROPIC_API_KEY;
12
+ const openaiKey = config.apiKey || process.env.OPENAI_API_KEY;
13
+ const llmProvider = config.llmProvider || process.env.LLM_PROVIDER;
14
+ const ollamaModel = config.llmModel || process.env.LLM_MODEL || 'llama2';
15
+
16
+ let llmClient: any;
17
+ switch (llmProvider) {
18
+ case 'ollama':
19
+ llmClient = new OllamaProvider({ model: ollamaModel });
20
+ break;
21
+ case 'anthropic':
22
+ if (!anthropicKey) throw new Error('ANTHROPIC_API_KEY required for Anthropic provider');
23
+ llmClient = new Anthropic({ apiKey: anthropicKey });
24
+ break;
25
+ case 'openai':
26
+ if (!openaiKey) throw new Error('OPENAI_API_KEY required for OpenAI provider');
27
+ llmClient = new OpenAI({ apiKey: openaiKey });
28
+ break;
29
+ default:
30
+ throw new Error('No valid LLM provider configured. Set llmProvider in config or LLM_PROVIDER env.');
31
+ }
32
+ return {
33
+ variables: [],
34
+ subroutines: [],
35
+ varBoundary: 0,
36
+ subBoundary: 0,
37
+ parameterStack: [],
38
+ output: [],
39
+ llmClient,
40
+ limits: {
41
+ maxLLMCalls: config.maxLLMCalls || 100,
42
+ currentLLMCalls: 0,
43
+ maxDepth: config.maxDepth || 50,
44
+ currentDepth: 0,
45
+ },
46
+ isReturn: false,
47
+ isBreak: false,
48
+ debug: config.debug || false,
49
+ };
50
+ }
51
+
52
+ // Variable management (maps to var_info functions in MASK)
53
+
54
+ export function setVariable(session: DiracSession, name: string, value: any, visible: boolean = false): void {
55
+ session.variables.push({
56
+ name,
57
+ value,
58
+ visible,
59
+ boundary: session.varBoundary,
60
+ passby: 'value',
61
+ });
62
+ }
63
+
64
+ export function getVariable(session: DiracSession, name: string): any {
65
+ // Search from end (most recent) to beginning
66
+ for (let i = session.variables.length - 1; i >= 0; i--) {
67
+ if (session.variables[i].name === name) {
68
+ return session.variables[i].value;
69
+ }
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ export function hasVariable(session: DiracSession, name: string): boolean {
75
+ return session.variables.some(v => v.name === name);
76
+ }
77
+
78
+ /**
79
+ * Set boundary marker for local variables
80
+ * Maps to var_info_set_boundary in MASK
81
+ */
82
+ export function setBoundary(session: DiracSession): number {
83
+ const oldBoundary = session.varBoundary;
84
+ session.varBoundary = session.variables.length;
85
+ return oldBoundary;
86
+ }
87
+
88
+ /**
89
+ * Pop variables back to boundary (cleanup local scope)
90
+ * Maps to var_info_pop_to_boundary in MASK
91
+ */
92
+ export function popToBoundary(session: DiracSession): void {
93
+ session.variables = session.variables.slice(0, session.varBoundary);
94
+ }
95
+
96
+ /**
97
+ * Clean private variables but keep visible ones
98
+ * Maps to var_info_clean_to_boundary in MASK
99
+ */
100
+ export function cleanToBoundary(session: DiracSession): void {
101
+ const kept: Variable[] = [];
102
+
103
+ for (let i = 0; i < session.varBoundary; i++) {
104
+ kept.push(session.variables[i]);
105
+ }
106
+
107
+ for (let i = session.varBoundary; i < session.variables.length; i++) {
108
+ if (session.variables[i].visible) {
109
+ kept.push(session.variables[i]);
110
+ }
111
+ }
112
+
113
+ session.variables = kept;
114
+ session.varBoundary = kept.length;
115
+ }
116
+
117
+ // Subroutine management (maps to subroutine functions in MASK)
118
+
119
+ export function registerSubroutine(
120
+ session: DiracSession,
121
+ name: string,
122
+ element: DiracElement,
123
+ description?: string,
124
+ parameters?: any[]
125
+ ): void {
126
+ session.subroutines.push({
127
+ name,
128
+ element,
129
+ boundary: session.subBoundary,
130
+ description,
131
+ parameters,
132
+ });
133
+ }
134
+
135
+ export function getSubroutine(session: DiracSession, name: string): DiracElement | undefined {
136
+ // Search from end (most recent) to beginning
137
+ for (let i = session.subroutines.length - 1; i >= 0; i--) {
138
+ if (session.subroutines[i].name === name) {
139
+ return session.subroutines[i].element;
140
+ }
141
+ }
142
+ return undefined;
143
+ }
144
+
145
+ export function setSubroutineBoundary(session: DiracSession): number {
146
+ const oldBoundary = session.subBoundary;
147
+ session.subBoundary = session.subroutines.length;
148
+ return oldBoundary;
149
+ }
150
+
151
+ export function popSubroutinesToBoundary(session: DiracSession): void {
152
+ session.subroutines = session.subroutines.slice(0, session.subBoundary);
153
+ }
154
+
155
+ export function cleanSubroutinesToBoundary(session: DiracSession): void {
156
+ // For now, same as pop (visibility not implemented for subroutines yet)
157
+ popSubroutinesToBoundary(session);
158
+ }
159
+
160
+ // Variable substitution (maps to var_replace functions in MASK)
161
+
162
+ export function substituteVariables(session: DiracSession, text: string): string {
163
+ // Decode HTML entities first
164
+ let decoded = text
165
+ .replace(/&#10;/g, '\n')
166
+ .replace(/&#13;/g, '\r')
167
+ .replace(/&#9;/g, '\t')
168
+ .replace(/&lt;/g, '<')
169
+ .replace(/&gt;/g, '>')
170
+ .replace(/&amp;/g, '&')
171
+ .replace(/&quot;/g, '"')
172
+ .replace(/&apos;/g, "'");
173
+
174
+ // Substitute both ${var}/$var and {var} patterns
175
+ return decoded
176
+ .replace(/\$\{?(\w+)\}?/g, (match, varName) => {
177
+ const value = getVariable(session, varName);
178
+ return value !== undefined ? String(value) : match;
179
+ })
180
+ .replace(/\{(\w+)\}/g, (match, varName) => {
181
+ const value = getVariable(session, varName);
182
+ return value !== undefined ? String(value) : match;
183
+ });
184
+ }
185
+
186
+ // Output management
187
+
188
+ export function emit(session: DiracSession, content: string): void {
189
+ session.output.push(content);
190
+ }
191
+
192
+ export function getOutput(session: DiracSession): string {
193
+ return session.output.join('');
194
+ }
195
+
196
+ // Parameter stack (for subroutine calls)
197
+
198
+ export function pushParameters(session: DiracSession, params: DiracElement[]): void {
199
+ session.parameterStack.push(params);
200
+ }
201
+
202
+ export function popParameters(session: DiracSession): DiracElement[] | undefined {
203
+ return session.parameterStack.pop();
204
+ }
205
+
206
+ export function getCurrentParameters(session: DiracSession): DiracElement[] | undefined {
207
+ return session.parameterStack[session.parameterStack.length - 1];
208
+ }
209
+
210
+ // Reflection/Introspection API
211
+
212
+ export function getAvailableSubroutines(session: DiracSession): Array<{
213
+ name: string;
214
+ description?: string;
215
+ parameters?: Array<{
216
+ name: string;
217
+ type?: string;
218
+ required?: boolean;
219
+ description?: string;
220
+ enum?: string[];
221
+ }>;
222
+ }> {
223
+ return session.subroutines.map(sub => ({
224
+ name: sub.name,
225
+ description: sub.description,
226
+ parameters: sub.parameters,
227
+ }));
228
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * <assign> tag - assign value to existing variable
3
+ * Maps to mask_tag_assign in MASK
4
+ */
5
+
6
+ import type { DiracSession, DiracElement } from '../types/index.js';
7
+ import { getVariable, setVariable, substituteVariables } from '../runtime/session.js';
8
+
9
+ export function executeAssign(session: DiracSession, element: DiracElement): void {
10
+ const name = element.attributes.name;
11
+ const valueAttr = element.attributes.value;
12
+
13
+ if (!name) {
14
+ throw new Error('<assign> requires name attribute');
15
+ }
16
+
17
+ // Get value
18
+ let value: any;
19
+ if (valueAttr !== undefined) {
20
+ value = substituteVariables(session, valueAttr);
21
+ } else if (element.text) {
22
+ value = substituteVariables(session, element.text);
23
+ } else {
24
+ value = '';
25
+ }
26
+
27
+ // Find existing variable and update it
28
+ for (let i = session.variables.length - 1; i >= 0; i--) {
29
+ if (session.variables[i].name === name) {
30
+ session.variables[i].value = value;
31
+ return;
32
+ }
33
+ }
34
+
35
+ // Variable not found - create it (same as MASK behavior)
36
+ setVariable(session, name, value, false);
37
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * <call> tag - invoke subroutine
3
+ * Maps to mask_call_integrate in MASK
4
+ */
5
+
6
+ import type { DiracSession, DiracElement } from '../types/index.js';
7
+ import {
8
+ getSubroutine,
9
+ setBoundary,
10
+ popToBoundary,
11
+ cleanToBoundary,
12
+ pushParameters,
13
+ popParameters,
14
+ substituteVariables,
15
+ setVariable,
16
+ getVariable,
17
+ } from '../runtime/session.js';
18
+ import { integrateChildren } from '../runtime/interpreter.js';
19
+
20
+ export async function executeCall(session: DiracSession, element: DiracElement): Promise<void> {
21
+ // Support both <call name="FOO" /> and direct <FOO /> syntax
22
+ // For <call> tag, use name/subroutine attribute
23
+ // For direct syntax, use element.tag
24
+ let name: string;
25
+
26
+ if (element.tag === 'call') {
27
+ // Explicit <call> tag - use name or subroutine attribute
28
+ name = element.attributes.name || element.attributes.subroutine || '';
29
+ } else {
30
+ // Direct tag syntax - use tag name itself, ignore name attribute
31
+ name = element.tag;
32
+ }
33
+
34
+ if (!name) {
35
+ throw new Error('<call> requires name or subroutine attribute');
36
+ }
37
+
38
+ const subroutine = getSubroutine(session, name);
39
+ if (!subroutine) {
40
+ throw new Error(`Subroutine '${name}' not found`);
41
+ }
42
+
43
+ // Handle extension (parent subroutine)
44
+ const extendsName = subroutine.attributes.extends;
45
+ if (extendsName) {
46
+ const parent = getSubroutine(session, extendsName);
47
+ if (parent) {
48
+ // Call parent first
49
+ await executeCallInternal(session, parent, element);
50
+ }
51
+ }
52
+
53
+ // Call this subroutine
54
+ await executeCallInternal(session, subroutine, element);
55
+ }
56
+
57
+ async function executeCallInternal(
58
+ session: DiracSession,
59
+ subroutine: DiracElement,
60
+ callElement: DiracElement
61
+ ): Promise<void> {
62
+ // Set boundary for local scope
63
+ const oldBoundary = setBoundary(session);
64
+ const wasReturn = session.isReturn;
65
+ session.isReturn = false;
66
+
67
+ // Substitute variables in call element attributes before pushing to parameter stack
68
+ const substitutedElement: DiracElement = {
69
+ tag: callElement.tag,
70
+ attributes: {},
71
+ children: callElement.children
72
+ };
73
+
74
+ // Process each attribute for {variable} substitution
75
+ for (const [key, value] of Object.entries(callElement.attributes)) {
76
+ if (typeof value === 'string') {
77
+ substitutedElement.attributes[key] = substituteVariables(session, value);
78
+ } else {
79
+ substitutedElement.attributes[key] = value;
80
+ }
81
+ }
82
+
83
+ // Push caller element onto parameter stack for <parameters select="*|@*|@attr"/> access
84
+ pushParameters(session, [substitutedElement]);
85
+
86
+ try {
87
+ // Bind parameters
88
+ const paramElements = callElement.children.filter(c => c.tag === 'parameters');
89
+ if (paramElements.length > 0) {
90
+ await bindParameters(session, subroutine, paramElements[0]);
91
+ }
92
+
93
+ // Execute subroutine body
94
+ await integrateChildren(session, subroutine);
95
+
96
+ } finally {
97
+ // Pop parameter stack
98
+ popParameters(session);
99
+
100
+ // Clean up scope (keep visible variables)
101
+ session.varBoundary = oldBoundary;
102
+ cleanToBoundary(session);
103
+ session.isReturn = wasReturn;
104
+ }
105
+ }
106
+
107
+ async function bindParameters(
108
+ session: DiracSession,
109
+ subroutine: DiracElement,
110
+ callParams: DiracElement
111
+ ): Promise<void> {
112
+ // Find <parameters> definition in subroutine
113
+ const paramDef = subroutine.children.find(c => c.tag === 'parameters');
114
+ if (!paramDef) {
115
+ return; // No parameters defined
116
+ }
117
+
118
+ // Get variable definitions from parameter declaration
119
+ const paramVars = paramDef.children.filter(c => c.tag === 'variable');
120
+ const callVars = callParams.children.filter(c => c.tag === 'variable');
121
+
122
+ // Bind each parameter
123
+ for (let i = 0; i < paramVars.length; i++) {
124
+ const paramVar = paramVars[i];
125
+ const callVar = callVars[i];
126
+
127
+ const paramName = paramVar.attributes.name;
128
+ const passby = paramVar.attributes.passby || 'value';
129
+
130
+ if (!paramName) continue;
131
+
132
+ let value: any;
133
+
134
+ if (callVar) {
135
+ // Get value from call site
136
+ const callValue = callVar.attributes.value;
137
+ if (callValue) {
138
+ if (passby === 'ref') {
139
+ // Pass by reference - store variable name
140
+ setVariable(session, paramName, getVariable(session, callValue), false);
141
+ session.variables[session.variables.length - 1].passby = 'ref';
142
+ session.variables[session.variables.length - 1].refName = callValue;
143
+ } else {
144
+ // Pass by value
145
+ value = substituteVariables(session, callValue);
146
+ setVariable(session, paramName, value, false);
147
+ }
148
+ }
149
+ } else {
150
+ // No value provided - use default if available
151
+ const defaultValue = paramVar.attributes.default || '';
152
+ value = substituteVariables(session, defaultValue);
153
+ setVariable(session, paramName, value, false);
154
+ }
155
+ }
156
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * <defvar> tag - define variable
3
+ * Maps to mask_tag_defvar in MASK
4
+ */
5
+
6
+
7
+ import type { DiracSession, DiracElement } from '../types/index.js';
8
+ import { setVariable, substituteVariables } from '../runtime/session.js';
9
+ import { integrate } from '../runtime/interpreter.js';
10
+ import { executeParameters } from './parameters.js';
11
+
12
+ export async function executeDefvar(session: DiracSession, element: DiracElement): Promise<void> {
13
+ const name = element.attributes.name;
14
+ const valueAttr = element.attributes.value;
15
+ const visibleAttr = element.attributes.visible || 'false';
16
+ const literal = 'literal' in element.attributes;
17
+
18
+ if (!name) {
19
+ throw new Error('<defvar> requires name attribute');
20
+ }
21
+
22
+ // Determine visibility
23
+ const visible = visibleAttr === 'true' || visibleAttr === 'variable' || visibleAttr === 'both';
24
+
25
+ let value: any;
26
+ if (valueAttr !== undefined) {
27
+ value = substituteVariables(session, valueAttr);
28
+ } else if (literal) {
29
+ // Literal mode: take text or XML as-is
30
+ if (element.text) {
31
+ value = substituteVariables(session, element.text);
32
+ } else {
33
+ value = '';
34
+ }
35
+ } else if (element.children && element.children.length > 0) {
36
+ // If the first child is a <parameters> tag, call and assign its return value
37
+ if (element.children.length === 1 && element.children[0].tag && element.children[0].tag.toLowerCase() === 'parameters') {
38
+ value = await executeParameters(session, element.children[0]);
39
+ } else {
40
+ // Otherwise, execute all children and capture output
41
+ const prevOutput = session.output;
42
+ session.output = [];
43
+ for (const child of element.children) {
44
+ await integrate(session, child);
45
+ }
46
+ value = session.output.join('');
47
+ session.output = prevOutput;
48
+ }
49
+ } else if (element.text) {
50
+ value = substituteVariables(session, element.text);
51
+ } else {
52
+ value = '';
53
+ }
54
+
55
+ setVariable(session, name, value, visible);
56
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * <eval> tag - evaluate JavaScript expression
3
+ * Maps to mask_tag_eval in MASK (but for JS, not C)
4
+ */
5
+
6
+ import type { DiracSession, DiracElement } from '../types/index.js';
7
+ import { setVariable, getVariable, substituteVariables } from '../runtime/session.js';
8
+
9
+ // AsyncFunction constructor
10
+ const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
11
+
12
+ export async function executeEval(session: DiracSession, element: DiracElement): Promise<void> {
13
+ const name = element.attributes.name;
14
+ const exprAttr = element.attributes.expr;
15
+
16
+ // Get expression - replace ${var} with var (will be passed as actual JS vars)
17
+ let expr: string;
18
+ if (exprAttr) {
19
+ expr = exprAttr.replace(/\$\{(\w+)\}/g, '$1');
20
+ } else if (element.text) {
21
+ expr = element.text.replace(/\$\{(\w+)\}/g, '$1');
22
+ } else {
23
+ throw new Error('<eval> requires expr attribute or text content');
24
+ }
25
+
26
+ if (session.debug) {
27
+ console.error(`[EVAL] Code after substitution:\n${expr}\n`);
28
+ }
29
+
30
+ try {
31
+ // Build context object with all variables
32
+ const context: Record<string, any> = {};
33
+ for (const v of session.variables) {
34
+ context[v.name] = v.value;
35
+ }
36
+
37
+ // Add Node.js modules to context
38
+ const { default: fs } = await import('fs');
39
+ const { default: path } = await import('path');
40
+ const { fileURLToPath } = await import('url');
41
+ context.fs = fs;
42
+ context.path = path;
43
+ context.__dirname = process.cwd(); // ESM doesn't have __dirname, use cwd
44
+
45
+ // Add helper to get current parameters from stack
46
+ context.getParams = () => {
47
+ const params = session.parameterStack[session.parameterStack.length - 1];
48
+ return params && params[0] ? params[0] : null;
49
+ };
50
+
51
+ let result: any;
52
+ // Execute as async function to support top-level await
53
+ const func = new AsyncFunction(...Object.keys(context), expr);
54
+ result = await func(...Object.values(context));
55
+
56
+ if (session.debug) {
57
+ console.error(`[EVAL] Result: ${JSON.stringify(result)}`);
58
+ }
59
+
60
+ // Store result if name provided
61
+ if (name) {
62
+ setVariable(session, name, result, false);
63
+ }
64
+
65
+ } catch (error) {
66
+ throw new Error(`Eval error: ${error instanceof Error ? error.message : String(error)}`);
67
+ }
68
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * <execute> tag - Execute dynamically generated Dirac code
3
+ * Takes LLM-generated or variable content and interprets it as Dirac XML
4
+ */
5
+
6
+ import type { DiracSession, DiracElement } from '../types/index.js';
7
+ import { getVariable, substituteVariables } from '../runtime/session.js';
8
+ import { DiracParser } from '../runtime/parser.js';
9
+ import { integrate } from '../runtime/interpreter.js';
10
+
11
+ export async function executeExecute(session: DiracSession, element: DiracElement): Promise<void> {
12
+ const sourceAttr = element.attributes.source;
13
+
14
+ // Get the Dirac code to execute
15
+ let diracCode: string;
16
+
17
+ if (sourceAttr) {
18
+ // Get from variable
19
+ diracCode = getVariable(session, sourceAttr);
20
+ if (!diracCode) {
21
+ throw new Error(`<execute> source variable '${sourceAttr}' not found`);
22
+ }
23
+ } else if (element.text) {
24
+ // Get from text content (with variable substitution)
25
+ diracCode = substituteVariables(session, element.text);
26
+ } else {
27
+ throw new Error('<execute> requires source attribute or text content');
28
+ }
29
+
30
+ if (session.debug) {
31
+ console.error(`[EXECUTE] Interpreting dynamic code:\n${diracCode}\n`);
32
+ }
33
+
34
+ // Strip markdown code blocks if present
35
+ diracCode = diracCode.trim();
36
+ if (diracCode.startsWith('```')) {
37
+ // Remove markdown code fences
38
+ diracCode = diracCode.replace(/^```(?:xml|html)?\n?/m, '').replace(/\n?```$/m, '').trim();
39
+ }
40
+
41
+ try {
42
+ // Parse the dynamic Dirac code
43
+ const parser = new DiracParser();
44
+ const dynamicAST = parser.parse(diracCode);
45
+
46
+ // Execute the dynamically generated code
47
+ await integrate(session, dynamicAST);
48
+
49
+ } catch (error) {
50
+ throw new Error(`Execute error: ${error instanceof Error ? error.message : String(error)}`);
51
+ }
52
+ }