dirac-lang 0.1.74 → 0.1.77
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 +1 -1
- package/dist/{agent-TC34E2DB.js → agent-VAFUNYDM.js} +4 -3
- package/dist/{chunk-KIIETJFM.js → chunk-CLGQYGHT.js} +1 -1
- package/dist/chunk-FPDW535D.js +305 -0
- package/dist/{chunk-YCUHRNXQ.js → chunk-TYIDNAZ7.js} +63 -324
- package/dist/{chunk-2EUVDYHX.js → chunk-VUMS53GF.js} +1 -1
- package/dist/cli.js +49 -19
- package/dist/{cron-M5HO2H5T.js → cron-RWSM6IBB.js} +3 -2
- package/dist/index.js +4 -3
- package/dist/{interpreter-QVHRO4LN.js → interpreter-X5V2FFGI.js} +3 -2
- package/dist/{run-at-GP5XZP5W.js → run-at-3QL4C4UD.js} +3 -2
- package/dist/{schedule-FWAU6HDT.js → schedule-4B3KUC7T.js} +3 -2
- package/dist/{session-server-K6OZRYTZ.js → session-server-IDEV4CXY.js} +4 -3
- package/dist/{shell-EB5Z2U45.js → shell-IUWCSKPG.js} +58 -29
- package/dist/subroutine-index-7B5YXKAA.js +14 -0
- package/dist/test-runner.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -258,7 +258,7 @@ npm install -g dirac-lang
|
|
|
258
258
|
|
|
259
259
|
## PAUL: The Human-Friendly Dirac Dialect
|
|
260
260
|
|
|
261
|
-
Dirac
|
|
261
|
+
Dirac's XML-based language is designed for robust machine execution and symbolic reasoning. For human authors, we introduce **PAUL** (Pattern Action Utility Language)—a concise, bra/ket-inspired notation for writing Dirac programs quickly and intuitively.
|
|
262
262
|
|
|
263
263
|
- PAUL uses bra/ket syntax and positional arguments for readability.
|
|
264
264
|
- It is ideal for human editing, rapid prototyping, and LLM prompts.
|
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
SessionServer,
|
|
3
3
|
getSocketPath,
|
|
4
4
|
isSessionRunning
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-HRHAMPOB.js";
|
|
5
|
+
} from "./chunk-CLGQYGHT.js";
|
|
6
|
+
import "./chunk-TYIDNAZ7.js";
|
|
8
7
|
import "./chunk-VC23AJJJ.js";
|
|
8
|
+
import "./chunk-FPDW535D.js";
|
|
9
|
+
import "./chunk-HRHAMPOB.js";
|
|
9
10
|
import "./chunk-M57VI7KL.js";
|
|
10
11
|
|
|
11
12
|
// src/agent.ts
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DiracParser
|
|
3
|
+
} from "./chunk-HRHAMPOB.js";
|
|
4
|
+
import {
|
|
5
|
+
emit,
|
|
6
|
+
setVariable
|
|
7
|
+
} from "./chunk-M57VI7KL.js";
|
|
8
|
+
|
|
9
|
+
// src/runtime/subroutine-registry.ts
|
|
10
|
+
import * as fs from "fs";
|
|
11
|
+
import * as path from "path";
|
|
12
|
+
import * as os from "os";
|
|
13
|
+
var SubroutineRegistry = class {
|
|
14
|
+
indexPath;
|
|
15
|
+
index;
|
|
16
|
+
constructor(indexPath) {
|
|
17
|
+
this.indexPath = indexPath || path.join(os.homedir(), ".dirac", "subroutine-index.json");
|
|
18
|
+
this.index = this.loadIndex();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load index from disk
|
|
22
|
+
*/
|
|
23
|
+
loadIndex() {
|
|
24
|
+
if (fs.existsSync(this.indexPath)) {
|
|
25
|
+
try {
|
|
26
|
+
const data = fs.readFileSync(this.indexPath, "utf-8");
|
|
27
|
+
return JSON.parse(data);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error("Error loading subroutine index:", err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
subroutines: [],
|
|
34
|
+
lastUpdated: Date.now()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Save index to disk
|
|
39
|
+
*/
|
|
40
|
+
saveIndex() {
|
|
41
|
+
const dir = path.dirname(this.indexPath);
|
|
42
|
+
if (!fs.existsSync(dir)) {
|
|
43
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
this.index.lastUpdated = Date.now();
|
|
46
|
+
fs.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2), "utf-8");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Scan a directory for .di files and index all subroutines
|
|
50
|
+
*/
|
|
51
|
+
async indexDirectory(dirPath) {
|
|
52
|
+
let count = 0;
|
|
53
|
+
const absoluteDirPath = path.isAbsolute(dirPath) ? dirPath : path.resolve(process.cwd(), dirPath);
|
|
54
|
+
const scanDir = (dir) => {
|
|
55
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
const fullPath = path.join(dir, entry.name);
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
scanDir(fullPath);
|
|
60
|
+
} else if (entry.isFile() && entry.name.endsWith(".di")) {
|
|
61
|
+
count += this.indexFile(fullPath);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
scanDir(absoluteDirPath);
|
|
66
|
+
this.saveIndex();
|
|
67
|
+
return count;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Index a single .di file
|
|
71
|
+
*/
|
|
72
|
+
indexFile(filePath) {
|
|
73
|
+
try {
|
|
74
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
75
|
+
const parser = new DiracParser();
|
|
76
|
+
const ast = parser.parse(content);
|
|
77
|
+
this.index.subroutines = this.index.subroutines.filter((s) => s.filePath !== filePath);
|
|
78
|
+
const subroutines = this.extractSubroutines(ast, filePath);
|
|
79
|
+
this.index.subroutines.push(...subroutines);
|
|
80
|
+
this.saveIndex();
|
|
81
|
+
return subroutines.length;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (process.env.DEBUG_REGISTRY === "1") {
|
|
84
|
+
console.error(`Error indexing ${filePath}:`, err);
|
|
85
|
+
}
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Extract subroutines from AST
|
|
91
|
+
*/
|
|
92
|
+
extractSubroutines(element, filePath) {
|
|
93
|
+
const subroutines = [];
|
|
94
|
+
if (element.tag === "subroutine") {
|
|
95
|
+
const name = element.attributes.name;
|
|
96
|
+
if (name) {
|
|
97
|
+
const metadata = {
|
|
98
|
+
name,
|
|
99
|
+
description: element.attributes.description,
|
|
100
|
+
parameters: [],
|
|
101
|
+
filePath
|
|
102
|
+
};
|
|
103
|
+
for (const [attrName, attrValue] of Object.entries(element.attributes)) {
|
|
104
|
+
if (attrName.startsWith("param-")) {
|
|
105
|
+
const paramName = attrName.substring(6);
|
|
106
|
+
const parts = attrValue.split(":");
|
|
107
|
+
metadata.parameters.push({
|
|
108
|
+
name: paramName,
|
|
109
|
+
type: parts[0] || "any",
|
|
110
|
+
required: parts[1] === "required",
|
|
111
|
+
description: parts[2]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
subroutines.push(metadata);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (element.children) {
|
|
119
|
+
for (const child of element.children) {
|
|
120
|
+
subroutines.push(...this.extractSubroutines(child, filePath));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return subroutines;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Simple text search (will be replaced with vector search)
|
|
127
|
+
* Supports multi-word queries by tokenizing and matching individual words
|
|
128
|
+
*/
|
|
129
|
+
search(query, limit = 10) {
|
|
130
|
+
const lowerQuery = query.toLowerCase();
|
|
131
|
+
const queryTokens = lowerQuery.split(/[\s\-_]+/).filter((t) => t.length > 0);
|
|
132
|
+
const results = this.index.subroutines.map((sub) => {
|
|
133
|
+
let score = 0;
|
|
134
|
+
const lowerName = sub.name.toLowerCase();
|
|
135
|
+
const lowerDesc = (sub.description || "").toLowerCase();
|
|
136
|
+
const nameTokens = lowerName.split(/[\s\-_]+/);
|
|
137
|
+
if (lowerName === lowerQuery) {
|
|
138
|
+
score += 100;
|
|
139
|
+
} else if (lowerName.includes(lowerQuery)) {
|
|
140
|
+
score += 50;
|
|
141
|
+
} else if (lowerDesc.includes(lowerQuery)) {
|
|
142
|
+
score += 30;
|
|
143
|
+
}
|
|
144
|
+
let tokenMatchCount = 0;
|
|
145
|
+
for (const queryToken of queryTokens) {
|
|
146
|
+
if (queryToken.length <= 2) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (nameTokens.some((nt) => nt === queryToken)) {
|
|
150
|
+
score += 40;
|
|
151
|
+
tokenMatchCount++;
|
|
152
|
+
} else if (nameTokens.some((nt) => nt.startsWith(queryToken))) {
|
|
153
|
+
score += 20;
|
|
154
|
+
tokenMatchCount++;
|
|
155
|
+
}
|
|
156
|
+
const descWords = lowerDesc.split(/[\s\-_]+/);
|
|
157
|
+
if (descWords.some((w) => w === queryToken || w.startsWith(queryToken))) {
|
|
158
|
+
score += 15;
|
|
159
|
+
tokenMatchCount++;
|
|
160
|
+
}
|
|
161
|
+
for (const param of sub.parameters) {
|
|
162
|
+
const lowerParamName = param.name.toLowerCase();
|
|
163
|
+
if (lowerParamName === queryToken) {
|
|
164
|
+
score += 10;
|
|
165
|
+
tokenMatchCount++;
|
|
166
|
+
} else if (lowerParamName.startsWith(queryToken)) {
|
|
167
|
+
score += 5;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (queryTokens.length > 1 && tokenMatchCount >= queryTokens.length * 0.5) {
|
|
172
|
+
score += 25;
|
|
173
|
+
}
|
|
174
|
+
return { sub, score };
|
|
175
|
+
}).filter((r) => r.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map((r) => r.sub);
|
|
176
|
+
return results;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get all subroutines
|
|
180
|
+
*/
|
|
181
|
+
getAll() {
|
|
182
|
+
return this.index.subroutines;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get statistics
|
|
186
|
+
*/
|
|
187
|
+
getStats() {
|
|
188
|
+
const files = new Set(this.index.subroutines.map((s) => s.filePath));
|
|
189
|
+
return {
|
|
190
|
+
totalSubroutines: this.index.subroutines.length,
|
|
191
|
+
totalFiles: files.size,
|
|
192
|
+
lastUpdated: new Date(this.index.lastUpdated)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Auto-index stdlib if index is empty (first run)
|
|
197
|
+
* Returns true if indexing was performed
|
|
198
|
+
*/
|
|
199
|
+
async autoIndexStdlib() {
|
|
200
|
+
if (this.index.subroutines.length > 0) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const { createRequire } = await import("module");
|
|
205
|
+
const require2 = createRequire(import.meta.url);
|
|
206
|
+
const stdlibPackagePath = require2.resolve("dirac-stdlib/package.json");
|
|
207
|
+
const stdlibLibPath = path.join(path.dirname(stdlibPackagePath), "lib");
|
|
208
|
+
if (fs.existsSync(stdlibLibPath)) {
|
|
209
|
+
console.log("First run detected. Indexing standard library...");
|
|
210
|
+
const count = await this.indexDirectory(stdlibLibPath);
|
|
211
|
+
console.log(`Indexed ${count} subroutines from dirac-stdlib`);
|
|
212
|
+
console.log("You can now use |load-context> to find and load subroutines!\n");
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
} catch (err) {
|
|
216
|
+
}
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// src/tags/subroutine-index.ts
|
|
222
|
+
var registry = new SubroutineRegistry();
|
|
223
|
+
async function executeIndexSubroutines(session, element) {
|
|
224
|
+
const pathAttr = element.attributes.path;
|
|
225
|
+
if (!pathAttr) {
|
|
226
|
+
throw new Error("<index-subroutines> requires path attribute");
|
|
227
|
+
}
|
|
228
|
+
const count = await registry.indexDirectory(pathAttr);
|
|
229
|
+
if (session.debug) {
|
|
230
|
+
emit(session, `Indexed ${count} subroutines from ${pathAttr}
|
|
231
|
+
`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async function executeSearchSubroutines(session, element) {
|
|
235
|
+
const query = element.attributes.query;
|
|
236
|
+
const limitAttr = element.attributes.limit;
|
|
237
|
+
const outputVar = element.attributes.output;
|
|
238
|
+
const format = element.attributes.format || "text";
|
|
239
|
+
if (!query) {
|
|
240
|
+
throw new Error("<search-subroutines> requires query attribute");
|
|
241
|
+
}
|
|
242
|
+
const limit = limitAttr ? parseInt(limitAttr, 10) : 10;
|
|
243
|
+
const results = registry.search(query, limit);
|
|
244
|
+
let output = "";
|
|
245
|
+
switch (format) {
|
|
246
|
+
case "json":
|
|
247
|
+
output = JSON.stringify(results, null, 2);
|
|
248
|
+
break;
|
|
249
|
+
case "xml":
|
|
250
|
+
output = "<subroutines>\n";
|
|
251
|
+
for (const sub of results) {
|
|
252
|
+
const params = sub.parameters.map((p) => `param-${p.name}="${p.type}"`).join(" ");
|
|
253
|
+
output += ` <subroutine name="${sub.name}" ${params} file="${sub.filePath}"/>
|
|
254
|
+
`;
|
|
255
|
+
if (sub.description) {
|
|
256
|
+
output += ` <!-- ${sub.description} -->
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
output += "</subroutines>";
|
|
261
|
+
break;
|
|
262
|
+
case "text":
|
|
263
|
+
default:
|
|
264
|
+
if (results.length === 0) {
|
|
265
|
+
output = "No subroutines found.\n";
|
|
266
|
+
} else {
|
|
267
|
+
output = `Found ${results.length} subroutine(s):
|
|
268
|
+
|
|
269
|
+
`;
|
|
270
|
+
for (const sub of results) {
|
|
271
|
+
output += `${sub.name}(${sub.parameters.map((p) => p.name).join(", ")})
|
|
272
|
+
`;
|
|
273
|
+
if (sub.description) {
|
|
274
|
+
output += ` ${sub.description}
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
output += ` File: ${sub.filePath}
|
|
278
|
+
|
|
279
|
+
`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
if (outputVar) {
|
|
285
|
+
setVariable(session, outputVar, output, false);
|
|
286
|
+
} else {
|
|
287
|
+
emit(session, output);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async function executeRegistryStats(session, element) {
|
|
291
|
+
const stats = registry.getStats();
|
|
292
|
+
const output = `Subroutine Registry Statistics:
|
|
293
|
+
Total Subroutines: ${stats.totalSubroutines}
|
|
294
|
+
Total Files: ${stats.totalFiles}
|
|
295
|
+
Last Updated: ${stats.lastUpdated.toLocaleString()}
|
|
296
|
+
`;
|
|
297
|
+
emit(session, output);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export {
|
|
301
|
+
registry,
|
|
302
|
+
executeIndexSubroutines,
|
|
303
|
+
executeSearchSubroutines,
|
|
304
|
+
executeRegistryStats
|
|
305
|
+
};
|