dirac-lang 0.1.69 → 0.1.71

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.
@@ -2,8 +2,8 @@ import {
2
2
  SessionServer,
3
3
  getSocketPath,
4
4
  isSessionRunning
5
- } from "./chunk-65TBONV6.js";
6
- import "./chunk-QUFYZS2S.js";
5
+ } from "./chunk-YVI7T3DS.js";
6
+ import "./chunk-QPO3WKH2.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
8
  import "./chunk-VC23AJJJ.js";
9
9
  import "./chunk-M57VI7KL.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-QUFYZS2S.js";
3
+ } from "./chunk-QPO3WKH2.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
@@ -181,6 +181,7 @@ async function executeAssign(session, element) {
181
181
  const name = element.attributes.name;
182
182
  const valueAttr = element.attributes.value;
183
183
  const trimAttr = element.attributes.trim;
184
+ const typeAttr = element.attributes.type;
184
185
  if (!name) {
185
186
  throw new Error("<assign> requires name attribute");
186
187
  }
@@ -203,6 +204,12 @@ async function executeAssign(session, element) {
203
204
  if (trimAttr === "true" && typeof value === "string") {
204
205
  value = value.trim();
205
206
  }
207
+ if (typeAttr === "cat") {
208
+ const existingValue = getVariable(session, name);
209
+ if (existingValue !== void 0) {
210
+ value = String(existingValue) + String(value);
211
+ }
212
+ }
206
213
  for (let i = session.variables.length - 1; i >= 0; i--) {
207
214
  if (session.variables[i].name === name) {
208
215
  session.variables[i].value = value;
@@ -474,12 +481,12 @@ async function executeIf(session, element) {
474
481
  const condition = await evaluatePredicate(session, conditionElement);
475
482
  if (condition) {
476
483
  if (thenElement) {
477
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
484
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
478
485
  await integrateChildren2(session, thenElement);
479
486
  }
480
487
  } else {
481
488
  if (elseElement) {
482
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
489
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
483
490
  await integrateChildren2(session, elseElement);
484
491
  }
485
492
  }
@@ -492,7 +499,7 @@ async function evaluatePredicate(session, predicateElement) {
492
499
  return await evaluateCondition(session, predicateElement);
493
500
  }
494
501
  const outputLengthBefore = session.output.length;
495
- const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
502
+ const { integrate: integrate2 } = await import("./interpreter-Y2AU6RG6.js");
496
503
  await integrate2(session, predicateElement);
497
504
  const newOutputChunks = session.output.slice(outputLengthBefore);
498
505
  const result = newOutputChunks.join("").trim();
@@ -515,11 +522,11 @@ async function evaluateCondition(session, condElement) {
515
522
  }
516
523
  const outputLengthBefore = session.output.length;
517
524
  const args = [];
518
- const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
525
+ const { integrate: integrate2 } = await import("./interpreter-Y2AU6RG6.js");
519
526
  for (const child of condElement.children) {
520
527
  if (child.tag.toLowerCase() === "arg") {
521
528
  const argOutputStart = session.output.length;
522
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
529
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
523
530
  await integrateChildren2(session, child);
524
531
  const newChunks = session.output.slice(argOutputStart);
525
532
  const argValue = newChunks.join("");
@@ -1740,7 +1747,7 @@ async function executeTagCheck(session, element) {
1740
1747
  const executeTag = correctedTag || tagName;
1741
1748
  console.error(`[tag-check] Executing <${executeTag}/> as all checks passed and execute=true.`);
1742
1749
  const elementToExecute = correctedTag ? { ...child, tag: correctedTag } : child;
1743
- const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
1750
+ const { integrate: integrate2 } = await import("./interpreter-Y2AU6RG6.js");
1744
1751
  await integrate2(session, elementToExecute);
1745
1752
  }
1746
1753
  }
@@ -1749,7 +1756,7 @@ async function executeTagCheck(session, element) {
1749
1756
  // src/tags/throw.ts
1750
1757
  async function executeThrow(session, element) {
1751
1758
  const exceptionName = element.attributes?.name || "exception";
1752
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1759
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
1753
1760
  const exceptionDom = {
1754
1761
  tag: "exception-content",
1755
1762
  attributes: { name: exceptionName },
@@ -1762,7 +1769,7 @@ async function executeThrow(session, element) {
1762
1769
  // src/tags/try.ts
1763
1770
  async function executeTry(session, element) {
1764
1771
  setExceptionBoundary(session);
1765
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1772
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
1766
1773
  await integrateChildren2(session, element);
1767
1774
  unsetExceptionBoundary(session);
1768
1775
  }
@@ -1772,7 +1779,7 @@ async function executeCatch(session, element) {
1772
1779
  const exceptionName = element.attributes?.name || "exception";
1773
1780
  const caughtCount = lookupException(session, exceptionName);
1774
1781
  if (caughtCount > 0) {
1775
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1782
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
1776
1783
  await integrateChildren2(session, element);
1777
1784
  }
1778
1785
  flushCurrentException(session);
@@ -1781,7 +1788,7 @@ async function executeCatch(session, element) {
1781
1788
  // src/tags/exception.ts
1782
1789
  async function executeException(session, element) {
1783
1790
  const exceptions = getCurrentExceptions(session);
1784
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1791
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-Y2AU6RG6.js");
1785
1792
  for (const exceptionDom of exceptions) {
1786
1793
  await integrateChildren2(session, exceptionDom);
1787
1794
  }
@@ -2046,6 +2053,7 @@ var SubroutineRegistry = class {
2046
2053
  this.index.subroutines = this.index.subroutines.filter((s) => s.filePath !== filePath);
2047
2054
  const subroutines = this.extractSubroutines(ast, filePath);
2048
2055
  this.index.subroutines.push(...subroutines);
2056
+ this.saveIndex();
2049
2057
  return subroutines.length;
2050
2058
  } catch (err) {
2051
2059
  if (process.env.DEBUG_REGISTRY === "1") {
@@ -2242,14 +2250,13 @@ async function executeRegistryStats(session, element) {
2242
2250
  }
2243
2251
 
2244
2252
  // src/tags/load-context.ts
2245
- var registry2 = new SubroutineRegistry();
2246
2253
  async function executeLoadContext(session, element) {
2247
2254
  let query = element.attributes.query;
2248
2255
  if (!query && element.text) {
2249
2256
  query = element.text.trim();
2250
2257
  }
2251
2258
  if (!query && element.children.length > 0) {
2252
- const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
2259
+ const { integrate: integrate2 } = await import("./interpreter-Y2AU6RG6.js");
2253
2260
  const beforeOutput = session.output.length;
2254
2261
  for (const child of element.children) {
2255
2262
  await integrate2(session, child);
@@ -2264,14 +2271,14 @@ async function executeLoadContext(session, element) {
2264
2271
  const limitAttr = element.attributes.limit;
2265
2272
  const shouldImport = element.attributes.import !== "false";
2266
2273
  const outputVar = element.attributes.output;
2267
- const stats = registry2.getStats();
2274
+ const stats = registry.getStats();
2268
2275
  if (stats.totalSubroutines === 0) {
2269
2276
  emit(session, `[load-context] Registry is empty. Use :index <path> or <index-subroutines path="..."> first.
2270
2277
  `);
2271
2278
  return;
2272
2279
  }
2273
2280
  const limit = limitAttr ? parseInt(limitAttr, 10) : 5;
2274
- const results = registry2.search(query, limit);
2281
+ const results = registry.search(query, limit);
2275
2282
  if (results.length === 0) {
2276
2283
  emit(session, `[load-context] No subroutines found for query: "${query}". Try indexing more libraries.
2277
2284
  `);
@@ -2324,7 +2331,7 @@ async function executeLoadContext(session, element) {
2324
2331
  }
2325
2332
 
2326
2333
  // src/tags/save-subroutine.ts
2327
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
2334
+ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
2328
2335
  import { resolve as resolve3, dirname as dirname4, join as join4 } from "path";
2329
2336
  import { homedir as homedir4 } from "os";
2330
2337
  async function executeSaveSubroutine(session, element) {
@@ -2352,40 +2359,13 @@ async function executeSaveSubroutine(session, element) {
2352
2359
  content = generateXMLNotation(subroutine);
2353
2360
  }
2354
2361
  let filePath;
2355
- let shouldMerge = false;
2356
2362
  if (file) {
2357
2363
  filePath = resolve3(process.cwd(), file);
2358
2364
  } else if (pathAttr) {
2359
2365
  const targetDir = join4(homedir4(), ".dirac", "lib", pathAttr);
2360
2366
  filePath = join4(targetDir, `${name}.di`);
2361
- } else if (subroutine.sourcePath && existsSync5(subroutine.sourcePath)) {
2362
- const sourceFile = subroutine.sourcePath;
2363
- const sourceContent = readFileSync3(sourceFile, "utf-8");
2364
- const parser = new DiracParser();
2365
- try {
2366
- const ast = parser.parse(sourceContent);
2367
- const subroutineCount = countSubroutines(ast);
2368
- if (subroutineCount === 1) {
2369
- filePath = sourceFile;
2370
- emit(session, `Updating single-subroutine file: ${filePath}
2371
- `);
2372
- } else {
2373
- emit(session, `Source file contains ${subroutineCount} subroutines - creating separate file
2374
- `);
2375
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5);
2376
- const defaultDir = join4(homedir4(), ".dirac", "lib", timestamp);
2377
- filePath = join4(defaultDir, `${name}.di`);
2378
- }
2379
- } catch (error) {
2380
- emit(session, `Warning: Could not parse source file - creating new file
2381
- `);
2382
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5);
2383
- const defaultDir = join4(homedir4(), ".dirac", "lib", timestamp);
2384
- filePath = join4(defaultDir, `${name}.di`);
2385
- }
2386
2367
  } else {
2387
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5);
2388
- const defaultDir = join4(homedir4(), ".dirac", "lib", timestamp);
2368
+ const defaultDir = join4(homedir4(), ".dirac", "lib", "user");
2389
2369
  filePath = join4(defaultDir, `${name}.di`);
2390
2370
  }
2391
2371
  const dir = dirname4(filePath);
@@ -2395,12 +2375,16 @@ async function executeSaveSubroutine(session, element) {
2395
2375
  writeFileSync4(filePath, content, "utf-8");
2396
2376
  emit(session, `Subroutine '${name}' saved to: ${filePath}
2397
2377
  `);
2378
+ const savedSub = session.subroutines.find((s) => s.name === name);
2379
+ if (savedSub) {
2380
+ savedSub.sourcePath = filePath;
2381
+ savedSub.modified = false;
2382
+ }
2398
2383
  if (session.debug) {
2399
2384
  console.error(`[save-subroutine] Saved '${name}' to: ${filePath}`);
2400
2385
  }
2401
2386
  try {
2402
- const registry3 = new SubroutineRegistry();
2403
- const count = registry3.indexFile(filePath);
2387
+ const count = registry.indexFile(filePath);
2404
2388
  if (session.debug) {
2405
2389
  console.error(`[save-subroutine] Re-indexed ${filePath}: ${count} subroutine(s)`);
2406
2390
  }
@@ -2518,21 +2502,9 @@ function serializeChildrenBraKet(children, indent) {
2518
2502
  function escapeXml3(text) {
2519
2503
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2520
2504
  }
2521
- function countSubroutines(element) {
2522
- let count = 0;
2523
- if (element.tag === "subroutine") {
2524
- count = 1;
2525
- }
2526
- if (element.children) {
2527
- for (const child of element.children) {
2528
- count += countSubroutines(child);
2529
- }
2530
- }
2531
- return count;
2532
- }
2533
2505
 
2534
2506
  // src/tags/edit-subroutine.ts
2535
- import { writeFileSync as writeFileSync5, readFileSync as readFileSync4, unlinkSync } from "fs";
2507
+ import { writeFileSync as writeFileSync5, readFileSync as readFileSync3, unlinkSync, existsSync as existsSync6 } from "fs";
2536
2508
  import { tmpdir } from "os";
2537
2509
  import { join as join5 } from "path";
2538
2510
  import { spawnSync } from "child_process";
@@ -2552,7 +2524,36 @@ async function executeEditSubroutine(session, element) {
2552
2524
  if (!subroutine) {
2553
2525
  throw new Error(`Subroutine '${name}' not found in session`);
2554
2526
  }
2555
- const xml = serializeSubroutineToXML(subroutine);
2527
+ let xml;
2528
+ if (subroutine.sourcePath && existsSync6(subroutine.sourcePath)) {
2529
+ try {
2530
+ const sourceContent = readFileSync3(subroutine.sourcePath, "utf-8");
2531
+ const match = sourceContent.match(
2532
+ new RegExp(`<subroutine\\s+name="${name}"[\\s\\S]*?<\\/subroutine>`, "i")
2533
+ );
2534
+ if (match) {
2535
+ xml = match[0];
2536
+ if (session.debug) {
2537
+ console.error(`[edit-subroutine] Loaded from source: ${subroutine.sourcePath}`);
2538
+ }
2539
+ } else {
2540
+ xml = serializeSubroutineToXML(subroutine);
2541
+ if (session.debug) {
2542
+ console.error(`[edit-subroutine] Could not extract from source, using serialization`);
2543
+ }
2544
+ }
2545
+ } catch (err) {
2546
+ xml = serializeSubroutineToXML(subroutine);
2547
+ if (session.debug) {
2548
+ console.error(`[edit-subroutine] Error reading source file, using serialization`);
2549
+ }
2550
+ }
2551
+ } else {
2552
+ xml = serializeSubroutineToXML(subroutine);
2553
+ if (session.debug) {
2554
+ console.error(`[edit-subroutine] No source file, serializing from AST`);
2555
+ }
2556
+ }
2556
2557
  const tempFile = join5(tmpdir(), `dirac-edit-${name}-${Date.now()}.di`);
2557
2558
  writeFileSync5(tempFile, xml, "utf-8");
2558
2559
  if (session.debug) {
@@ -2572,7 +2573,7 @@ async function executeEditSubroutine(session, element) {
2572
2573
  unlinkSync(tempFile);
2573
2574
  throw new Error(`Editor exited with code ${result.status}`);
2574
2575
  }
2575
- const editedContent = readFileSync4(tempFile, "utf-8");
2576
+ const editedContent = readFileSync3(tempFile, "utf-8");
2576
2577
  unlinkSync(tempFile);
2577
2578
  if (session.debug) {
2578
2579
  console.error(`[edit-subroutine] Editor closed, re-importing subroutine`);
@@ -2580,6 +2581,10 @@ async function executeEditSubroutine(session, element) {
2580
2581
  const parser = new DiracParser();
2581
2582
  const ast = parser.parse(editedContent);
2582
2583
  await integrate(session, ast);
2584
+ const editedSub = session.subroutines.find((s) => s.name === name);
2585
+ if (editedSub) {
2586
+ editedSub.modified = true;
2587
+ }
2583
2588
  emit(session, `Subroutine '${name}' updated in session (use save-subroutine to persist)
2584
2589
  `);
2585
2590
  }
@@ -2591,9 +2596,14 @@ function serializeSubroutineToXML(sub) {
2591
2596
  return lines.join("\n");
2592
2597
  }
2593
2598
  function serializeElement2(el, lines, indent) {
2594
- if (!el || !el.tag) {
2595
- if (el && typeof el === "string") {
2596
- lines.push(indent + el);
2599
+ if (!el.tag || el.tag === "") {
2600
+ if (el.text) {
2601
+ let lastIdx = lines.length - 1;
2602
+ if (lastIdx >= 0 && !lines[lastIdx].endsWith(">")) {
2603
+ lines[lastIdx] += el.text;
2604
+ } else {
2605
+ lines.push(indent + el.text);
2606
+ }
2597
2607
  }
2598
2608
  return;
2599
2609
  }
@@ -2606,22 +2616,46 @@ function serializeElement2(el, lines, indent) {
2606
2616
  }
2607
2617
  }
2608
2618
  const hasChildren = el.children && el.children.length > 0;
2609
- const hasText = el.text && el.text.trim();
2610
- if (!hasChildren && !hasText) {
2611
- lines.push(tag + " />");
2612
- } else if (hasText && !hasChildren) {
2613
- lines.push(tag + ">" + el.text + `</${el.tag}>`);
2619
+ if (!hasChildren) {
2620
+ let lastIdx = lines.length - 1;
2621
+ if (lastIdx >= 0 && !lines[lastIdx].endsWith(">") && !lines[lastIdx].trim().startsWith("<")) {
2622
+ lines[lastIdx] += tag.slice(indent.length) + " />";
2623
+ } else {
2624
+ lines.push(tag + " />");
2625
+ }
2614
2626
  } else {
2615
- lines.push(tag + ">");
2616
- if (hasText) {
2617
- lines.push(indent + " " + el.text);
2627
+ let lastIdx = lines.length - 1;
2628
+ const shouldInline = lastIdx >= 0 && !lines[lastIdx].endsWith(">");
2629
+ if (shouldInline) {
2630
+ lines[lastIdx] += tag.slice(indent.length) + ">";
2631
+ } else {
2632
+ lines.push(tag + ">");
2618
2633
  }
2619
- if (hasChildren) {
2620
- for (const child of el.children) {
2621
- serializeElement2(child, lines, indent + " ");
2634
+ let allInline = true;
2635
+ for (let i = 0; i < el.children.length; i++) {
2636
+ const child = el.children[i];
2637
+ if (!child.tag || child.tag === "") {
2638
+ lastIdx = lines.length - 1;
2639
+ if (child.text) {
2640
+ lines[lastIdx] += child.text;
2641
+ }
2642
+ } else {
2643
+ const isSimpleVar = child.tag === "variable" && child.attributes && child.attributes.name;
2644
+ if (isSimpleVar) {
2645
+ lastIdx = lines.length - 1;
2646
+ lines[lastIdx] += `<variable name="${child.attributes.name}" />`;
2647
+ } else {
2648
+ allInline = false;
2649
+ serializeElement2(child, lines, indent + " ");
2650
+ }
2622
2651
  }
2623
2652
  }
2624
- lines.push(`${indent}</${el.tag}>`);
2653
+ lastIdx = lines.length - 1;
2654
+ if (allInline || lines[lastIdx].indexOf(`<${el.tag}`) !== -1) {
2655
+ lines[lastIdx] += `</${el.tag}>`;
2656
+ } else {
2657
+ lines.push(`${indent}</${el.tag}>`);
2658
+ }
2625
2659
  }
2626
2660
  }
2627
2661
 
@@ -2645,7 +2679,7 @@ async function executeForeach(session, element) {
2645
2679
  const parser2 = new DiracParser2();
2646
2680
  try {
2647
2681
  const fromElement = parser2.parse(fromAttr);
2648
- const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
2682
+ const { integrate: integrate2 } = await import("./interpreter-Y2AU6RG6.js");
2649
2683
  await integrate2(session, fromElement);
2650
2684
  } catch (e) {
2651
2685
  session.output = savedOutput;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-QUFYZS2S.js";
3
+ } from "./chunk-QPO3WKH2.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
package/dist/cli.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-AJSYOXXZ.js";
5
5
  import {
6
6
  execute
7
- } from "./chunk-6SKZC4N7.js";
8
- import "./chunk-QUFYZS2S.js";
7
+ } from "./chunk-PLH7YN7I.js";
8
+ import "./chunk-QPO3WKH2.js";
9
9
  import "./chunk-HRHAMPOB.js";
10
10
  import "./chunk-VC23AJJJ.js";
11
11
  import "./chunk-M57VI7KL.js";
@@ -16,7 +16,7 @@ import "dotenv/config";
16
16
  // package.json
17
17
  var package_default = {
18
18
  name: "dirac-lang",
19
- version: "0.1.68",
19
+ version: "0.1.70",
20
20
  description: "LLM-Augmented Declarative Execution",
21
21
  type: "module",
22
22
  main: "dist/index.js",
@@ -109,7 +109,7 @@ async function main() {
109
109
  const args = process.argv.slice(2);
110
110
  const calledAs = process.argv[1];
111
111
  if (calledAs && calledAs.endsWith("/dish")) {
112
- const { DiracShell } = await import("./shell-BYGHH5YH.js");
112
+ const { DiracShell } = await import("./shell-BTRWJIV3.js");
113
113
  const shellConfig = loadShellConfig(args);
114
114
  const shell = new DiracShell(shellConfig);
115
115
  await shell.start();
@@ -158,11 +158,11 @@ async function main() {
158
158
  if (args[0] === "agent") {
159
159
  const subcommand = args[1];
160
160
  if (subcommand === "daemon") {
161
- const { runAgentDaemon } = await import("./agent-RH5SYOLV.js");
161
+ const { runAgentDaemon } = await import("./agent-WJUVRA6D.js");
162
162
  await runAgentDaemon();
163
163
  return;
164
164
  }
165
- const { AgentCLI } = await import("./agent-RH5SYOLV.js");
165
+ const { AgentCLI } = await import("./agent-WJUVRA6D.js");
166
166
  const agent = new AgentCLI();
167
167
  switch (subcommand) {
168
168
  case "start":
@@ -189,8 +189,8 @@ async function main() {
189
189
  return;
190
190
  }
191
191
  if (args[0] === "shell") {
192
- const { DiracShell } = await import("./shell-BYGHH5YH.js");
193
- const { SessionServer, isSessionRunning, getSocketPath } = await import("./session-server-XV4RB5IW.js");
192
+ const { DiracShell } = await import("./shell-BTRWJIV3.js");
193
+ const { SessionServer, isSessionRunning, getSocketPath } = await import("./session-server-L5HBRT5P.js");
194
194
  const { SessionClient } = await import("./session-client-3VTC5MLO.js");
195
195
  const daemonMode = args.includes("--daemon") || args.includes("-d");
196
196
  const agentMode = args.includes("--agent") || args.includes("-a");
@@ -236,7 +236,7 @@ async function main() {
236
236
  return;
237
237
  }
238
238
  if (args[0] === "daemon") {
239
- const { SessionServer } = await import("./session-server-XV4RB5IW.js");
239
+ const { SessionServer } = await import("./session-server-L5HBRT5P.js");
240
240
  const server = new SessionServer();
241
241
  await server.start();
242
242
  console.log("Session daemon started");
@@ -3,7 +3,7 @@ import {
3
3
  listCronJobs,
4
4
  stopAllCronJobs,
5
5
  stopCronJob
6
- } from "./chunk-QUFYZS2S.js";
6
+ } from "./chunk-QPO3WKH2.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
8
  import "./chunk-VC23AJJJ.js";
9
9
  import "./chunk-M57VI7KL.js";
package/dist/index.d.ts CHANGED
@@ -58,6 +58,7 @@ interface Subroutine {
58
58
  parameters?: ParameterMetadata[];
59
59
  meta?: Record<string, string>;
60
60
  sourcePath?: string;
61
+ modified?: boolean;
61
62
  }
62
63
  /**
63
64
  * Execution context - maps to MaskSession in MASK
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@ import {
2
2
  createLLMAdapter,
3
3
  execute,
4
4
  executeUserCommand
5
- } from "./chunk-6SKZC4N7.js";
5
+ } from "./chunk-PLH7YN7I.js";
6
6
  import {
7
7
  integrate
8
- } from "./chunk-QUFYZS2S.js";
8
+ } from "./chunk-QPO3WKH2.js";
9
9
  import {
10
10
  DiracParser
11
11
  } from "./chunk-HRHAMPOB.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  integrate,
3
3
  integrateChildren
4
- } from "./chunk-QUFYZS2S.js";
4
+ } from "./chunk-QPO3WKH2.js";
5
5
  import "./chunk-HRHAMPOB.js";
6
6
  import "./chunk-VC23AJJJ.js";
7
7
  import "./chunk-M57VI7KL.js";
@@ -3,7 +3,7 @@ import {
3
3
  cancelScheduledRun,
4
4
  executeRunAt,
5
5
  listScheduledRuns
6
- } from "./chunk-QUFYZS2S.js";
6
+ } from "./chunk-QPO3WKH2.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
8
  import "./chunk-VC23AJJJ.js";
9
9
  import "./chunk-M57VI7KL.js";
@@ -3,7 +3,7 @@ import {
3
3
  listScheduledTasks,
4
4
  stopAllScheduledTasks,
5
5
  stopScheduledTask
6
- } from "./chunk-QUFYZS2S.js";
6
+ } from "./chunk-QPO3WKH2.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
8
  import "./chunk-VC23AJJJ.js";
9
9
  import "./chunk-M57VI7KL.js";
@@ -2,8 +2,8 @@ import {
2
2
  SessionServer,
3
3
  getSocketPath,
4
4
  isSessionRunning
5
- } from "./chunk-65TBONV6.js";
6
- import "./chunk-QUFYZS2S.js";
5
+ } from "./chunk-YVI7T3DS.js";
6
+ import "./chunk-QPO3WKH2.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
8
  import "./chunk-VC23AJJJ.js";
9
9
  import "./chunk-M57VI7KL.js";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-AJSYOXXZ.js";
5
5
  import {
6
6
  integrate
7
- } from "./chunk-QUFYZS2S.js";
7
+ } from "./chunk-QPO3WKH2.js";
8
8
  import {
9
9
  DiracParser
10
10
  } from "./chunk-HRHAMPOB.js";
@@ -271,7 +271,7 @@ var DiracShell = class {
271
271
  } catch (err) {
272
272
  }
273
273
  }
274
- checkUnsavedSubroutines() {
274
+ getUnsavedSubroutines() {
275
275
  const unsaved = [];
276
276
  const excludePaths = [
277
277
  path.join(os.homedir(), ".dirac", "lib"),
@@ -283,8 +283,12 @@ var DiracShell = class {
283
283
  if (sub.meta && sub.meta["hide-from-llm"] === "true") {
284
284
  continue;
285
285
  }
286
+ if (sub.modified) {
287
+ unsaved.push(sub.name);
288
+ continue;
289
+ }
286
290
  if (!sub.sourcePath) {
287
- unsaved.push({ name: sub.name, reason: "created in session" });
291
+ unsaved.push(sub.name);
288
292
  } else {
289
293
  const isExcluded = excludePaths.some(
290
294
  (excludePath) => sub.sourcePath.startsWith(excludePath)
@@ -292,28 +296,51 @@ var DiracShell = class {
292
296
  if (isExcluded) {
293
297
  continue;
294
298
  }
295
- if (fs.existsSync(sub.sourcePath)) {
296
- try {
297
- const content = fs.readFileSync(sub.sourcePath, "utf-8");
298
- const parser = new DiracParser();
299
- const ast = parser.parse(content);
300
- const count = this.countSubroutinesInAST(ast);
301
- if (count > 1) {
302
- const shortPath = sub.sourcePath.replace(os.homedir(), "~");
303
- unsaved.push({ name: sub.name, reason: `from multi-sub file (${shortPath})` });
304
- }
305
- } catch (err) {
306
- }
307
- }
308
299
  }
309
300
  }
310
- if (unsaved.length > 0) {
311
- console.log("\n\u26A0\uFE0F Warning: You have unsaved subroutines:");
312
- for (const { name, reason } of unsaved) {
313
- console.log(` - ${name} (${reason})`);
314
- }
315
- console.log('\nUse :save <name> or |save-subroutine name="..."> to persist them.\n');
301
+ return unsaved;
302
+ }
303
+ async promptSaveUnsaved(unsaved) {
304
+ console.log("\n\u26A0\uFE0F Warning: You have unsaved subroutines created in this session:");
305
+ for (const name of unsaved) {
306
+ console.log(` - ${name}`);
316
307
  }
308
+ console.log("\nOptions:");
309
+ console.log(" a - Save all and exit");
310
+ console.log(" n - Exit without saving");
311
+ console.log(" c - Cancel (return to shell)");
312
+ return new Promise((resolve2) => {
313
+ const confirmRl = readline.createInterface({
314
+ input: process.stdin,
315
+ output: process.stdout
316
+ });
317
+ confirmRl.question("\nYour choice [a/n/c]: ", async (answer) => {
318
+ confirmRl.close();
319
+ const choice = answer.trim().toLowerCase();
320
+ if (choice === "a") {
321
+ console.log("\nSaving all unsaved subroutines...\n");
322
+ for (const name of unsaved) {
323
+ try {
324
+ const xml = `<save-subroutine name="${name}" format="xml" />`;
325
+ const ast = this.xmlParser.parse(xml);
326
+ await integrate(this.session, ast);
327
+ if (this.session.output.length > 0) {
328
+ console.log(this.session.output.join(""));
329
+ this.session.output = [];
330
+ }
331
+ } catch (error) {
332
+ console.error(`Error saving ${name}:`, error instanceof Error ? error.message : String(error));
333
+ }
334
+ }
335
+ resolve2(true);
336
+ } else if (choice === "n") {
337
+ resolve2(true);
338
+ } else {
339
+ console.log("\n(Exit canceled - returning to shell)\n");
340
+ resolve2(false);
341
+ }
342
+ });
343
+ });
317
344
  }
318
345
  countSubroutinesInAST(element) {
319
346
  let count = 0;
@@ -327,24 +354,44 @@ var DiracShell = class {
327
354
  }
328
355
  return count;
329
356
  }
357
+ finalizeExit() {
358
+ this.saveHistory();
359
+ if (this.client) {
360
+ this.client.disconnect();
361
+ }
362
+ import("./schedule-R3ZBENYA.js").then(({ stopAllScheduledTasks }) => {
363
+ stopAllScheduledTasks();
364
+ console.log("\nGoodbye!");
365
+ process.exit(0);
366
+ }).catch(() => {
367
+ console.log("\nGoodbye!");
368
+ process.exit(0);
369
+ });
370
+ }
330
371
  setupHandlers() {
331
372
  this.rl.on("line", async (input) => {
332
373
  await this.handleInput(input);
333
374
  });
334
- this.rl.on("close", () => {
335
- this.checkUnsavedSubroutines();
336
- this.saveHistory();
337
- if (this.client) {
338
- this.client.disconnect();
375
+ this.rl.on("close", async () => {
376
+ const unsaved = this.getUnsavedSubroutines();
377
+ if (unsaved.length > 0) {
378
+ const shouldExit = await this.promptSaveUnsaved(unsaved);
379
+ if (shouldExit) {
380
+ this.finalizeExit();
381
+ } else {
382
+ this.rl = readline.createInterface({
383
+ input: process.stdin,
384
+ output: process.stdout,
385
+ prompt: "> ",
386
+ historySize: MAX_HISTORY,
387
+ completer: this.completer.bind(this)
388
+ });
389
+ this.setupHandlers();
390
+ this.rl.prompt();
391
+ }
392
+ } else {
393
+ this.finalizeExit();
339
394
  }
340
- import("./schedule-ZGPBTVXG.js").then(({ stopAllScheduledTasks }) => {
341
- stopAllScheduledTasks();
342
- console.log("\nGoodbye!");
343
- process.exit(0);
344
- }).catch(() => {
345
- console.log("\nGoodbye!");
346
- process.exit(0);
347
- });
348
395
  });
349
396
  this.rl.on("SIGINT", () => {
350
397
  if (this.inputBuffer.length > 0) {
@@ -703,7 +750,7 @@ Examples:
703
750
  break;
704
751
  case "tasks":
705
752
  try {
706
- const { listScheduledTasks } = await import("./schedule-ZGPBTVXG.js");
753
+ const { listScheduledTasks } = await import("./schedule-R3ZBENYA.js");
707
754
  const tasks = listScheduledTasks();
708
755
  if (tasks.length === 0) {
709
756
  console.log("No scheduled tasks running.");
@@ -722,7 +769,7 @@ Examples:
722
769
  console.log("Usage: :stop <task-name>");
723
770
  } else {
724
771
  try {
725
- const { stopScheduledTask } = await import("./schedule-ZGPBTVXG.js");
772
+ const { stopScheduledTask } = await import("./schedule-R3ZBENYA.js");
726
773
  const taskName = args[0];
727
774
  const stopped = stopScheduledTask(taskName);
728
775
  if (stopped) {
@@ -737,7 +784,7 @@ Examples:
737
784
  break;
738
785
  case "stopall":
739
786
  try {
740
- const { stopAllScheduledTasks } = await import("./schedule-ZGPBTVXG.js");
787
+ const { stopAllScheduledTasks } = await import("./schedule-R3ZBENYA.js");
741
788
  stopAllScheduledTasks();
742
789
  console.log("All scheduled tasks stopped.");
743
790
  } catch (error) {
@@ -746,7 +793,7 @@ Examples:
746
793
  break;
747
794
  case "crons":
748
795
  try {
749
- const { listCronJobs } = await import("./cron-VEWKZ2ZU.js");
796
+ const { listCronJobs } = await import("./cron-HFJ3HK5G.js");
750
797
  const jobs = listCronJobs();
751
798
  if (jobs.length === 0) {
752
799
  console.log("No cron jobs running.");
@@ -766,7 +813,7 @@ Examples:
766
813
  console.log("Usage: :stopcron <job-name>");
767
814
  } else {
768
815
  try {
769
- const { stopCronJob } = await import("./cron-VEWKZ2ZU.js");
816
+ const { stopCronJob } = await import("./cron-HFJ3HK5G.js");
770
817
  const jobName = args[0];
771
818
  const stopped = stopCronJob(jobName);
772
819
  if (stopped) {
@@ -781,7 +828,7 @@ Examples:
781
828
  break;
782
829
  case "stopallcrons":
783
830
  try {
784
- const { stopAllCronJobs } = await import("./cron-VEWKZ2ZU.js");
831
+ const { stopAllCronJobs } = await import("./cron-HFJ3HK5G.js");
785
832
  stopAllCronJobs();
786
833
  console.log("All cron jobs stopped.");
787
834
  } catch (error) {
@@ -790,7 +837,7 @@ Examples:
790
837
  break;
791
838
  case "scheduled":
792
839
  try {
793
- const { listScheduledRuns } = await import("./run-at-OPGYI26L.js");
840
+ const { listScheduledRuns } = await import("./run-at-JFHLEZNU.js");
794
841
  const runs = listScheduledRuns();
795
842
  if (runs.length === 0) {
796
843
  console.log("No scheduled runs pending.");
@@ -810,7 +857,7 @@ Examples:
810
857
  console.log("Usage: :cancel <run-name>");
811
858
  } else {
812
859
  try {
813
- const { cancelScheduledRun } = await import("./run-at-OPGYI26L.js");
860
+ const { cancelScheduledRun } = await import("./run-at-JFHLEZNU.js");
814
861
  const runName = args[0];
815
862
  const cancelled = cancelScheduledRun(runName);
816
863
  if (cancelled) {
@@ -825,7 +872,7 @@ Examples:
825
872
  break;
826
873
  case "cancelall":
827
874
  try {
828
- const { cancelAllScheduledRuns } = await import("./run-at-OPGYI26L.js");
875
+ const { cancelAllScheduledRuns } = await import("./run-at-JFHLEZNU.js");
829
876
  cancelAllScheduledRuns();
830
877
  console.log("All scheduled runs cancelled.");
831
878
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-QUFYZS2S.js";
3
+ } from "./chunk-QPO3WKH2.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirac-lang",
3
- "version": "0.1.69",
3
+ "version": "0.1.71",
4
4
  "description": "LLM-Augmented Declarative Execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",