dirac-lang 0.1.32 → 0.1.34
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/README.md +28 -0
- package/dist/{chunk-UYDP4ZFS.js → chunk-4LLFMVOW.js} +2 -2
- package/dist/{chunk-JMUUPZZA.js → chunk-4QLTSCDG.js} +1 -1
- package/dist/chunk-DRPHX3WX.js +166 -0
- package/dist/{chunk-JIWLKB5O.js → chunk-GLXVY235.js} +37 -1
- package/dist/{chunk-YRJ3SODI.js → chunk-HPGONBNW.js} +44 -19
- package/dist/cli.js +49 -170
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/{interpreter-WP3KMLST.js → interpreter-F65BCAYX.js} +3 -3
- package/dist/{session-UIWHLPTR.js → session-UBATJEND.js} +1 -1
- package/dist/shell-FHSPULIL.js +290 -0
- package/dist/{subroutine-I5XXJMFL.js → subroutine-V4D4LQIH.js} +2 -2
- package/dist/{tag-validator-QX47WU2J.js → tag-validator-3RLLFTY6.js} +1 -1
- package/dist/test-runner.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -255,3 +255,31 @@ npm install -g dirac-lang
|
|
|
255
255
|
---
|
|
256
256
|
|
|
257
257
|
*"In the quantum realm, a bra meets a ket to produce reality. In Dirac, a declaration meets an LLM to produce execution."*
|
|
258
|
+
|
|
259
|
+
## PAUL: The Human-Friendly Dirac Dialect
|
|
260
|
+
|
|
261
|
+
Dirac’s XML-based language is designed for robust machine execution and symbolic reasoning. For human authors, we introduce **PAUL** (Programming AI Utility Language)—a concise, bra/ket-inspired notation for writing Dirac programs quickly and intuitively.
|
|
262
|
+
|
|
263
|
+
- PAUL uses bra/ket syntax and positional arguments for readability.
|
|
264
|
+
- It is ideal for human editing, rapid prototyping, and LLM prompts.
|
|
265
|
+
- PAUL scripts are typically saved with the `.bk` extension.
|
|
266
|
+
- The Dirac interpreter translates PAUL to XML Dirac for execution.
|
|
267
|
+
|
|
268
|
+
**Example:**
|
|
269
|
+
|
|
270
|
+
PAUL (.bk):
|
|
271
|
+
```
|
|
272
|
+
|greet Alice>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Dirac XML (.di):
|
|
276
|
+
```xml
|
|
277
|
+
<greet name="Alice" />
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Note:**
|
|
281
|
+
- PAUL relies on conventions for mapping positional arguments to named parameters.
|
|
282
|
+
- For machine execution, always convert PAUL to XML Dirac.
|
|
283
|
+
- The `.bk` extension is recommended for PAUL scripts.
|
|
284
|
+
|
|
285
|
+
PAUL is the human-centric dialect of Dirac—optimized for clarity, speed, and LLM interaction.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
integrate
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HPGONBNW.js";
|
|
4
4
|
import {
|
|
5
5
|
DiracParser
|
|
6
6
|
} from "./chunk-HRHAMPOB.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
createSession,
|
|
9
9
|
getAvailableSubroutines,
|
|
10
10
|
getOutput
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GLXVY235.js";
|
|
12
12
|
|
|
13
13
|
// src/utils/llm-adapter.ts
|
|
14
14
|
function createLLMAdapter(session) {
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// src/runtime/braket-parser.ts
|
|
2
|
+
var BraKetParser = class {
|
|
3
|
+
lines = [];
|
|
4
|
+
currentLine = 0;
|
|
5
|
+
/**
|
|
6
|
+
* Parse bra-ket notation and compile to XML
|
|
7
|
+
*/
|
|
8
|
+
parse(source) {
|
|
9
|
+
this.lines = source.split("\n");
|
|
10
|
+
this.currentLine = 0;
|
|
11
|
+
const xml = ["<dirac>"];
|
|
12
|
+
this.parseBlock(xml, -1);
|
|
13
|
+
xml.push("</dirac>");
|
|
14
|
+
return xml.join("\n");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse a block of lines at a given indentation level
|
|
18
|
+
*/
|
|
19
|
+
parseBlock(output, parentIndent) {
|
|
20
|
+
while (this.currentLine < this.lines.length) {
|
|
21
|
+
const line = this.parseLine(this.lines[this.currentLine]);
|
|
22
|
+
if (line.type === "empty") {
|
|
23
|
+
this.currentLine++;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (line.indent <= parentIndent) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
if (line.type === "bra") {
|
|
30
|
+
const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : "";
|
|
31
|
+
output.push(`${" ".repeat(line.indent)}<subroutine name="${line.tag}"${attrs}>`);
|
|
32
|
+
this.currentLine++;
|
|
33
|
+
this.parseBlock(output, line.indent);
|
|
34
|
+
output.push(`${" ".repeat(line.indent)}</subroutine>`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (line.type === "ket") {
|
|
38
|
+
const indent = " ".repeat(line.indent);
|
|
39
|
+
const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : "";
|
|
40
|
+
const nextLine = this.currentLine + 1 < this.lines.length ? this.parseLine(this.lines[this.currentLine + 1]) : null;
|
|
41
|
+
if (nextLine && nextLine.indent > line.indent && nextLine.type !== "empty") {
|
|
42
|
+
output.push(`${indent}<${line.tag}${attrs}>`);
|
|
43
|
+
this.currentLine++;
|
|
44
|
+
this.parseBlock(output, line.indent);
|
|
45
|
+
output.push(`${indent}</${line.tag}>`);
|
|
46
|
+
} else {
|
|
47
|
+
if (line.text) {
|
|
48
|
+
const content = this.convertInlineKets(line.text);
|
|
49
|
+
output.push(`${indent}<${line.tag}${attrs}>${content}</${line.tag}>`);
|
|
50
|
+
} else {
|
|
51
|
+
output.push(`${indent}<${line.tag}${attrs}/>`);
|
|
52
|
+
}
|
|
53
|
+
this.currentLine++;
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (line.type === "text") {
|
|
58
|
+
const indent = " ".repeat(line.indent);
|
|
59
|
+
const content = this.convertInlineKets(line.text || "");
|
|
60
|
+
output.push(`${indent}${content}`);
|
|
61
|
+
this.currentLine++;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parse a single line into structured form
|
|
68
|
+
*/
|
|
69
|
+
parseLine(raw) {
|
|
70
|
+
const match = raw.match(/^(\s*)(.*)/);
|
|
71
|
+
const indent = match ? Math.floor(match[1].length / 2) : 0;
|
|
72
|
+
const content = match ? match[2] : "";
|
|
73
|
+
if (!content.trim()) {
|
|
74
|
+
return { indent, type: "empty", raw };
|
|
75
|
+
}
|
|
76
|
+
const braMatch = content.match(/^<([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^|]*)\|$/);
|
|
77
|
+
if (braMatch) {
|
|
78
|
+
return {
|
|
79
|
+
indent,
|
|
80
|
+
type: "bra",
|
|
81
|
+
tag: braMatch[1],
|
|
82
|
+
attrs: braMatch[2].trim() || void 0,
|
|
83
|
+
raw
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const ketMatch = content.match(/^\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>\s*(.*)/);
|
|
87
|
+
if (ketMatch) {
|
|
88
|
+
return {
|
|
89
|
+
indent,
|
|
90
|
+
type: "ket",
|
|
91
|
+
tag: ketMatch[1],
|
|
92
|
+
attrs: ketMatch[2].trim() || void 0,
|
|
93
|
+
text: ketMatch[3] || void 0,
|
|
94
|
+
raw
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
indent,
|
|
99
|
+
type: "text",
|
|
100
|
+
text: content,
|
|
101
|
+
raw
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Convert bra-ket attribute syntax to XML
|
|
106
|
+
* Examples:
|
|
107
|
+
* name=value → name="value"
|
|
108
|
+
* x=5 y=10 → x="5" y="10"
|
|
109
|
+
* select=@* → select="@*"
|
|
110
|
+
*/
|
|
111
|
+
convertAttributes(attrs) {
|
|
112
|
+
if (!attrs) return "";
|
|
113
|
+
const parts = [];
|
|
114
|
+
let current = "";
|
|
115
|
+
let inQuotes = false;
|
|
116
|
+
let quoteChar = "";
|
|
117
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
118
|
+
const char = attrs[i];
|
|
119
|
+
if ((char === '"' || char === "'") && (i === 0 || attrs[i - 1] !== "\\")) {
|
|
120
|
+
if (!inQuotes) {
|
|
121
|
+
inQuotes = true;
|
|
122
|
+
quoteChar = char;
|
|
123
|
+
current += char;
|
|
124
|
+
} else if (char === quoteChar) {
|
|
125
|
+
inQuotes = false;
|
|
126
|
+
current += char;
|
|
127
|
+
} else {
|
|
128
|
+
current += char;
|
|
129
|
+
}
|
|
130
|
+
} else if (char === " " && !inQuotes) {
|
|
131
|
+
if (current.trim()) {
|
|
132
|
+
parts.push(current.trim());
|
|
133
|
+
current = "";
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
current += char;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (current.trim()) {
|
|
140
|
+
parts.push(current.trim());
|
|
141
|
+
}
|
|
142
|
+
return parts.map((part) => {
|
|
143
|
+
const match = part.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=(.+)$/);
|
|
144
|
+
if (!match) return part;
|
|
145
|
+
const [, name, value] = match;
|
|
146
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
147
|
+
return `${name}=${value}`;
|
|
148
|
+
}
|
|
149
|
+
return `${name}="${value}"`;
|
|
150
|
+
}).join(" ");
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Convert inline kets within text content
|
|
154
|
+
* Example: "Hello |variable name=x> world" → "Hello <variable name="x"/> world"
|
|
155
|
+
*/
|
|
156
|
+
convertInlineKets(text) {
|
|
157
|
+
return text.replace(/\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>/g, (match, tag, attrs) => {
|
|
158
|
+
const attrStr = attrs.trim() ? ` ${this.convertAttributes(attrs.trim())}` : "";
|
|
159
|
+
return `<${tag}${attrStr}/>`;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
BraKetParser
|
|
166
|
+
};
|
|
@@ -51,6 +51,38 @@ var OllamaProvider = class {
|
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
// src/llm/custom.ts
|
|
55
|
+
var CustomLLMProvider = class {
|
|
56
|
+
client;
|
|
57
|
+
model;
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
this.client = new CustomLLMClient(options);
|
|
60
|
+
this.model = options.model || "default";
|
|
61
|
+
}
|
|
62
|
+
async complete(prompt, opts = {}) {
|
|
63
|
+
const messages = opts.messages || [
|
|
64
|
+
{ role: "user", content: prompt }
|
|
65
|
+
];
|
|
66
|
+
return await this.client.chat({ messages });
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var CustomLLMClient = class {
|
|
70
|
+
baseUrl;
|
|
71
|
+
constructor({ baseUrl = "http://localhost:5001" } = {}) {
|
|
72
|
+
this.baseUrl = baseUrl;
|
|
73
|
+
}
|
|
74
|
+
async chat({ messages }) {
|
|
75
|
+
const prompt = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
76
|
+
const res = await fetch(`${this.baseUrl}/chat`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify({ message: prompt })
|
|
80
|
+
});
|
|
81
|
+
const data = await res.json();
|
|
82
|
+
return data.response;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
54
86
|
// src/runtime/session.ts
|
|
55
87
|
function substituteAttribute(session, value) {
|
|
56
88
|
if (typeof value !== "string") return value;
|
|
@@ -81,8 +113,12 @@ function createSession(config = {}) {
|
|
|
81
113
|
if (!openaiKey) throw new Error("OPENAI_API_KEY required for OpenAI provider");
|
|
82
114
|
llmClient = new OpenAI({ apiKey: openaiKey });
|
|
83
115
|
break;
|
|
116
|
+
case "custom":
|
|
117
|
+
const customBaseUrl = config.customLLMUrl || process.env.CUSTOM_LLM_URL || "http://localhost:5001";
|
|
118
|
+
llmClient = new CustomLLMProvider({ baseUrl: customBaseUrl, model: ollamaModel });
|
|
119
|
+
break;
|
|
84
120
|
default:
|
|
85
|
-
throw new Error(`Unknown LLM provider: ${llmProvider}. Use 'ollama', 'anthropic', or '
|
|
121
|
+
throw new Error(`Unknown LLM provider: ${llmProvider}. Use 'ollama', 'anthropic', 'openai', or 'custom'.`);
|
|
86
122
|
}
|
|
87
123
|
}
|
|
88
124
|
return {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-HRHAMPOB.js";
|
|
4
4
|
import {
|
|
5
5
|
executeSubroutine
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4QLTSCDG.js";
|
|
7
7
|
import {
|
|
8
8
|
cleanSubroutinesToBoundary,
|
|
9
9
|
cleanToBoundary,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
substituteVariables,
|
|
26
26
|
throwException,
|
|
27
27
|
unsetExceptionBoundary
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-GLXVY235.js";
|
|
29
29
|
|
|
30
30
|
// src/tags/parameters.ts
|
|
31
31
|
async function executeParameters(session, element) {
|
|
@@ -257,7 +257,7 @@ async function executeCall(session, element) {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
async function registerExtendChain(session, subroutine, currentName) {
|
|
260
|
-
const { executeSubroutine: executeSubroutine2 } = await import("./subroutine-
|
|
260
|
+
const { executeSubroutine: executeSubroutine2 } = await import("./subroutine-V4D4LQIH.js");
|
|
261
261
|
const extendsAttr = subroutine.attributes.extends;
|
|
262
262
|
let parentName;
|
|
263
263
|
if (extendsAttr) {
|
|
@@ -425,12 +425,12 @@ async function executeIf(session, element) {
|
|
|
425
425
|
const condition = await evaluatePredicate(session, conditionElement);
|
|
426
426
|
if (condition) {
|
|
427
427
|
if (thenElement) {
|
|
428
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
428
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
429
429
|
await integrateChildren2(session, thenElement);
|
|
430
430
|
}
|
|
431
431
|
} else {
|
|
432
432
|
if (elseElement) {
|
|
433
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
433
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
434
434
|
await integrateChildren2(session, elseElement);
|
|
435
435
|
}
|
|
436
436
|
}
|
|
@@ -443,7 +443,7 @@ async function evaluatePredicate(session, predicateElement) {
|
|
|
443
443
|
return await evaluateCondition(session, predicateElement);
|
|
444
444
|
}
|
|
445
445
|
const outputLengthBefore = session.output.length;
|
|
446
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
446
|
+
const { integrate: integrate2 } = await import("./interpreter-F65BCAYX.js");
|
|
447
447
|
await integrate2(session, predicateElement);
|
|
448
448
|
const newOutputChunks = session.output.slice(outputLengthBefore);
|
|
449
449
|
const result = newOutputChunks.join("").trim();
|
|
@@ -466,11 +466,11 @@ async function evaluateCondition(session, condElement) {
|
|
|
466
466
|
}
|
|
467
467
|
const outputLengthBefore = session.output.length;
|
|
468
468
|
const args = [];
|
|
469
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
469
|
+
const { integrate: integrate2 } = await import("./interpreter-F65BCAYX.js");
|
|
470
470
|
for (const child of condElement.children) {
|
|
471
471
|
if (child.tag.toLowerCase() === "arg") {
|
|
472
472
|
const argOutputStart = session.output.length;
|
|
473
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
473
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
474
474
|
await integrateChildren2(session, child);
|
|
475
475
|
const newChunks = session.output.slice(argOutputStart);
|
|
476
476
|
const argValue = newChunks.join("");
|
|
@@ -531,7 +531,7 @@ function evaluateConditionType(evalType, args) {
|
|
|
531
531
|
// src/tags/llm.ts
|
|
532
532
|
async function executeLLM(session, element) {
|
|
533
533
|
if (!session.llmClient) {
|
|
534
|
-
throw new Error("<llm> tag requires LLM configuration. Set LLM_PROVIDER (ollama/anthropic/openai) and appropriate API keys in environment or config.yml");
|
|
534
|
+
throw new Error("<llm> tag requires LLM configuration. Set LLM_PROVIDER (ollama/anthropic/openai/custom) and appropriate API keys in environment or config.yml");
|
|
535
535
|
}
|
|
536
536
|
if (session.limits.currentLLMCalls >= session.limits.maxLLMCalls) {
|
|
537
537
|
throw new Error("Maximum LLM calls exceeded");
|
|
@@ -540,7 +540,8 @@ async function executeLLM(session, element) {
|
|
|
540
540
|
const providerName = session.llmClient.constructor.name;
|
|
541
541
|
const isOpenAI = providerName === "OpenAI";
|
|
542
542
|
const isOllama = providerName === "OllamaProvider";
|
|
543
|
-
const
|
|
543
|
+
const isCustom = providerName === "CustomLLMProvider";
|
|
544
|
+
const defaultModel = isOpenAI ? "gpt-4.1-2025-04-14" : isOllama ? "llama2" : isCustom ? "custom-model" : "claude-sonnet-4-20250514";
|
|
544
545
|
const model = element.attributes.model || process.env.DEFAULT_MODEL || defaultModel;
|
|
545
546
|
const outputVar = element.attributes.output;
|
|
546
547
|
const contextVar = element.attributes.context;
|
|
@@ -579,7 +580,7 @@ async function executeLLM(session, element) {
|
|
|
579
580
|
console.error("[LLM] Full prompt sent to LLM (noextra):\n" + prompt + "\n");
|
|
580
581
|
}
|
|
581
582
|
} else {
|
|
582
|
-
const { getAvailableSubroutines } = await import("./session-
|
|
583
|
+
const { getAvailableSubroutines } = await import("./session-UBATJEND.js");
|
|
583
584
|
const subroutines = getAvailableSubroutines(session);
|
|
584
585
|
if (session.debug) {
|
|
585
586
|
console.error(
|
|
@@ -647,6 +648,14 @@ then you call it like
|
|
|
647
648
|
temperature,
|
|
648
649
|
max_tokens: maxTokens
|
|
649
650
|
});
|
|
651
|
+
} else if (isCustom) {
|
|
652
|
+
const customPrompt = dialogHistory.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
653
|
+
result = await session.llmClient.complete(customPrompt, {
|
|
654
|
+
model,
|
|
655
|
+
temperature,
|
|
656
|
+
max_tokens: maxTokens,
|
|
657
|
+
messages: dialogHistory
|
|
658
|
+
});
|
|
650
659
|
} else {
|
|
651
660
|
const response = await session.llmClient.messages.create({
|
|
652
661
|
model,
|
|
@@ -706,7 +715,7 @@ ${result}
|
|
|
706
715
|
const parser = new DiracParser();
|
|
707
716
|
let dynamicAST = parser.parse(diracCode);
|
|
708
717
|
if (validateTags) {
|
|
709
|
-
const { validateDiracCode, applyCorrectedTags } = await import("./tag-validator-
|
|
718
|
+
const { validateDiracCode, applyCorrectedTags } = await import("./tag-validator-3RLLFTY6.js");
|
|
710
719
|
let validation = await validateDiracCode(session, dynamicAST, { autocorrect });
|
|
711
720
|
let retryCount = 0;
|
|
712
721
|
while (!validation.valid && retryCount < maxRetries) {
|
|
@@ -735,6 +744,14 @@ Please fix these errors and generate valid Dirac XML again. Remember to only use
|
|
|
735
744
|
temperature,
|
|
736
745
|
max_tokens: maxTokens
|
|
737
746
|
});
|
|
747
|
+
} else if (isCustom) {
|
|
748
|
+
const customPrompt = dialogHistory.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
749
|
+
result = await session.llmClient.complete(customPrompt, {
|
|
750
|
+
model,
|
|
751
|
+
temperature,
|
|
752
|
+
max_tokens: maxTokens,
|
|
753
|
+
messages: dialogHistory
|
|
754
|
+
});
|
|
738
755
|
} else {
|
|
739
756
|
const response = await session.llmClient.messages.create({
|
|
740
757
|
model,
|
|
@@ -815,6 +832,14 @@ ${feedbackPrompt}
|
|
|
815
832
|
temperature,
|
|
816
833
|
max_tokens: maxTokens
|
|
817
834
|
});
|
|
835
|
+
} else if (isCustom) {
|
|
836
|
+
const customPrompt = dialogHistory.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
837
|
+
result = await session.llmClient.complete(customPrompt, {
|
|
838
|
+
model,
|
|
839
|
+
temperature,
|
|
840
|
+
max_tokens: maxTokens,
|
|
841
|
+
messages: dialogHistory
|
|
842
|
+
});
|
|
818
843
|
} else {
|
|
819
844
|
const response = await session.llmClient.messages.create({
|
|
820
845
|
model,
|
|
@@ -1237,7 +1262,7 @@ async function getBestTagMatch(candidate, allowed) {
|
|
|
1237
1262
|
return { tag: allowed[bestIdx], score: bestScore };
|
|
1238
1263
|
}
|
|
1239
1264
|
async function executeTagCheck(session, element) {
|
|
1240
|
-
const { getAvailableSubroutines } = await import("./session-
|
|
1265
|
+
const { getAvailableSubroutines } = await import("./session-UBATJEND.js");
|
|
1241
1266
|
const subroutines = getAvailableSubroutines(session);
|
|
1242
1267
|
const allowed = new Set(subroutines.map((s) => s.name));
|
|
1243
1268
|
console.error("[tag-check] Allowed subroutines:", Array.from(allowed));
|
|
@@ -1330,7 +1355,7 @@ async function executeTagCheck(session, element) {
|
|
|
1330
1355
|
const executeTag = correctedTag || tagName;
|
|
1331
1356
|
console.error(`[tag-check] Executing <${executeTag}/> as all checks passed and execute=true.`);
|
|
1332
1357
|
const elementToExecute = correctedTag ? { ...child, tag: correctedTag } : child;
|
|
1333
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
1358
|
+
const { integrate: integrate2 } = await import("./interpreter-F65BCAYX.js");
|
|
1334
1359
|
await integrate2(session, elementToExecute);
|
|
1335
1360
|
}
|
|
1336
1361
|
}
|
|
@@ -1339,7 +1364,7 @@ async function executeTagCheck(session, element) {
|
|
|
1339
1364
|
// src/tags/throw.ts
|
|
1340
1365
|
async function executeThrow(session, element) {
|
|
1341
1366
|
const exceptionName = element.attributes?.name || "exception";
|
|
1342
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1367
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
1343
1368
|
const exceptionDom = {
|
|
1344
1369
|
tag: "exception-content",
|
|
1345
1370
|
attributes: { name: exceptionName },
|
|
@@ -1352,7 +1377,7 @@ async function executeThrow(session, element) {
|
|
|
1352
1377
|
// src/tags/try.ts
|
|
1353
1378
|
async function executeTry(session, element) {
|
|
1354
1379
|
setExceptionBoundary(session);
|
|
1355
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1380
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
1356
1381
|
await integrateChildren2(session, element);
|
|
1357
1382
|
unsetExceptionBoundary(session);
|
|
1358
1383
|
}
|
|
@@ -1362,7 +1387,7 @@ async function executeCatch(session, element) {
|
|
|
1362
1387
|
const exceptionName = element.attributes?.name || "exception";
|
|
1363
1388
|
const caughtCount = lookupException(session, exceptionName);
|
|
1364
1389
|
if (caughtCount > 0) {
|
|
1365
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1390
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
1366
1391
|
await integrateChildren2(session, element);
|
|
1367
1392
|
}
|
|
1368
1393
|
flushCurrentException(session);
|
|
@@ -1371,7 +1396,7 @@ async function executeCatch(session, element) {
|
|
|
1371
1396
|
// src/tags/exception.ts
|
|
1372
1397
|
async function executeException(session, element) {
|
|
1373
1398
|
const exceptions = getCurrentExceptions(session);
|
|
1374
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1399
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-F65BCAYX.js");
|
|
1375
1400
|
for (const exceptionDom of exceptions) {
|
|
1376
1401
|
await integrateChildren2(session, exceptionDom);
|
|
1377
1402
|
}
|
|
@@ -1511,7 +1536,7 @@ async function executeForeach(session, element) {
|
|
|
1511
1536
|
const parser2 = new DiracParser2();
|
|
1512
1537
|
try {
|
|
1513
1538
|
const fromElement = parser2.parse(fromAttr);
|
|
1514
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
1539
|
+
const { integrate: integrate2 } = await import("./interpreter-F65BCAYX.js");
|
|
1515
1540
|
await integrate2(session, fromElement);
|
|
1516
1541
|
} catch (e) {
|
|
1517
1542
|
session.output = savedOutput;
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
BraKetParser
|
|
4
|
+
} from "./chunk-DRPHX3WX.js";
|
|
2
5
|
import {
|
|
3
6
|
execute
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-4LLFMVOW.js";
|
|
8
|
+
import "./chunk-HPGONBNW.js";
|
|
6
9
|
import "./chunk-HRHAMPOB.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-4QLTSCDG.js";
|
|
11
|
+
import "./chunk-GLXVY235.js";
|
|
9
12
|
|
|
10
13
|
// src/cli.ts
|
|
11
14
|
import "dotenv/config";
|
|
@@ -13,7 +16,7 @@ import "dotenv/config";
|
|
|
13
16
|
// package.json
|
|
14
17
|
var package_default = {
|
|
15
18
|
name: "dirac-lang",
|
|
16
|
-
version: "0.1.
|
|
19
|
+
version: "0.1.34",
|
|
17
20
|
description: "LLM-Augmented Declarative Execution",
|
|
18
21
|
type: "module",
|
|
19
22
|
main: "dist/index.js",
|
|
@@ -63,175 +66,14 @@ var package_default = {
|
|
|
63
66
|
import fs from "fs";
|
|
64
67
|
import yaml from "js-yaml";
|
|
65
68
|
import { resolve, extname } from "path";
|
|
66
|
-
|
|
67
|
-
// src/runtime/braket-parser.ts
|
|
68
|
-
var BraKetParser = class {
|
|
69
|
-
lines = [];
|
|
70
|
-
currentLine = 0;
|
|
71
|
-
/**
|
|
72
|
-
* Parse bra-ket notation and compile to XML
|
|
73
|
-
*/
|
|
74
|
-
parse(source) {
|
|
75
|
-
this.lines = source.split("\n");
|
|
76
|
-
this.currentLine = 0;
|
|
77
|
-
const xml = ["<dirac>"];
|
|
78
|
-
this.parseBlock(xml, -1);
|
|
79
|
-
xml.push("</dirac>");
|
|
80
|
-
return xml.join("\n");
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Parse a block of lines at a given indentation level
|
|
84
|
-
*/
|
|
85
|
-
parseBlock(output, parentIndent) {
|
|
86
|
-
while (this.currentLine < this.lines.length) {
|
|
87
|
-
const line = this.parseLine(this.lines[this.currentLine]);
|
|
88
|
-
if (line.type === "empty") {
|
|
89
|
-
this.currentLine++;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (line.indent <= parentIndent) {
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
if (line.type === "bra") {
|
|
96
|
-
const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : "";
|
|
97
|
-
output.push(`${" ".repeat(line.indent)}<subroutine name="${line.tag}"${attrs}>`);
|
|
98
|
-
this.currentLine++;
|
|
99
|
-
this.parseBlock(output, line.indent);
|
|
100
|
-
output.push(`${" ".repeat(line.indent)}</subroutine>`);
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
if (line.type === "ket") {
|
|
104
|
-
const indent = " ".repeat(line.indent);
|
|
105
|
-
const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : "";
|
|
106
|
-
const nextLine = this.currentLine + 1 < this.lines.length ? this.parseLine(this.lines[this.currentLine + 1]) : null;
|
|
107
|
-
if (nextLine && nextLine.indent > line.indent && nextLine.type !== "empty") {
|
|
108
|
-
output.push(`${indent}<${line.tag}${attrs}>`);
|
|
109
|
-
this.currentLine++;
|
|
110
|
-
this.parseBlock(output, line.indent);
|
|
111
|
-
output.push(`${indent}</${line.tag}>`);
|
|
112
|
-
} else {
|
|
113
|
-
if (line.text) {
|
|
114
|
-
const content = this.convertInlineKets(line.text);
|
|
115
|
-
output.push(`${indent}<${line.tag}${attrs}>${content}</${line.tag}>`);
|
|
116
|
-
} else {
|
|
117
|
-
output.push(`${indent}<${line.tag}${attrs}/>`);
|
|
118
|
-
}
|
|
119
|
-
this.currentLine++;
|
|
120
|
-
}
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (line.type === "text") {
|
|
124
|
-
const indent = " ".repeat(line.indent);
|
|
125
|
-
const content = this.convertInlineKets(line.text || "");
|
|
126
|
-
output.push(`${indent}${content}`);
|
|
127
|
-
this.currentLine++;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Parse a single line into structured form
|
|
134
|
-
*/
|
|
135
|
-
parseLine(raw) {
|
|
136
|
-
const match = raw.match(/^(\s*)(.*)/);
|
|
137
|
-
const indent = match ? Math.floor(match[1].length / 2) : 0;
|
|
138
|
-
const content = match ? match[2] : "";
|
|
139
|
-
if (!content.trim()) {
|
|
140
|
-
return { indent, type: "empty", raw };
|
|
141
|
-
}
|
|
142
|
-
const braMatch = content.match(/^<([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^|]*)\|$/);
|
|
143
|
-
if (braMatch) {
|
|
144
|
-
return {
|
|
145
|
-
indent,
|
|
146
|
-
type: "bra",
|
|
147
|
-
tag: braMatch[1],
|
|
148
|
-
attrs: braMatch[2].trim() || void 0,
|
|
149
|
-
raw
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
const ketMatch = content.match(/^\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>\s*(.*)/);
|
|
153
|
-
if (ketMatch) {
|
|
154
|
-
return {
|
|
155
|
-
indent,
|
|
156
|
-
type: "ket",
|
|
157
|
-
tag: ketMatch[1],
|
|
158
|
-
attrs: ketMatch[2].trim() || void 0,
|
|
159
|
-
text: ketMatch[3] || void 0,
|
|
160
|
-
raw
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
indent,
|
|
165
|
-
type: "text",
|
|
166
|
-
text: content,
|
|
167
|
-
raw
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Convert bra-ket attribute syntax to XML
|
|
172
|
-
* Examples:
|
|
173
|
-
* name=value → name="value"
|
|
174
|
-
* x=5 y=10 → x="5" y="10"
|
|
175
|
-
* select=@* → select="@*"
|
|
176
|
-
*/
|
|
177
|
-
convertAttributes(attrs) {
|
|
178
|
-
if (!attrs) return "";
|
|
179
|
-
const parts = [];
|
|
180
|
-
let current = "";
|
|
181
|
-
let inQuotes = false;
|
|
182
|
-
let quoteChar = "";
|
|
183
|
-
for (let i = 0; i < attrs.length; i++) {
|
|
184
|
-
const char = attrs[i];
|
|
185
|
-
if ((char === '"' || char === "'") && (i === 0 || attrs[i - 1] !== "\\")) {
|
|
186
|
-
if (!inQuotes) {
|
|
187
|
-
inQuotes = true;
|
|
188
|
-
quoteChar = char;
|
|
189
|
-
current += char;
|
|
190
|
-
} else if (char === quoteChar) {
|
|
191
|
-
inQuotes = false;
|
|
192
|
-
current += char;
|
|
193
|
-
} else {
|
|
194
|
-
current += char;
|
|
195
|
-
}
|
|
196
|
-
} else if (char === " " && !inQuotes) {
|
|
197
|
-
if (current.trim()) {
|
|
198
|
-
parts.push(current.trim());
|
|
199
|
-
current = "";
|
|
200
|
-
}
|
|
201
|
-
} else {
|
|
202
|
-
current += char;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (current.trim()) {
|
|
206
|
-
parts.push(current.trim());
|
|
207
|
-
}
|
|
208
|
-
return parts.map((part) => {
|
|
209
|
-
const match = part.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=(.+)$/);
|
|
210
|
-
if (!match) return part;
|
|
211
|
-
const [, name, value] = match;
|
|
212
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
213
|
-
return `${name}=${value}`;
|
|
214
|
-
}
|
|
215
|
-
return `${name}="${value}"`;
|
|
216
|
-
}).join(" ");
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Convert inline kets within text content
|
|
220
|
-
* Example: "Hello |variable name=x> world" → "Hello <variable name="x"/> world"
|
|
221
|
-
*/
|
|
222
|
-
convertInlineKets(text) {
|
|
223
|
-
return text.replace(/\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>/g, (match, tag, attrs) => {
|
|
224
|
-
const attrStr = attrs.trim() ? ` ${this.convertAttributes(attrs.trim())}` : "";
|
|
225
|
-
return `<${tag}${attrStr}/>`;
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
// src/cli.ts
|
|
231
69
|
async function main() {
|
|
232
70
|
const args = process.argv.slice(2);
|
|
233
71
|
if (args.includes("--help") || args.includes("-h")) {
|
|
234
72
|
console.log("Usage: dirac <file.di|file.bk>");
|
|
73
|
+
console.log(" dirac shell [options]");
|
|
74
|
+
console.log("");
|
|
75
|
+
console.log("Commands:");
|
|
76
|
+
console.log(" shell Start interactive shell (REPL)");
|
|
235
77
|
console.log("");
|
|
236
78
|
console.log("File formats:");
|
|
237
79
|
console.log(" .di XML notation (verbose)");
|
|
@@ -245,14 +87,51 @@ async function main() {
|
|
|
245
87
|
console.log(" --model <name> Set default LLM model");
|
|
246
88
|
console.log(" --max-llm <n> Maximum LLM calls (default: 100)");
|
|
247
89
|
console.log(" --max-depth <n> Maximum recursion depth (default: 50)");
|
|
90
|
+
console.log(" -f, --config <path> Path to config.yml file");
|
|
248
91
|
process.exit(0);
|
|
249
92
|
}
|
|
250
93
|
if (args.includes("--version") || args.includes("-v")) {
|
|
251
94
|
console.log(package_default.version);
|
|
252
95
|
process.exit(0);
|
|
253
96
|
}
|
|
97
|
+
if (args[0] === "shell") {
|
|
98
|
+
const { DiracShell } = await import("./shell-FHSPULIL.js");
|
|
99
|
+
const shellConfig = { debug: false };
|
|
100
|
+
for (let i = 1; i < args.length; i++) {
|
|
101
|
+
const arg = args[i];
|
|
102
|
+
if (arg === "--debug") {
|
|
103
|
+
shellConfig.debug = true;
|
|
104
|
+
} else if ((arg === "-f" || arg === "--config") && i + 1 < args.length) {
|
|
105
|
+
const configPath = resolve(args[++i]);
|
|
106
|
+
if (fs.existsSync(configPath)) {
|
|
107
|
+
const configData = yaml.load(fs.readFileSync(configPath, "utf-8"));
|
|
108
|
+
Object.assign(shellConfig, {
|
|
109
|
+
llmProvider: configData.llmProvider,
|
|
110
|
+
llmModel: configData.llmModel,
|
|
111
|
+
customLLMUrl: configData.customLLMUrl
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!shellConfig.llmProvider) {
|
|
117
|
+
const defaultConfigPath = resolve(process.cwd(), "config.yml");
|
|
118
|
+
if (fs.existsSync(defaultConfigPath)) {
|
|
119
|
+
try {
|
|
120
|
+
const configData = yaml.load(fs.readFileSync(defaultConfigPath, "utf-8"));
|
|
121
|
+
shellConfig.llmProvider = shellConfig.llmProvider || configData.llmProvider;
|
|
122
|
+
shellConfig.llmModel = shellConfig.llmModel || configData.llmModel;
|
|
123
|
+
shellConfig.customLLMUrl = shellConfig.customLLMUrl || configData.customLLMUrl;
|
|
124
|
+
} catch (err) {
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const shell = new DiracShell(shellConfig);
|
|
129
|
+
shell.start();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
254
132
|
if (args.length === 0) {
|
|
255
133
|
console.error("Usage: dirac <file.di|file.bk>");
|
|
134
|
+
console.error(" dirac shell [options]");
|
|
256
135
|
console.error("Try dirac --help for more information.");
|
|
257
136
|
process.exit(1);
|
|
258
137
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,19 +2,19 @@ import {
|
|
|
2
2
|
createLLMAdapter,
|
|
3
3
|
execute,
|
|
4
4
|
executeUserCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4LLFMVOW.js";
|
|
6
6
|
import {
|
|
7
7
|
integrate
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HPGONBNW.js";
|
|
9
9
|
import {
|
|
10
10
|
DiracParser
|
|
11
11
|
} from "./chunk-HRHAMPOB.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-4QLTSCDG.js";
|
|
13
13
|
import {
|
|
14
14
|
createSession,
|
|
15
15
|
getAvailableSubroutines,
|
|
16
16
|
getOutput
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-GLXVY235.js";
|
|
18
18
|
export {
|
|
19
19
|
DiracParser,
|
|
20
20
|
createLLMAdapter,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
integrate,
|
|
3
3
|
integrateChildren
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HPGONBNW.js";
|
|
5
5
|
import "./chunk-HRHAMPOB.js";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-4QLTSCDG.js";
|
|
7
|
+
import "./chunk-GLXVY235.js";
|
|
8
8
|
export {
|
|
9
9
|
integrate,
|
|
10
10
|
integrateChildren
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
BraKetParser
|
|
4
|
+
} from "./chunk-DRPHX3WX.js";
|
|
5
|
+
import {
|
|
6
|
+
integrate
|
|
7
|
+
} from "./chunk-HPGONBNW.js";
|
|
8
|
+
import {
|
|
9
|
+
DiracParser
|
|
10
|
+
} from "./chunk-HRHAMPOB.js";
|
|
11
|
+
import "./chunk-4QLTSCDG.js";
|
|
12
|
+
import {
|
|
13
|
+
createSession
|
|
14
|
+
} from "./chunk-GLXVY235.js";
|
|
15
|
+
|
|
16
|
+
// src/shell.ts
|
|
17
|
+
import * as readline from "readline";
|
|
18
|
+
import * as fs from "fs";
|
|
19
|
+
import * as path from "path";
|
|
20
|
+
import * as os from "os";
|
|
21
|
+
import yaml from "js-yaml";
|
|
22
|
+
var HISTORY_FILE = path.join(os.homedir(), ".dirac_history");
|
|
23
|
+
var MAX_HISTORY = 1e3;
|
|
24
|
+
var DiracShell = class {
|
|
25
|
+
session;
|
|
26
|
+
braketParser;
|
|
27
|
+
xmlParser;
|
|
28
|
+
rl;
|
|
29
|
+
inputBuffer = [];
|
|
30
|
+
baseIndent = null;
|
|
31
|
+
config;
|
|
32
|
+
constructor(config = {}) {
|
|
33
|
+
this.config = config;
|
|
34
|
+
this.session = createSession(config);
|
|
35
|
+
this.braketParser = new BraKetParser();
|
|
36
|
+
this.xmlParser = new DiracParser();
|
|
37
|
+
this.rl = readline.createInterface({
|
|
38
|
+
input: process.stdin,
|
|
39
|
+
output: process.stdout,
|
|
40
|
+
prompt: "> ",
|
|
41
|
+
historySize: MAX_HISTORY
|
|
42
|
+
});
|
|
43
|
+
this.loadHistory();
|
|
44
|
+
this.setupHandlers();
|
|
45
|
+
}
|
|
46
|
+
loadHistory() {
|
|
47
|
+
try {
|
|
48
|
+
if (fs.existsSync(HISTORY_FILE)) {
|
|
49
|
+
const history = fs.readFileSync(HISTORY_FILE, "utf-8").split("\n").filter((line) => line.trim()).slice(-MAX_HISTORY);
|
|
50
|
+
this.rl.history = history.reverse();
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
saveHistory() {
|
|
56
|
+
try {
|
|
57
|
+
const history = this.rl.history.slice().reverse().join("\n");
|
|
58
|
+
fs.writeFileSync(HISTORY_FILE, history, "utf-8");
|
|
59
|
+
} catch (err) {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
setupHandlers() {
|
|
63
|
+
this.rl.on("line", async (input) => {
|
|
64
|
+
await this.handleInput(input);
|
|
65
|
+
});
|
|
66
|
+
this.rl.on("close", () => {
|
|
67
|
+
this.saveHistory();
|
|
68
|
+
console.log("\nGoodbye!");
|
|
69
|
+
process.exit(0);
|
|
70
|
+
});
|
|
71
|
+
this.rl.on("SIGINT", () => {
|
|
72
|
+
if (this.inputBuffer.length > 0) {
|
|
73
|
+
this.inputBuffer = [];
|
|
74
|
+
this.baseIndent = null;
|
|
75
|
+
console.log("\n(Input cancelled)");
|
|
76
|
+
this.rl.setPrompt("> ");
|
|
77
|
+
this.rl.prompt();
|
|
78
|
+
} else {
|
|
79
|
+
this.rl.close();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async handleInput(input) {
|
|
84
|
+
if (!this.inputBuffer.length && input.trim().startsWith(":")) {
|
|
85
|
+
await this.handleCommand(input.trim());
|
|
86
|
+
this.rl.prompt();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const indent = this.getIndent(input);
|
|
90
|
+
if (this.inputBuffer.length === 0) {
|
|
91
|
+
this.inputBuffer.push(input);
|
|
92
|
+
this.baseIndent = indent;
|
|
93
|
+
if (this.needsContinuation(input)) {
|
|
94
|
+
this.rl.setPrompt("... ");
|
|
95
|
+
console.log(" (Press Enter on empty line to execute, or Ctrl+C to cancel)");
|
|
96
|
+
this.rl.prompt();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
if (input.trim() === "") {
|
|
101
|
+
await this.executeBuffer();
|
|
102
|
+
this.rl.setPrompt("> ");
|
|
103
|
+
this.rl.prompt();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.inputBuffer.push(input);
|
|
107
|
+
this.rl.setPrompt("... ");
|
|
108
|
+
this.rl.prompt();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
await this.executeBuffer();
|
|
112
|
+
this.rl.prompt();
|
|
113
|
+
}
|
|
114
|
+
getIndent(line) {
|
|
115
|
+
const match = line.match(/^(\s*)/);
|
|
116
|
+
return match ? match[1].length : 0;
|
|
117
|
+
}
|
|
118
|
+
needsContinuation(line) {
|
|
119
|
+
const trimmed = line.trim();
|
|
120
|
+
if (trimmed.match(/^<[a-zA-Z_][a-zA-Z0-9_-]*.*\|$/)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
const ketMatch = trimmed.match(/^\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>\s*(.*)$/);
|
|
124
|
+
if (ketMatch && !ketMatch[3]) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
async executeBuffer() {
|
|
130
|
+
if (this.inputBuffer.length === 0) return;
|
|
131
|
+
const input = this.inputBuffer.join("\n");
|
|
132
|
+
this.inputBuffer = [];
|
|
133
|
+
this.baseIndent = null;
|
|
134
|
+
try {
|
|
135
|
+
this.session.output = [];
|
|
136
|
+
const xml = this.braketParser.parse(input);
|
|
137
|
+
if (this.config.debug) {
|
|
138
|
+
console.log("[Debug] Generated XML:\n", xml);
|
|
139
|
+
}
|
|
140
|
+
const ast = this.xmlParser.parse(xml);
|
|
141
|
+
await integrate(this.session, ast);
|
|
142
|
+
if (this.session.output.length > 0) {
|
|
143
|
+
console.log(this.session.output.join(""));
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
147
|
+
if (this.config.debug && error instanceof Error && error.stack) {
|
|
148
|
+
console.error(error.stack);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async handleCommand(cmd) {
|
|
153
|
+
const parts = cmd.slice(1).split(/\s+/);
|
|
154
|
+
const command = parts[0];
|
|
155
|
+
const args = parts.slice(1);
|
|
156
|
+
switch (command) {
|
|
157
|
+
case "help":
|
|
158
|
+
console.log(`
|
|
159
|
+
Dirac Shell - Interactive REPL
|
|
160
|
+
|
|
161
|
+
Commands:
|
|
162
|
+
:help Show this help
|
|
163
|
+
:vars List all variables
|
|
164
|
+
:subs List all subroutines
|
|
165
|
+
:clear Clear session (reset variables and subroutines)
|
|
166
|
+
:debug Toggle debug mode
|
|
167
|
+
:config Show current configuration
|
|
168
|
+
:exit Exit shell
|
|
169
|
+
|
|
170
|
+
Syntax:
|
|
171
|
+
|tag attrs>text Ket notation (most tags)
|
|
172
|
+
<name| Bra notation (subroutine definitions)
|
|
173
|
+
|output>content Indented children
|
|
174
|
+
|
|
175
|
+
Multi-line Input:
|
|
176
|
+
- Type a line that needs continuation (like <greeting| or |llm>)
|
|
177
|
+
- Shell switches to '...' prompt
|
|
178
|
+
- Type your content lines (add spaces for indentation manually)
|
|
179
|
+
- Press ENTER on an empty line to execute
|
|
180
|
+
- Or press Ctrl+C to cancel
|
|
181
|
+
|
|
182
|
+
Note: You must manually add spaces for indentation (2 spaces per level)
|
|
183
|
+
|
|
184
|
+
Examples:
|
|
185
|
+
|output>Hello World
|
|
186
|
+
|defvar name=count value=5>
|
|
187
|
+
|llm>create a greeting subroutine
|
|
188
|
+
<greeting| name=String
|
|
189
|
+
|output>Hello |variable name=name>
|
|
190
|
+
|greeting name=World>
|
|
191
|
+
`);
|
|
192
|
+
break;
|
|
193
|
+
case "vars":
|
|
194
|
+
if (this.session.variables.length === 0) {
|
|
195
|
+
console.log("No variables defined");
|
|
196
|
+
} else {
|
|
197
|
+
console.log("Variables:");
|
|
198
|
+
for (const v of this.session.variables) {
|
|
199
|
+
if (v.visible) {
|
|
200
|
+
console.log(` ${v.name} = ${JSON.stringify(v.value)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
case "subs":
|
|
206
|
+
if (this.session.subroutines.length === 0) {
|
|
207
|
+
console.log("No subroutines defined");
|
|
208
|
+
} else {
|
|
209
|
+
console.log("Subroutines:");
|
|
210
|
+
for (const s of this.session.subroutines) {
|
|
211
|
+
const params = s.parameters?.map((p) => p.name).join(", ") || "";
|
|
212
|
+
console.log(` ${s.name}(${params})`);
|
|
213
|
+
if (s.description) {
|
|
214
|
+
console.log(` ${s.description}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
case "clear":
|
|
220
|
+
this.session.variables = [];
|
|
221
|
+
this.session.subroutines = [];
|
|
222
|
+
this.session.varBoundary = 0;
|
|
223
|
+
this.session.subBoundary = 0;
|
|
224
|
+
console.log("Session cleared");
|
|
225
|
+
break;
|
|
226
|
+
case "debug":
|
|
227
|
+
this.config.debug = !this.config.debug;
|
|
228
|
+
this.session.debug = this.config.debug;
|
|
229
|
+
console.log(`Debug mode: ${this.config.debug ? "ON" : "OFF"}`);
|
|
230
|
+
break;
|
|
231
|
+
case "config":
|
|
232
|
+
console.log("Configuration:");
|
|
233
|
+
console.log(` LLM Provider: ${this.config.llmProvider || "none"}`);
|
|
234
|
+
console.log(` LLM Model: ${this.config.llmModel || "default"}`);
|
|
235
|
+
console.log(` Debug: ${this.config.debug ? "ON" : "OFF"}`);
|
|
236
|
+
if (this.config.customLLMUrl) {
|
|
237
|
+
console.log(` Custom LLM URL: ${this.config.customLLMUrl}`);
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
case "exit":
|
|
241
|
+
case "quit":
|
|
242
|
+
this.rl.close();
|
|
243
|
+
break;
|
|
244
|
+
default:
|
|
245
|
+
console.log(`Unknown command: ${command}. Type :help for available commands.`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
start() {
|
|
249
|
+
console.log("Dirac Shell v0.1.0");
|
|
250
|
+
console.log("Type :help for commands, :exit to quit\n");
|
|
251
|
+
if (this.config.llmProvider) {
|
|
252
|
+
console.log(`LLM: ${this.config.llmProvider} (${this.config.llmModel || "default"})
|
|
253
|
+
`);
|
|
254
|
+
} else {
|
|
255
|
+
console.log("Warning: No LLM provider configured. Set LLM_PROVIDER environment variable.\n");
|
|
256
|
+
}
|
|
257
|
+
this.rl.prompt();
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
async function main() {
|
|
261
|
+
let config = {
|
|
262
|
+
debug: process.env.DEBUG === "1"
|
|
263
|
+
};
|
|
264
|
+
const configPath = path.join(process.cwd(), "config.yml");
|
|
265
|
+
if (fs.existsSync(configPath)) {
|
|
266
|
+
try {
|
|
267
|
+
const configData = yaml.load(fs.readFileSync(configPath, "utf-8"));
|
|
268
|
+
config = {
|
|
269
|
+
...config,
|
|
270
|
+
llmProvider: configData.llmProvider || process.env.LLM_PROVIDER,
|
|
271
|
+
llmModel: configData.llmModel || process.env.LLM_MODEL,
|
|
272
|
+
customLLMUrl: configData.customLLMUrl || process.env.CUSTOM_LLM_URL
|
|
273
|
+
};
|
|
274
|
+
} catch (err) {
|
|
275
|
+
console.error("Warning: Could not load config.yml");
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
config.llmProvider = process.env.LLM_PROVIDER;
|
|
279
|
+
config.llmModel = process.env.LLM_MODEL;
|
|
280
|
+
config.customLLMUrl = process.env.CUSTOM_LLM_URL;
|
|
281
|
+
}
|
|
282
|
+
const shell = new DiracShell(config);
|
|
283
|
+
shell.start();
|
|
284
|
+
}
|
|
285
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
286
|
+
main();
|
|
287
|
+
}
|
|
288
|
+
export {
|
|
289
|
+
DiracShell
|
|
290
|
+
};
|
|
@@ -49,7 +49,7 @@ async function getBestTagMatch(candidate, allowed) {
|
|
|
49
49
|
}
|
|
50
50
|
async function validateTag(session, element, options = {}) {
|
|
51
51
|
const { autocorrect = false, similarityCutoff = SIMILARITY_CUTOFF } = options;
|
|
52
|
-
const { getAvailableSubroutines } = await import("./session-
|
|
52
|
+
const { getAvailableSubroutines } = await import("./session-UBATJEND.js");
|
|
53
53
|
const subroutines = getAvailableSubroutines(session);
|
|
54
54
|
const allowed = new Set(subroutines.map((s) => s.name));
|
|
55
55
|
const tagName = element.tag;
|
package/dist/test-runner.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
integrate
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HPGONBNW.js";
|
|
4
4
|
import {
|
|
5
5
|
DiracParser
|
|
6
6
|
} from "./chunk-HRHAMPOB.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-4QLTSCDG.js";
|
|
8
8
|
import {
|
|
9
9
|
createSession,
|
|
10
10
|
getOutput
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GLXVY235.js";
|
|
12
12
|
|
|
13
13
|
// src/test-runner.ts
|
|
14
14
|
import fs from "fs";
|