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 CHANGED
@@ -258,7 +258,7 @@ npm install -g dirac-lang
258
258
 
259
259
  ## PAUL: The Human-Friendly Dirac Dialect
260
260
 
261
- Diracs 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.
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-KIIETJFM.js";
6
- import "./chunk-YCUHRNXQ.js";
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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-YCUHRNXQ.js";
3
+ } from "./chunk-TYIDNAZ7.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
@@ -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
+ };