dirac-lang 0.1.67 → 0.1.69

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,11 +2,11 @@ import {
2
2
  SessionServer,
3
3
  getSocketPath,
4
4
  isSessionRunning
5
- } from "./chunk-6OIMDS6G.js";
6
- import "./chunk-XNH4TU3Q.js";
5
+ } from "./chunk-65TBONV6.js";
6
+ import "./chunk-QUFYZS2S.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
- import "./chunk-NKA6ZJDV.js";
9
- import "./chunk-3UW6GWYQ.js";
8
+ import "./chunk-VC23AJJJ.js";
9
+ import "./chunk-M57VI7KL.js";
10
10
 
11
11
  // src/agent.ts
12
12
  import fs from "fs";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-XNH4TU3Q.js";
3
+ } from "./chunk-QUFYZS2S.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
7
7
  import {
8
8
  createSession
9
- } from "./chunk-3UW6GWYQ.js";
9
+ } from "./chunk-M57VI7KL.js";
10
10
 
11
11
  // src/session-server.ts
12
12
  import net from "net";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-XNH4TU3Q.js";
3
+ } from "./chunk-QUFYZS2S.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-3UW6GWYQ.js";
11
+ } from "./chunk-M57VI7KL.js";
12
12
 
13
13
  // src/utils/llm-adapter.ts
14
14
  function createLLMAdapter(session) {
@@ -190,7 +190,7 @@ function cleanToBoundary(session) {
190
190
  session.variables = kept;
191
191
  session.varBoundary = kept.length;
192
192
  }
193
- function registerSubroutine(session, name, element, description, parameters, meta, visible) {
193
+ function registerSubroutine(session, name, element, description, parameters, meta, visible, sourcePath) {
194
194
  session.subroutines.push({
195
195
  name,
196
196
  element,
@@ -198,7 +198,8 @@ function registerSubroutine(session, name, element, description, parameters, met
198
198
  visible,
199
199
  description,
200
200
  parameters,
201
- meta
201
+ meta,
202
+ sourcePath
202
203
  });
203
204
  }
204
205
  function getSubroutine(session, name) {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-HRHAMPOB.js";
4
4
  import {
5
5
  executeSubroutine
6
- } from "./chunk-NKA6ZJDV.js";
6
+ } from "./chunk-VC23AJJJ.js";
7
7
  import {
8
8
  CustomLLMProvider,
9
9
  OllamaProvider,
@@ -28,7 +28,7 @@ import {
28
28
  substituteVariables,
29
29
  throwException,
30
30
  unsetExceptionBoundary
31
- } from "./chunk-3UW6GWYQ.js";
31
+ } from "./chunk-M57VI7KL.js";
32
32
 
33
33
  // src/tags/parameters.ts
34
34
  async function executeParameters(session, element) {
@@ -284,7 +284,7 @@ async function executeCall(session, element) {
284
284
  }
285
285
  }
286
286
  async function registerExtendChain(session, subroutine, currentName) {
287
- const { executeSubroutine: executeSubroutine2 } = await import("./subroutine-WJU6SDRC.js");
287
+ const { executeSubroutine: executeSubroutine2 } = await import("./subroutine-OQJ3AY27.js");
288
288
  const extendsAttr = subroutine.attributes.extends;
289
289
  let parentName;
290
290
  if (extendsAttr) {
@@ -474,12 +474,12 @@ async function executeIf(session, element) {
474
474
  const condition = await evaluatePredicate(session, conditionElement);
475
475
  if (condition) {
476
476
  if (thenElement) {
477
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
477
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
478
478
  await integrateChildren2(session, thenElement);
479
479
  }
480
480
  } else {
481
481
  if (elseElement) {
482
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
482
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
483
483
  await integrateChildren2(session, elseElement);
484
484
  }
485
485
  }
@@ -492,7 +492,7 @@ async function evaluatePredicate(session, predicateElement) {
492
492
  return await evaluateCondition(session, predicateElement);
493
493
  }
494
494
  const outputLengthBefore = session.output.length;
495
- const { integrate: integrate2 } = await import("./interpreter-TDPDELJC.js");
495
+ const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
496
496
  await integrate2(session, predicateElement);
497
497
  const newOutputChunks = session.output.slice(outputLengthBefore);
498
498
  const result = newOutputChunks.join("").trim();
@@ -515,11 +515,11 @@ async function evaluateCondition(session, condElement) {
515
515
  }
516
516
  const outputLengthBefore = session.output.length;
517
517
  const args = [];
518
- const { integrate: integrate2 } = await import("./interpreter-TDPDELJC.js");
518
+ const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
519
519
  for (const child of condElement.children) {
520
520
  if (child.tag.toLowerCase() === "arg") {
521
521
  const argOutputStart = session.output.length;
522
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
522
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
523
523
  await integrateChildren2(session, child);
524
524
  const newChunks = session.output.slice(argOutputStart);
525
525
  const argValue = newChunks.join("");
@@ -808,7 +808,7 @@ async function executeLLM(session, element) {
808
808
  let systemPrompt = "";
809
809
  let currentUserPrompt = userPrompt;
810
810
  if (!noExtra) {
811
- const { getAvailableSubroutines: getAvailableSubroutines2 } = await import("./session-AZIX6ILU.js");
811
+ const { getAvailableSubroutines: getAvailableSubroutines2 } = await import("./session-OL5ARO6Q.js");
812
812
  const allSubroutines = getAvailableSubroutines2(session);
813
813
  if (session.debug) {
814
814
  console.error(`[LLM] Total subroutines from session: ${allSubroutines.length}`);
@@ -1012,7 +1012,7 @@ ${result}
1012
1012
  const parser = new DiracParser();
1013
1013
  let dynamicAST = parser.parse(diracCode);
1014
1014
  if (validateTags) {
1015
- const { validateDiracCode, applyCorrectedTags } = await import("./tag-validator-PEBTT5HJ.js");
1015
+ const { validateDiracCode, applyCorrectedTags } = await import("./tag-validator-JZVMOKGK.js");
1016
1016
  let validation = await validateDiracCode(session, dynamicAST, { autocorrect });
1017
1017
  let retryCount = 0;
1018
1018
  while (!validation.valid && retryCount < maxRetries) {
@@ -1092,6 +1092,28 @@ ${validation.errorMessages.join("\n")}`);
1092
1092
  if (iteration === 1) {
1093
1093
  dumpGeneratedSubroutines(session, diracCode, userPrompt);
1094
1094
  }
1095
+ const onIterationCallback = element.attributes["on-iteration"];
1096
+ if (onIterationCallback && feedbackMode) {
1097
+ if (session.debug) {
1098
+ console.error(`[LLM] Calling on-iteration plugin: ${onIterationCallback}`);
1099
+ }
1100
+ setVariable(session, "__llm_iteration__", iteration.toString(), true);
1101
+ setVariable(session, "__llm_max_iterations__", maxIterations.toString(), true);
1102
+ const callElement = {
1103
+ tag: onIterationCallback,
1104
+ attributes: {},
1105
+ children: [],
1106
+ text: ""
1107
+ };
1108
+ await integrate(session, callElement);
1109
+ const stopRequested = getVariable(session, "__llm_stop_requested__");
1110
+ if (stopRequested === "true") {
1111
+ if (session.debug) {
1112
+ console.error("[LLM] Plugin requested stop");
1113
+ }
1114
+ break;
1115
+ }
1116
+ }
1095
1117
  if (feedbackMode) {
1096
1118
  const outputAfter = session.output.slice();
1097
1119
  const executionOutput = outputAfter.slice(outputBefore.length).join("");
@@ -1625,7 +1647,7 @@ async function getBestTagMatch(candidate, allowed) {
1625
1647
  return { tag: allowed[bestIdx], score: bestScore };
1626
1648
  }
1627
1649
  async function executeTagCheck(session, element) {
1628
- const { getAvailableSubroutines: getAvailableSubroutines2 } = await import("./session-AZIX6ILU.js");
1650
+ const { getAvailableSubroutines: getAvailableSubroutines2 } = await import("./session-OL5ARO6Q.js");
1629
1651
  const subroutines = getAvailableSubroutines2(session);
1630
1652
  const allowed = new Set(subroutines.map((s) => s.name));
1631
1653
  console.error("[tag-check] Allowed subroutines:", Array.from(allowed));
@@ -1718,7 +1740,7 @@ async function executeTagCheck(session, element) {
1718
1740
  const executeTag = correctedTag || tagName;
1719
1741
  console.error(`[tag-check] Executing <${executeTag}/> as all checks passed and execute=true.`);
1720
1742
  const elementToExecute = correctedTag ? { ...child, tag: correctedTag } : child;
1721
- const { integrate: integrate2 } = await import("./interpreter-TDPDELJC.js");
1743
+ const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
1722
1744
  await integrate2(session, elementToExecute);
1723
1745
  }
1724
1746
  }
@@ -1727,7 +1749,7 @@ async function executeTagCheck(session, element) {
1727
1749
  // src/tags/throw.ts
1728
1750
  async function executeThrow(session, element) {
1729
1751
  const exceptionName = element.attributes?.name || "exception";
1730
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
1752
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1731
1753
  const exceptionDom = {
1732
1754
  tag: "exception-content",
1733
1755
  attributes: { name: exceptionName },
@@ -1740,7 +1762,7 @@ async function executeThrow(session, element) {
1740
1762
  // src/tags/try.ts
1741
1763
  async function executeTry(session, element) {
1742
1764
  setExceptionBoundary(session);
1743
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
1765
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1744
1766
  await integrateChildren2(session, element);
1745
1767
  unsetExceptionBoundary(session);
1746
1768
  }
@@ -1750,7 +1772,7 @@ async function executeCatch(session, element) {
1750
1772
  const exceptionName = element.attributes?.name || "exception";
1751
1773
  const caughtCount = lookupException(session, exceptionName);
1752
1774
  if (caughtCount > 0) {
1753
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
1775
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1754
1776
  await integrateChildren2(session, element);
1755
1777
  }
1756
1778
  flushCurrentException(session);
@@ -1759,7 +1781,7 @@ async function executeCatch(session, element) {
1759
1781
  // src/tags/exception.ts
1760
1782
  async function executeException(session, element) {
1761
1783
  const exceptions = getCurrentExceptions(session);
1762
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-TDPDELJC.js");
1784
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-N4ERLMWW.js");
1763
1785
  for (const exceptionDom of exceptions) {
1764
1786
  await integrateChildren2(session, exceptionDom);
1765
1787
  }
@@ -2227,7 +2249,7 @@ async function executeLoadContext(session, element) {
2227
2249
  query = element.text.trim();
2228
2250
  }
2229
2251
  if (!query && element.children.length > 0) {
2230
- const { integrate: integrate2 } = await import("./interpreter-TDPDELJC.js");
2252
+ const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
2231
2253
  const beforeOutput = session.output.length;
2232
2254
  for (const child of element.children) {
2233
2255
  await integrate2(session, child);
@@ -2296,13 +2318,13 @@ async function executeLoadContext(session, element) {
2296
2318
  parameters: s.parameters.map((p) => p.name),
2297
2319
  filePath: s.filePath
2298
2320
  }));
2299
- const { setVariable: setVariable2 } = await import("./session-AZIX6ILU.js");
2321
+ const { setVariable: setVariable2 } = await import("./session-OL5ARO6Q.js");
2300
2322
  setVariable2(session, outputVar, JSON.stringify(summary, null, 2), false);
2301
2323
  }
2302
2324
  }
2303
2325
 
2304
2326
  // src/tags/save-subroutine.ts
2305
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
2327
+ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
2306
2328
  import { resolve as resolve3, dirname as dirname4, join as join4 } from "path";
2307
2329
  import { homedir as homedir4 } from "os";
2308
2330
  async function executeSaveSubroutine(session, element) {
@@ -2330,11 +2352,37 @@ async function executeSaveSubroutine(session, element) {
2330
2352
  content = generateXMLNotation(subroutine);
2331
2353
  }
2332
2354
  let filePath;
2355
+ let shouldMerge = false;
2333
2356
  if (file) {
2334
2357
  filePath = resolve3(process.cwd(), file);
2335
2358
  } else if (pathAttr) {
2336
2359
  const targetDir = join4(homedir4(), ".dirac", "lib", pathAttr);
2337
2360
  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
+ }
2338
2386
  } else {
2339
2387
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5);
2340
2388
  const defaultDir = join4(homedir4(), ".dirac", "lib", timestamp);
@@ -2350,6 +2398,17 @@ async function executeSaveSubroutine(session, element) {
2350
2398
  if (session.debug) {
2351
2399
  console.error(`[save-subroutine] Saved '${name}' to: ${filePath}`);
2352
2400
  }
2401
+ try {
2402
+ const registry3 = new SubroutineRegistry();
2403
+ const count = registry3.indexFile(filePath);
2404
+ if (session.debug) {
2405
+ console.error(`[save-subroutine] Re-indexed ${filePath}: ${count} subroutine(s)`);
2406
+ }
2407
+ } catch (error) {
2408
+ if (session.debug) {
2409
+ console.error(`[save-subroutine] Warning: Failed to re-index: ${error}`);
2410
+ }
2411
+ }
2353
2412
  }
2354
2413
  function generateXMLNotation(subroutine) {
2355
2414
  let xml = "<!-- Exported subroutine -->\n\n";
@@ -2459,6 +2518,112 @@ function serializeChildrenBraKet(children, indent) {
2459
2518
  function escapeXml3(text) {
2460
2519
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
2461
2520
  }
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
+
2534
+ // src/tags/edit-subroutine.ts
2535
+ import { writeFileSync as writeFileSync5, readFileSync as readFileSync4, unlinkSync } from "fs";
2536
+ import { tmpdir } from "os";
2537
+ import { join as join5 } from "path";
2538
+ import { spawnSync } from "child_process";
2539
+ async function executeEditSubroutine(session, element) {
2540
+ const name = element.attributes.name;
2541
+ const editor = element.attributes.editor || process.env.EDITOR || process.env.VISUAL || "vi";
2542
+ if (!name) {
2543
+ throw new Error("<edit-subroutine> requires name attribute");
2544
+ }
2545
+ let subroutine = void 0;
2546
+ for (let i = session.subroutines.length - 1; i >= 0; i--) {
2547
+ if (session.subroutines[i].name === name) {
2548
+ subroutine = session.subroutines[i];
2549
+ break;
2550
+ }
2551
+ }
2552
+ if (!subroutine) {
2553
+ throw new Error(`Subroutine '${name}' not found in session`);
2554
+ }
2555
+ const xml = serializeSubroutineToXML(subroutine);
2556
+ const tempFile = join5(tmpdir(), `dirac-edit-${name}-${Date.now()}.di`);
2557
+ writeFileSync5(tempFile, xml, "utf-8");
2558
+ if (session.debug) {
2559
+ console.error(`[edit-subroutine] Wrote '${name}' to temp file: ${tempFile}`);
2560
+ console.error(`[edit-subroutine] Opening with editor: ${editor}`);
2561
+ }
2562
+ const result = spawnSync(editor, [tempFile], {
2563
+ stdio: "inherit",
2564
+ // Pass through stdin/stdout/stderr
2565
+ shell: true
2566
+ });
2567
+ if (result.error) {
2568
+ unlinkSync(tempFile);
2569
+ throw new Error(`Failed to open editor: ${result.error.message}`);
2570
+ }
2571
+ if (result.status !== 0) {
2572
+ unlinkSync(tempFile);
2573
+ throw new Error(`Editor exited with code ${result.status}`);
2574
+ }
2575
+ const editedContent = readFileSync4(tempFile, "utf-8");
2576
+ unlinkSync(tempFile);
2577
+ if (session.debug) {
2578
+ console.error(`[edit-subroutine] Editor closed, re-importing subroutine`);
2579
+ }
2580
+ const parser = new DiracParser();
2581
+ const ast = parser.parse(editedContent);
2582
+ await integrate(session, ast);
2583
+ emit(session, `Subroutine '${name}' updated in session (use save-subroutine to persist)
2584
+ `);
2585
+ }
2586
+ function serializeSubroutineToXML(sub) {
2587
+ const lines = [];
2588
+ lines.push("<!-- Editing subroutine: " + sub.name + " -->");
2589
+ lines.push("");
2590
+ serializeElement2(sub.element, lines, "");
2591
+ return lines.join("\n");
2592
+ }
2593
+ function serializeElement2(el, lines, indent) {
2594
+ if (!el || !el.tag) {
2595
+ if (el && typeof el === "string") {
2596
+ lines.push(indent + el);
2597
+ }
2598
+ return;
2599
+ }
2600
+ let tag = `${indent}<${el.tag}`;
2601
+ if (el.attributes) {
2602
+ for (const [key, value] of Object.entries(el.attributes)) {
2603
+ if (typeof value === "string") {
2604
+ tag += ` ${key}="${value.replace(/"/g, "&quot;")}"`;
2605
+ }
2606
+ }
2607
+ }
2608
+ 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}>`);
2614
+ } else {
2615
+ lines.push(tag + ">");
2616
+ if (hasText) {
2617
+ lines.push(indent + " " + el.text);
2618
+ }
2619
+ if (hasChildren) {
2620
+ for (const child of el.children) {
2621
+ serializeElement2(child, lines, indent + " ");
2622
+ }
2623
+ }
2624
+ lines.push(`${indent}</${el.tag}>`);
2625
+ }
2626
+ }
2462
2627
 
2463
2628
  // src/tags/foreach.ts
2464
2629
  import { XMLParser } from "fast-xml-parser";
@@ -2480,7 +2645,7 @@ async function executeForeach(session, element) {
2480
2645
  const parser2 = new DiracParser2();
2481
2646
  try {
2482
2647
  const fromElement = parser2.parse(fromAttr);
2483
- const { integrate: integrate2 } = await import("./interpreter-TDPDELJC.js");
2648
+ const { integrate: integrate2 } = await import("./interpreter-N4ERLMWW.js");
2484
2649
  await integrate2(session, fromElement);
2485
2650
  } catch (e) {
2486
2651
  session.output = savedOutput;
@@ -3042,6 +3207,9 @@ async function integrate(session, element) {
3042
3207
  case "save-subroutine":
3043
3208
  await executeSaveSubroutine(session, element);
3044
3209
  break;
3210
+ case "edit-subroutine":
3211
+ await executeEditSubroutine(session, element);
3212
+ break;
3045
3213
  case "foreach":
3046
3214
  await executeForeach(session, element);
3047
3215
  break;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  registerSubroutine
3
- } from "./chunk-3UW6GWYQ.js";
3
+ } from "./chunk-M57VI7KL.js";
4
4
 
5
5
  // src/tags/subroutine.ts
6
6
  function executeSubroutine(session, element) {
@@ -58,7 +58,8 @@ function executeSubroutine(session, element) {
58
58
  description,
59
59
  parameters.length > 0 ? parameters : void 0,
60
60
  Object.keys(meta).length > 0 ? meta : void 0,
61
- visible
61
+ visible,
62
+ session.currentFile
62
63
  );
63
64
  }
64
65
 
package/dist/cli.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  } from "./chunk-AJSYOXXZ.js";
5
5
  import {
6
6
  execute
7
- } from "./chunk-3IC2OMWT.js";
8
- import "./chunk-XNH4TU3Q.js";
7
+ } from "./chunk-6SKZC4N7.js";
8
+ import "./chunk-QUFYZS2S.js";
9
9
  import "./chunk-HRHAMPOB.js";
10
- import "./chunk-NKA6ZJDV.js";
11
- import "./chunk-3UW6GWYQ.js";
10
+ import "./chunk-VC23AJJJ.js";
11
+ import "./chunk-M57VI7KL.js";
12
12
 
13
13
  // src/cli.ts
14
14
  import "dotenv/config";
@@ -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.66",
19
+ version: "0.1.68",
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-YYSQKOZV.js");
112
+ const { DiracShell } = await import("./shell-BYGHH5YH.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-Y5D5SMAS.js");
161
+ const { runAgentDaemon } = await import("./agent-RH5SYOLV.js");
162
162
  await runAgentDaemon();
163
163
  return;
164
164
  }
165
- const { AgentCLI } = await import("./agent-Y5D5SMAS.js");
165
+ const { AgentCLI } = await import("./agent-RH5SYOLV.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-YYSQKOZV.js");
193
- const { SessionServer, isSessionRunning, getSocketPath } = await import("./session-server-RZYUXJFQ.js");
192
+ const { DiracShell } = await import("./shell-BYGHH5YH.js");
193
+ const { SessionServer, isSessionRunning, getSocketPath } = await import("./session-server-XV4RB5IW.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-RZYUXJFQ.js");
239
+ const { SessionServer } = await import("./session-server-XV4RB5IW.js");
240
240
  const server = new SessionServer();
241
241
  await server.start();
242
242
  console.log("Session daemon started");
@@ -3,10 +3,10 @@ import {
3
3
  listCronJobs,
4
4
  stopAllCronJobs,
5
5
  stopCronJob
6
- } from "./chunk-XNH4TU3Q.js";
6
+ } from "./chunk-QUFYZS2S.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
- import "./chunk-NKA6ZJDV.js";
9
- import "./chunk-3UW6GWYQ.js";
8
+ import "./chunk-VC23AJJJ.js";
9
+ import "./chunk-M57VI7KL.js";
10
10
  export {
11
11
  executeCron,
12
12
  listCronJobs,
package/dist/index.d.ts CHANGED
@@ -57,6 +57,7 @@ interface Subroutine {
57
57
  description?: string;
58
58
  parameters?: ParameterMetadata[];
59
59
  meta?: Record<string, string>;
60
+ sourcePath?: string;
60
61
  }
61
62
  /**
62
63
  * Execution context - maps to MaskSession in MASK
package/dist/index.js CHANGED
@@ -2,19 +2,19 @@ import {
2
2
  createLLMAdapter,
3
3
  execute,
4
4
  executeUserCommand
5
- } from "./chunk-3IC2OMWT.js";
5
+ } from "./chunk-6SKZC4N7.js";
6
6
  import {
7
7
  integrate
8
- } from "./chunk-XNH4TU3Q.js";
8
+ } from "./chunk-QUFYZS2S.js";
9
9
  import {
10
10
  DiracParser
11
11
  } from "./chunk-HRHAMPOB.js";
12
- import "./chunk-NKA6ZJDV.js";
12
+ import "./chunk-VC23AJJJ.js";
13
13
  import {
14
14
  createSession,
15
15
  getAvailableSubroutines,
16
16
  getOutput
17
- } from "./chunk-3UW6GWYQ.js";
17
+ } from "./chunk-M57VI7KL.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-XNH4TU3Q.js";
4
+ } from "./chunk-QUFYZS2S.js";
5
5
  import "./chunk-HRHAMPOB.js";
6
- import "./chunk-NKA6ZJDV.js";
7
- import "./chunk-3UW6GWYQ.js";
6
+ import "./chunk-VC23AJJJ.js";
7
+ import "./chunk-M57VI7KL.js";
8
8
  export {
9
9
  integrate,
10
10
  integrateChildren
@@ -3,10 +3,10 @@ import {
3
3
  cancelScheduledRun,
4
4
  executeRunAt,
5
5
  listScheduledRuns
6
- } from "./chunk-XNH4TU3Q.js";
6
+ } from "./chunk-QUFYZS2S.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
- import "./chunk-NKA6ZJDV.js";
9
- import "./chunk-3UW6GWYQ.js";
8
+ import "./chunk-VC23AJJJ.js";
9
+ import "./chunk-M57VI7KL.js";
10
10
  export {
11
11
  cancelAllScheduledRuns,
12
12
  cancelScheduledRun,
@@ -3,10 +3,10 @@ import {
3
3
  listScheduledTasks,
4
4
  stopAllScheduledTasks,
5
5
  stopScheduledTask
6
- } from "./chunk-XNH4TU3Q.js";
6
+ } from "./chunk-QUFYZS2S.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
- import "./chunk-NKA6ZJDV.js";
9
- import "./chunk-3UW6GWYQ.js";
8
+ import "./chunk-VC23AJJJ.js";
9
+ import "./chunk-M57VI7KL.js";
10
10
  export {
11
11
  executeSchedule,
12
12
  listScheduledTasks,
@@ -26,7 +26,7 @@ import {
26
26
  substituteVariables,
27
27
  throwException,
28
28
  unsetExceptionBoundary
29
- } from "./chunk-3UW6GWYQ.js";
29
+ } from "./chunk-M57VI7KL.js";
30
30
  export {
31
31
  cleanSubroutinesToBoundary,
32
32
  cleanToBoundary,
@@ -2,11 +2,11 @@ import {
2
2
  SessionServer,
3
3
  getSocketPath,
4
4
  isSessionRunning
5
- } from "./chunk-6OIMDS6G.js";
6
- import "./chunk-XNH4TU3Q.js";
5
+ } from "./chunk-65TBONV6.js";
6
+ import "./chunk-QUFYZS2S.js";
7
7
  import "./chunk-HRHAMPOB.js";
8
- import "./chunk-NKA6ZJDV.js";
9
- import "./chunk-3UW6GWYQ.js";
8
+ import "./chunk-VC23AJJJ.js";
9
+ import "./chunk-M57VI7KL.js";
10
10
  export {
11
11
  SessionServer,
12
12
  getSocketPath,
@@ -4,14 +4,14 @@ import {
4
4
  } from "./chunk-AJSYOXXZ.js";
5
5
  import {
6
6
  integrate
7
- } from "./chunk-XNH4TU3Q.js";
7
+ } from "./chunk-QUFYZS2S.js";
8
8
  import {
9
9
  DiracParser
10
10
  } from "./chunk-HRHAMPOB.js";
11
- import "./chunk-NKA6ZJDV.js";
11
+ import "./chunk-VC23AJJJ.js";
12
12
  import {
13
13
  createSession
14
- } from "./chunk-3UW6GWYQ.js";
14
+ } from "./chunk-M57VI7KL.js";
15
15
 
16
16
  // src/shell.ts
17
17
  import * as readline from "readline";
@@ -271,16 +271,73 @@ var DiracShell = class {
271
271
  } catch (err) {
272
272
  }
273
273
  }
274
+ checkUnsavedSubroutines() {
275
+ const unsaved = [];
276
+ const excludePaths = [
277
+ path.join(os.homedir(), ".dirac", "lib"),
278
+ // System library
279
+ "/tmp/"
280
+ // Temp files
281
+ ];
282
+ for (const sub of this.session.subroutines) {
283
+ if (sub.meta && sub.meta["hide-from-llm"] === "true") {
284
+ continue;
285
+ }
286
+ if (!sub.sourcePath) {
287
+ unsaved.push({ name: sub.name, reason: "created in session" });
288
+ } else {
289
+ const isExcluded = excludePaths.some(
290
+ (excludePath) => sub.sourcePath.startsWith(excludePath)
291
+ );
292
+ if (isExcluded) {
293
+ continue;
294
+ }
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
+ }
309
+ }
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');
316
+ }
317
+ }
318
+ countSubroutinesInAST(element) {
319
+ let count = 0;
320
+ if (element.tag === "subroutine") {
321
+ count = 1;
322
+ }
323
+ if (element.children) {
324
+ for (const child of element.children) {
325
+ count += this.countSubroutinesInAST(child);
326
+ }
327
+ }
328
+ return count;
329
+ }
274
330
  setupHandlers() {
275
331
  this.rl.on("line", async (input) => {
276
332
  await this.handleInput(input);
277
333
  });
278
334
  this.rl.on("close", () => {
335
+ this.checkUnsavedSubroutines();
279
336
  this.saveHistory();
280
337
  if (this.client) {
281
338
  this.client.disconnect();
282
339
  }
283
- import("./schedule-U4S53I4N.js").then(({ stopAllScheduledTasks }) => {
340
+ import("./schedule-ZGPBTVXG.js").then(({ stopAllScheduledTasks }) => {
284
341
  stopAllScheduledTasks();
285
342
  console.log("\nGoodbye!");
286
343
  process.exit(0);
@@ -646,7 +703,7 @@ Examples:
646
703
  break;
647
704
  case "tasks":
648
705
  try {
649
- const { listScheduledTasks } = await import("./schedule-U4S53I4N.js");
706
+ const { listScheduledTasks } = await import("./schedule-ZGPBTVXG.js");
650
707
  const tasks = listScheduledTasks();
651
708
  if (tasks.length === 0) {
652
709
  console.log("No scheduled tasks running.");
@@ -665,7 +722,7 @@ Examples:
665
722
  console.log("Usage: :stop <task-name>");
666
723
  } else {
667
724
  try {
668
- const { stopScheduledTask } = await import("./schedule-U4S53I4N.js");
725
+ const { stopScheduledTask } = await import("./schedule-ZGPBTVXG.js");
669
726
  const taskName = args[0];
670
727
  const stopped = stopScheduledTask(taskName);
671
728
  if (stopped) {
@@ -680,7 +737,7 @@ Examples:
680
737
  break;
681
738
  case "stopall":
682
739
  try {
683
- const { stopAllScheduledTasks } = await import("./schedule-U4S53I4N.js");
740
+ const { stopAllScheduledTasks } = await import("./schedule-ZGPBTVXG.js");
684
741
  stopAllScheduledTasks();
685
742
  console.log("All scheduled tasks stopped.");
686
743
  } catch (error) {
@@ -689,7 +746,7 @@ Examples:
689
746
  break;
690
747
  case "crons":
691
748
  try {
692
- const { listCronJobs } = await import("./cron-J54RKLKD.js");
749
+ const { listCronJobs } = await import("./cron-VEWKZ2ZU.js");
693
750
  const jobs = listCronJobs();
694
751
  if (jobs.length === 0) {
695
752
  console.log("No cron jobs running.");
@@ -709,7 +766,7 @@ Examples:
709
766
  console.log("Usage: :stopcron <job-name>");
710
767
  } else {
711
768
  try {
712
- const { stopCronJob } = await import("./cron-J54RKLKD.js");
769
+ const { stopCronJob } = await import("./cron-VEWKZ2ZU.js");
713
770
  const jobName = args[0];
714
771
  const stopped = stopCronJob(jobName);
715
772
  if (stopped) {
@@ -724,7 +781,7 @@ Examples:
724
781
  break;
725
782
  case "stopallcrons":
726
783
  try {
727
- const { stopAllCronJobs } = await import("./cron-J54RKLKD.js");
784
+ const { stopAllCronJobs } = await import("./cron-VEWKZ2ZU.js");
728
785
  stopAllCronJobs();
729
786
  console.log("All cron jobs stopped.");
730
787
  } catch (error) {
@@ -733,7 +790,7 @@ Examples:
733
790
  break;
734
791
  case "scheduled":
735
792
  try {
736
- const { listScheduledRuns } = await import("./run-at-GX2JTTG4.js");
793
+ const { listScheduledRuns } = await import("./run-at-OPGYI26L.js");
737
794
  const runs = listScheduledRuns();
738
795
  if (runs.length === 0) {
739
796
  console.log("No scheduled runs pending.");
@@ -753,7 +810,7 @@ Examples:
753
810
  console.log("Usage: :cancel <run-name>");
754
811
  } else {
755
812
  try {
756
- const { cancelScheduledRun } = await import("./run-at-GX2JTTG4.js");
813
+ const { cancelScheduledRun } = await import("./run-at-OPGYI26L.js");
757
814
  const runName = args[0];
758
815
  const cancelled = cancelScheduledRun(runName);
759
816
  if (cancelled) {
@@ -768,7 +825,7 @@ Examples:
768
825
  break;
769
826
  case "cancelall":
770
827
  try {
771
- const { cancelAllScheduledRuns } = await import("./run-at-GX2JTTG4.js");
828
+ const { cancelAllScheduledRuns } = await import("./run-at-OPGYI26L.js");
772
829
  cancelAllScheduledRuns();
773
830
  console.log("All scheduled runs cancelled.");
774
831
  } catch (error) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeSubroutine
3
- } from "./chunk-NKA6ZJDV.js";
4
- import "./chunk-3UW6GWYQ.js";
3
+ } from "./chunk-VC23AJJJ.js";
4
+ import "./chunk-M57VI7KL.js";
5
5
  export {
6
6
  executeSubroutine
7
7
  };
@@ -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-AZIX6ILU.js");
52
+ const { getAvailableSubroutines } = await import("./session-OL5ARO6Q.js");
53
53
  const subroutines = getAvailableSubroutines(session);
54
54
  const allowed = new Set(subroutines.map((s) => s.name));
55
55
  const tagName = element.tag;
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-XNH4TU3Q.js";
3
+ } from "./chunk-QUFYZS2S.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
7
- import "./chunk-NKA6ZJDV.js";
7
+ import "./chunk-VC23AJJJ.js";
8
8
  import {
9
9
  createSession,
10
10
  getOutput
11
- } from "./chunk-3UW6GWYQ.js";
11
+ } from "./chunk-M57VI7KL.js";
12
12
 
13
13
  // src/test-runner.ts
14
14
  import fs from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirac-lang",
3
- "version": "0.1.67",
3
+ "version": "0.1.69",
4
4
  "description": "LLM-Augmented Declarative Execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",