dirac-lang 0.1.97 → 0.1.99
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/dist/{agent-MJSTQERB.js → agent-3SJF56JW.js} +5 -5
- package/dist/{chunk-4TBIVB4X.js → chunk-3VCKPUTQ.js} +143 -30
- package/dist/{chunk-SLGJRZ3P.js → chunk-53QJQ2CC.js} +1 -1
- package/dist/{chunk-ECAW4X46.js → chunk-EAM7IZWA.js} +1 -1
- package/dist/{chunk-CDTZNFCJ.js → chunk-EE3YBMAD.js} +2 -2
- package/dist/{chunk-KFMG6CZW.js → chunk-R6R6OHPA.js} +2 -2
- package/dist/{chunk-PPH7KYKH.js → chunk-ZYSWVMID.js} +6 -0
- package/dist/cli.js +12 -12
- package/dist/{cron-2J3SEPZW.js → cron-TTPFON3Y.js} +4 -4
- package/dist/index.js +5 -5
- package/dist/interpreter-ENHZAIWT.js +12 -0
- package/dist/{run-at-MHURF5PL.js → run-at-A3CJX4TR.js} +4 -4
- package/dist/{schedule-KMBLI46W.js → schedule-OYEKDXZV.js} +4 -4
- package/dist/scope-validator-TVQIOEAI.js +171 -0
- package/dist/{session-IH5LO7FS.js → session-6WX5O74B.js} +3 -1
- package/dist/{session-server-TQPJVLA4.js → session-server-LMDDND5E.js} +5 -5
- package/dist/{shell-CY5XIPQC.js → shell-PV6KIJL5.js} +156 -15
- package/dist/{subroutine-7JJKHTV4.js → subroutine-O3YGYHRZ.js} +2 -2
- package/dist/{subroutine-index-RVJSWWJ7.js → subroutine-index-GB3OSH56.js} +2 -2
- package/dist/subroutine-serializer-LNFHABUC.js +160 -0
- package/dist/{tag-validator-REN6XLMT.js → tag-validator-QS7T4GFE.js} +110 -19
- package/dist/test-runner.js +4 -4
- package/lib/native-tags.di +2 -1
- package/package.json +1 -1
- package/dist/interpreter-4CIWAOBY.js +0 -12
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// src/utils/scope-validator.ts
|
|
2
|
+
function extractParameterNames(element) {
|
|
3
|
+
const params = [];
|
|
4
|
+
for (const attr in element.attributes) {
|
|
5
|
+
if (attr.startsWith("param-")) {
|
|
6
|
+
const paramName = attr.slice(6);
|
|
7
|
+
params.push(paramName);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return params;
|
|
11
|
+
}
|
|
12
|
+
function extractVariableReferences(text) {
|
|
13
|
+
const pattern = /\$\{([a-zA-Z_][a-zA-Z0-9_-]*)\}/g;
|
|
14
|
+
const matches = [];
|
|
15
|
+
let match;
|
|
16
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
17
|
+
matches.push(match[1]);
|
|
18
|
+
}
|
|
19
|
+
return matches;
|
|
20
|
+
}
|
|
21
|
+
var ScopeContext = class {
|
|
22
|
+
parameters;
|
|
23
|
+
// Declared parameters
|
|
24
|
+
declaredVariables;
|
|
25
|
+
// Variables declared with <defvar>
|
|
26
|
+
referencedVariables;
|
|
27
|
+
// Variables referenced with <variable> or ${}
|
|
28
|
+
referencedParameters;
|
|
29
|
+
// Parameters actually used
|
|
30
|
+
constructor(parameters) {
|
|
31
|
+
this.parameters = new Set(parameters);
|
|
32
|
+
this.declaredVariables = /* @__PURE__ */ new Set();
|
|
33
|
+
this.referencedVariables = /* @__PURE__ */ new Set();
|
|
34
|
+
this.referencedParameters = /* @__PURE__ */ new Set();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if a name is available in current scope
|
|
38
|
+
* Priority: parameters -> declared variables
|
|
39
|
+
*/
|
|
40
|
+
isInScope(name) {
|
|
41
|
+
return this.parameters.has(name) || this.declaredVariables.has(name);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Record a variable declaration
|
|
45
|
+
*/
|
|
46
|
+
declareVariable(name) {
|
|
47
|
+
this.declaredVariables.add(name);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Record a variable/parameter reference
|
|
51
|
+
*/
|
|
52
|
+
referenceVariable(name) {
|
|
53
|
+
this.referencedVariables.add(name);
|
|
54
|
+
if (this.parameters.has(name)) {
|
|
55
|
+
this.referencedParameters.add(name);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
function validateScope(element, scope, errors, warnings) {
|
|
60
|
+
if (element.tag === "defvar") {
|
|
61
|
+
const varName = element.attributes.name;
|
|
62
|
+
if (varName) {
|
|
63
|
+
scope.declareVariable(varName);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (element.tag === "variable") {
|
|
67
|
+
const varName = element.attributes.name;
|
|
68
|
+
if (varName) {
|
|
69
|
+
scope.referenceVariable(varName);
|
|
70
|
+
if (!scope.isInScope(varName)) {
|
|
71
|
+
warnings.push(
|
|
72
|
+
`Variable reference '${varName}' not found in local scope (may be from parent scope)`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (element.tag === "parameters") {
|
|
78
|
+
const select = element.attributes.select;
|
|
79
|
+
if (select && select.startsWith("@")) {
|
|
80
|
+
const paramName = select.slice(1);
|
|
81
|
+
scope.referenceVariable(paramName);
|
|
82
|
+
if (!scope.isInScope(paramName)) {
|
|
83
|
+
warnings.push(
|
|
84
|
+
`Parameter reference '${paramName}' not found in subroutine parameters`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const [attrName, attrValue] of Object.entries(element.attributes)) {
|
|
90
|
+
if (typeof attrValue === "string") {
|
|
91
|
+
const varRefs = extractVariableReferences(attrValue);
|
|
92
|
+
for (const varRef of varRefs) {
|
|
93
|
+
scope.referenceVariable(varRef);
|
|
94
|
+
if (!scope.isInScope(varRef)) {
|
|
95
|
+
warnings.push(
|
|
96
|
+
`Variable substitution '\${${varRef}}' in attribute not found in local scope (may be from parent scope)`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const dollarVarPattern = /\$([a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
101
|
+
let dollarMatch;
|
|
102
|
+
while ((dollarMatch = dollarVarPattern.exec(attrValue)) !== null) {
|
|
103
|
+
const varName = dollarMatch[1];
|
|
104
|
+
scope.referenceVariable(varName);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const child of element.children) {
|
|
109
|
+
validateScope(child, scope, errors, warnings);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function validateSubroutineScope(subroutine) {
|
|
113
|
+
const errors = [];
|
|
114
|
+
const warnings = [];
|
|
115
|
+
const parameters = extractParameterNames(subroutine);
|
|
116
|
+
const scope = new ScopeContext(parameters);
|
|
117
|
+
for (const child of subroutine.children) {
|
|
118
|
+
validateScope(child, scope, errors, warnings);
|
|
119
|
+
}
|
|
120
|
+
const unusedParameters = parameters.filter((p) => !scope.referencedParameters.has(p));
|
|
121
|
+
if (unusedParameters.length > 0) {
|
|
122
|
+
warnings.push(
|
|
123
|
+
`Unused parameters: ${unusedParameters.join(", ")}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
const unusedVariables = Array.from(scope.declaredVariables).filter(
|
|
127
|
+
(v) => !scope.referencedVariables.has(v)
|
|
128
|
+
);
|
|
129
|
+
if (unusedVariables.length > 0) {
|
|
130
|
+
warnings.push(
|
|
131
|
+
`Unused variables: ${unusedVariables.join(", ")}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const undefinedReferences = Array.from(scope.referencedVariables).filter(
|
|
135
|
+
(v) => !scope.isInScope(v)
|
|
136
|
+
);
|
|
137
|
+
const undefinedParameters = undefinedReferences.filter(
|
|
138
|
+
(v) => !scope.declaredVariables.has(v)
|
|
139
|
+
);
|
|
140
|
+
const undefinedVariables = undefinedReferences.filter(
|
|
141
|
+
(v) => scope.declaredVariables.has(v)
|
|
142
|
+
);
|
|
143
|
+
return {
|
|
144
|
+
valid: errors.length === 0,
|
|
145
|
+
errors,
|
|
146
|
+
warnings,
|
|
147
|
+
undefinedParameters,
|
|
148
|
+
undefinedVariables,
|
|
149
|
+
unusedParameters,
|
|
150
|
+
unusedVariables
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function validateAllSubroutineScopes(ast) {
|
|
154
|
+
const results = /* @__PURE__ */ new Map();
|
|
155
|
+
function findSubroutines(element) {
|
|
156
|
+
if (element.tag === "subroutine") {
|
|
157
|
+
const name = element.attributes.name || "anonymous";
|
|
158
|
+
const result = validateSubroutineScope(element);
|
|
159
|
+
results.set(name, result);
|
|
160
|
+
}
|
|
161
|
+
for (const child of element.children) {
|
|
162
|
+
findSubroutines(child);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
findSubroutines(ast);
|
|
166
|
+
return results;
|
|
167
|
+
}
|
|
168
|
+
export {
|
|
169
|
+
validateAllSubroutineScopes,
|
|
170
|
+
validateSubroutineScope
|
|
171
|
+
};
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
popToBoundary,
|
|
19
19
|
pushParameters,
|
|
20
20
|
registerSubroutine,
|
|
21
|
+
removeSubroutine,
|
|
21
22
|
setBoundary,
|
|
22
23
|
setExceptionBoundary,
|
|
23
24
|
setSubroutineBoundary,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
substituteVariables,
|
|
27
28
|
throwException,
|
|
28
29
|
unsetExceptionBoundary
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ZYSWVMID.js";
|
|
30
31
|
export {
|
|
31
32
|
cleanSubroutinesToBoundary,
|
|
32
33
|
cleanToBoundary,
|
|
@@ -47,6 +48,7 @@ export {
|
|
|
47
48
|
popToBoundary,
|
|
48
49
|
pushParameters,
|
|
49
50
|
registerSubroutine,
|
|
51
|
+
removeSubroutine,
|
|
50
52
|
setBoundary,
|
|
51
53
|
setExceptionBoundary,
|
|
52
54
|
setSubroutineBoundary,
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
SessionServer,
|
|
3
3
|
getSocketPath,
|
|
4
4
|
isSessionRunning
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-SLGJRZ3P.js";
|
|
5
|
+
} from "./chunk-R6R6OHPA.js";
|
|
6
|
+
import "./chunk-3VCKPUTQ.js";
|
|
7
|
+
import "./chunk-53QJQ2CC.js";
|
|
9
8
|
import "./chunk-HRHAMPOB.js";
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-EAM7IZWA.js";
|
|
10
|
+
import "./chunk-ZYSWVMID.js";
|
|
11
11
|
export {
|
|
12
12
|
SessionServer,
|
|
13
13
|
getSocketPath,
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BraKetParser,
|
|
4
4
|
integrate
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-SLGJRZ3P.js";
|
|
5
|
+
} from "./chunk-3VCKPUTQ.js";
|
|
6
|
+
import "./chunk-53QJQ2CC.js";
|
|
8
7
|
import {
|
|
9
8
|
DiracParser
|
|
10
9
|
} from "./chunk-HRHAMPOB.js";
|
|
10
|
+
import "./chunk-EAM7IZWA.js";
|
|
11
11
|
import {
|
|
12
12
|
createSession
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZYSWVMID.js";
|
|
14
14
|
|
|
15
15
|
// src/shell.ts
|
|
16
16
|
import * as readline from "readline";
|
|
@@ -358,7 +358,7 @@ var DiracShell = class {
|
|
|
358
358
|
if (this.client) {
|
|
359
359
|
this.client.disconnect();
|
|
360
360
|
}
|
|
361
|
-
import("./schedule-
|
|
361
|
+
import("./schedule-OYEKDXZV.js").then(({ stopAllScheduledTasks }) => {
|
|
362
362
|
stopAllScheduledTasks();
|
|
363
363
|
console.log("\nGoodbye!");
|
|
364
364
|
process.exit(0);
|
|
@@ -504,6 +504,15 @@ var DiracShell = class {
|
|
|
504
504
|
if (this.session.output.length > 0) {
|
|
505
505
|
console.log(this.session.output.join(""));
|
|
506
506
|
}
|
|
507
|
+
const silentExecution = this.session.variables.find((v) => v.name === "__llm_silent_execution__");
|
|
508
|
+
if (silentExecution?.value) {
|
|
509
|
+
console.error(`
|
|
510
|
+
[LLM generated]
|
|
511
|
+
${silentExecution.value}
|
|
512
|
+
`);
|
|
513
|
+
const idx = this.session.variables.findIndex((v) => v.name === "__llm_silent_execution__");
|
|
514
|
+
if (idx !== -1) this.session.variables.splice(idx, 1);
|
|
515
|
+
}
|
|
507
516
|
} catch (error) {
|
|
508
517
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
509
518
|
if (this.config.debug && error instanceof Error && error.stack) {
|
|
@@ -532,6 +541,8 @@ Commands:
|
|
|
532
541
|
:search <query> Search indexed subroutines
|
|
533
542
|
:load <query> Load context (search and import subroutines)
|
|
534
543
|
:save <name> [file] Save subroutine (default: ~/.dirac/lib/TIMESTAMP/name.di)
|
|
544
|
+
:edit <name> Edit subroutine in external editor
|
|
545
|
+
:remove <name> Remove subroutine from session stack (not from disk)
|
|
535
546
|
:stats Show registry statistics
|
|
536
547
|
:tasks List all scheduled tasks
|
|
537
548
|
:stop <name> Stop a scheduled task
|
|
@@ -543,6 +554,7 @@ Commands:
|
|
|
543
554
|
:cancel <name> Cancel a scheduled run
|
|
544
555
|
:cancelall Cancel all scheduled runs
|
|
545
556
|
:save-training [mode=full|pruned|both] Save LLM dialog as training data (opens in editor)
|
|
557
|
+
:save-subroutine-training <name> Save subroutine as training data with description
|
|
546
558
|
:exit Exit shell
|
|
547
559
|
|
|
548
560
|
Syntax:
|
|
@@ -749,6 +761,49 @@ Examples:
|
|
|
749
761
|
}
|
|
750
762
|
}
|
|
751
763
|
break;
|
|
764
|
+
case "edit":
|
|
765
|
+
if (args.length === 0) {
|
|
766
|
+
console.log("Usage: :edit <subroutine-name>");
|
|
767
|
+
console.log(" Opens the subroutine in your default editor ($EDITOR or vi)");
|
|
768
|
+
console.log("Examples:");
|
|
769
|
+
console.log(" :edit greet # edit greet subroutine in default editor");
|
|
770
|
+
console.log(" Use :save after editing to persist changes to disk");
|
|
771
|
+
} else {
|
|
772
|
+
const subName = args[0];
|
|
773
|
+
try {
|
|
774
|
+
const xml = `<edit-subroutine name="${subName}" />`;
|
|
775
|
+
const ast = this.xmlParser.parse(xml);
|
|
776
|
+
await integrate(this.session, ast);
|
|
777
|
+
if (this.session.output.length > 0) {
|
|
778
|
+
console.log(this.session.output.join(""));
|
|
779
|
+
}
|
|
780
|
+
} catch (error) {
|
|
781
|
+
console.error("Error editing subroutine:", error instanceof Error ? error.message : String(error));
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
break;
|
|
785
|
+
case "remove":
|
|
786
|
+
if (args.length === 0) {
|
|
787
|
+
console.log("Usage: :remove <subroutine-name>");
|
|
788
|
+
console.log(" Removes all instances of the subroutine from the session stack");
|
|
789
|
+
console.log(" Note: This does NOT delete the subroutine from disk");
|
|
790
|
+
console.log("Examples:");
|
|
791
|
+
console.log(" :remove greet # remove greet subroutine from session");
|
|
792
|
+
} else {
|
|
793
|
+
const subName = args[0];
|
|
794
|
+
try {
|
|
795
|
+
const { removeSubroutine } = await import("./session-6WX5O74B.js");
|
|
796
|
+
const removed = removeSubroutine(this.session, subName);
|
|
797
|
+
if (removed) {
|
|
798
|
+
console.log(`Removed subroutine '${subName}' from session stack`);
|
|
799
|
+
} else {
|
|
800
|
+
console.log(`Subroutine '${subName}' not found in session`);
|
|
801
|
+
}
|
|
802
|
+
} catch (error) {
|
|
803
|
+
console.error("Error removing subroutine:", error instanceof Error ? error.message : String(error));
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
break;
|
|
752
807
|
case "stats":
|
|
753
808
|
try {
|
|
754
809
|
const xml = "<registry-stats />";
|
|
@@ -763,7 +818,7 @@ Examples:
|
|
|
763
818
|
break;
|
|
764
819
|
case "tasks":
|
|
765
820
|
try {
|
|
766
|
-
const { listScheduledTasks } = await import("./schedule-
|
|
821
|
+
const { listScheduledTasks } = await import("./schedule-OYEKDXZV.js");
|
|
767
822
|
const tasks = listScheduledTasks();
|
|
768
823
|
if (tasks.length === 0) {
|
|
769
824
|
console.log("No scheduled tasks running.");
|
|
@@ -782,7 +837,7 @@ Examples:
|
|
|
782
837
|
console.log("Usage: :stop <task-name>");
|
|
783
838
|
} else {
|
|
784
839
|
try {
|
|
785
|
-
const { stopScheduledTask } = await import("./schedule-
|
|
840
|
+
const { stopScheduledTask } = await import("./schedule-OYEKDXZV.js");
|
|
786
841
|
const taskName = args[0];
|
|
787
842
|
const stopped = stopScheduledTask(taskName);
|
|
788
843
|
if (stopped) {
|
|
@@ -797,7 +852,7 @@ Examples:
|
|
|
797
852
|
break;
|
|
798
853
|
case "stopall":
|
|
799
854
|
try {
|
|
800
|
-
const { stopAllScheduledTasks } = await import("./schedule-
|
|
855
|
+
const { stopAllScheduledTasks } = await import("./schedule-OYEKDXZV.js");
|
|
801
856
|
stopAllScheduledTasks();
|
|
802
857
|
console.log("All scheduled tasks stopped.");
|
|
803
858
|
} catch (error) {
|
|
@@ -806,7 +861,7 @@ Examples:
|
|
|
806
861
|
break;
|
|
807
862
|
case "crons":
|
|
808
863
|
try {
|
|
809
|
-
const { listCronJobs } = await import("./cron-
|
|
864
|
+
const { listCronJobs } = await import("./cron-TTPFON3Y.js");
|
|
810
865
|
const jobs = listCronJobs();
|
|
811
866
|
if (jobs.length === 0) {
|
|
812
867
|
console.log("No cron jobs running.");
|
|
@@ -826,7 +881,7 @@ Examples:
|
|
|
826
881
|
console.log("Usage: :stopcron <job-name>");
|
|
827
882
|
} else {
|
|
828
883
|
try {
|
|
829
|
-
const { stopCronJob } = await import("./cron-
|
|
884
|
+
const { stopCronJob } = await import("./cron-TTPFON3Y.js");
|
|
830
885
|
const jobName = args[0];
|
|
831
886
|
const stopped = stopCronJob(jobName);
|
|
832
887
|
if (stopped) {
|
|
@@ -841,7 +896,7 @@ Examples:
|
|
|
841
896
|
break;
|
|
842
897
|
case "stopallcrons":
|
|
843
898
|
try {
|
|
844
|
-
const { stopAllCronJobs } = await import("./cron-
|
|
899
|
+
const { stopAllCronJobs } = await import("./cron-TTPFON3Y.js");
|
|
845
900
|
stopAllCronJobs();
|
|
846
901
|
console.log("All cron jobs stopped.");
|
|
847
902
|
} catch (error) {
|
|
@@ -850,7 +905,7 @@ Examples:
|
|
|
850
905
|
break;
|
|
851
906
|
case "scheduled":
|
|
852
907
|
try {
|
|
853
|
-
const { listScheduledRuns } = await import("./run-at-
|
|
908
|
+
const { listScheduledRuns } = await import("./run-at-A3CJX4TR.js");
|
|
854
909
|
const runs = listScheduledRuns();
|
|
855
910
|
if (runs.length === 0) {
|
|
856
911
|
console.log("No scheduled runs pending.");
|
|
@@ -870,7 +925,7 @@ Examples:
|
|
|
870
925
|
console.log("Usage: :cancel <run-name>");
|
|
871
926
|
} else {
|
|
872
927
|
try {
|
|
873
|
-
const { cancelScheduledRun } = await import("./run-at-
|
|
928
|
+
const { cancelScheduledRun } = await import("./run-at-A3CJX4TR.js");
|
|
874
929
|
const runName = args[0];
|
|
875
930
|
const cancelled = cancelScheduledRun(runName);
|
|
876
931
|
if (cancelled) {
|
|
@@ -885,13 +940,99 @@ Examples:
|
|
|
885
940
|
break;
|
|
886
941
|
case "cancelall":
|
|
887
942
|
try {
|
|
888
|
-
const { cancelAllScheduledRuns } = await import("./run-at-
|
|
943
|
+
const { cancelAllScheduledRuns } = await import("./run-at-A3CJX4TR.js");
|
|
889
944
|
cancelAllScheduledRuns();
|
|
890
945
|
console.log("All scheduled runs cancelled.");
|
|
891
946
|
} catch (error) {
|
|
892
947
|
console.error("Error cancelling runs:", error instanceof Error ? error.message : String(error));
|
|
893
948
|
}
|
|
894
949
|
break;
|
|
950
|
+
case "save-subroutine-training":
|
|
951
|
+
if (args.length === 0) {
|
|
952
|
+
console.log("Usage: :save-subroutine-training <subroutine-name>");
|
|
953
|
+
console.log(" Saves a subroutine as training data (opens in editor)");
|
|
954
|
+
console.log(" You will be prompted to provide a description for the training example");
|
|
955
|
+
console.log("Examples:");
|
|
956
|
+
console.log(" :save-subroutine-training greet");
|
|
957
|
+
} else {
|
|
958
|
+
const subName = args[0];
|
|
959
|
+
try {
|
|
960
|
+
let subroutine = void 0;
|
|
961
|
+
const subroutines = this.client ? (await this.client.getState()).subroutines || [] : this.session.subroutines;
|
|
962
|
+
for (let i = subroutines.length - 1; i >= 0; i--) {
|
|
963
|
+
if (subroutines[i].name === subName) {
|
|
964
|
+
subroutine = subroutines[i];
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
if (!subroutine) {
|
|
969
|
+
console.log(`Subroutine '${subName}' not found in session`);
|
|
970
|
+
break;
|
|
971
|
+
}
|
|
972
|
+
const description = await new Promise((resolve2) => {
|
|
973
|
+
this.rl.question(`Enter description (user's request that would generate this subroutine): `, resolve2);
|
|
974
|
+
});
|
|
975
|
+
if (!description.trim()) {
|
|
976
|
+
console.log("Cancelled (no description provided)");
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
const { serializeSubroutineForTraining } = await import("./subroutine-serializer-LNFHABUC.js");
|
|
980
|
+
const subroutineContent = serializeSubroutineForTraining(subroutine);
|
|
981
|
+
const trainingExample = {
|
|
982
|
+
messages: [
|
|
983
|
+
{ role: "user", content: description.trim() },
|
|
984
|
+
{ role: "assistant", content: subroutineContent }
|
|
985
|
+
]
|
|
986
|
+
};
|
|
987
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Date.now();
|
|
988
|
+
const tempFile = path.join(os.tmpdir(), `dirac-subroutine-training-${timestamp}.jsonl`);
|
|
989
|
+
const tempContent = JSON.stringify(trainingExample, null, 2);
|
|
990
|
+
fs.writeFileSync(tempFile, tempContent, "utf-8");
|
|
991
|
+
console.log("Opening in editor...");
|
|
992
|
+
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
993
|
+
const { spawnSync } = await import("child_process");
|
|
994
|
+
const result = spawnSync(editor, [tempFile], {
|
|
995
|
+
stdio: "inherit",
|
|
996
|
+
shell: true
|
|
997
|
+
});
|
|
998
|
+
if (result.error) {
|
|
999
|
+
fs.unlinkSync(tempFile);
|
|
1000
|
+
console.error(`Failed to open editor: ${result.error.message}`);
|
|
1001
|
+
break;
|
|
1002
|
+
}
|
|
1003
|
+
if (result.status !== 0) {
|
|
1004
|
+
fs.unlinkSync(tempFile);
|
|
1005
|
+
console.error(`Editor exited with code ${result.status}`);
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
const answer = await new Promise((resolve2) => {
|
|
1009
|
+
this.rl.question("Save to file (or press Enter to cancel): ", resolve2);
|
|
1010
|
+
});
|
|
1011
|
+
if (!answer.trim()) {
|
|
1012
|
+
fs.unlinkSync(tempFile);
|
|
1013
|
+
console.log("Cancelled");
|
|
1014
|
+
break;
|
|
1015
|
+
}
|
|
1016
|
+
let savePath;
|
|
1017
|
+
if (answer.startsWith("/") || answer.startsWith("~")) {
|
|
1018
|
+
savePath = answer.replace(/^~/, os.homedir());
|
|
1019
|
+
} else if (answer.includes("/")) {
|
|
1020
|
+
savePath = path.resolve(answer);
|
|
1021
|
+
} else {
|
|
1022
|
+
const trainingDir = path.join(os.homedir(), ".dirac", "training");
|
|
1023
|
+
fs.mkdirSync(trainingDir, { recursive: true });
|
|
1024
|
+
savePath = path.join(trainingDir, answer.endsWith(".jsonl") ? answer : `${answer}.jsonl`);
|
|
1025
|
+
}
|
|
1026
|
+
const editedContent = fs.readFileSync(tempFile, "utf-8");
|
|
1027
|
+
const editedData = JSON.parse(editedContent);
|
|
1028
|
+
fs.appendFileSync(savePath, JSON.stringify(editedData) + "\n");
|
|
1029
|
+
console.log(`\u2713 Saved training example for '${subName}' to ${savePath}`);
|
|
1030
|
+
fs.unlinkSync(tempFile);
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
console.error("Error saving subroutine training data:", error instanceof Error ? error.message : String(error));
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
break;
|
|
895
1036
|
case "save-training":
|
|
896
1037
|
try {
|
|
897
1038
|
const fullCommand = cmd.slice(1);
|
|
@@ -1153,7 +1294,7 @@ ${JSON.stringify(prunedExample, null, 2)}`;
|
|
|
1153
1294
|
console.log("Set ANTHROPIC_API_KEY or OPENAI_API_KEY environment variable,");
|
|
1154
1295
|
console.log("or create ~/.dirac/config.yml with llmProvider and llmModel.\n");
|
|
1155
1296
|
}
|
|
1156
|
-
const { registry } = await import("./subroutine-index-
|
|
1297
|
+
const { registry } = await import("./subroutine-index-GB3OSH56.js");
|
|
1157
1298
|
const wasIndexed = await registry.autoIndexStdlib();
|
|
1158
1299
|
await this.loadEssentialSubroutines();
|
|
1159
1300
|
if (this.config.initScript) {
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
executeRegistryStats,
|
|
4
4
|
executeSearchSubroutines,
|
|
5
5
|
registry
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-53QJQ2CC.js";
|
|
7
7
|
import "./chunk-HRHAMPOB.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-ZYSWVMID.js";
|
|
9
9
|
export {
|
|
10
10
|
executeIndexSubroutines,
|
|
11
11
|
executeRegistryStats,
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/utils/subroutine-serializer.ts
|
|
2
|
+
function serializeSubroutineForTraining(sub) {
|
|
3
|
+
const lines = [];
|
|
4
|
+
serializeElement(sub.element, lines, "");
|
|
5
|
+
return lines.join("\n");
|
|
6
|
+
}
|
|
7
|
+
function serializeSubroutineToXML(sub) {
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push("<!-- Editing subroutine: " + sub.name + " -->");
|
|
10
|
+
lines.push("");
|
|
11
|
+
serializeElement(sub.element, lines, "");
|
|
12
|
+
return lines.join("\n");
|
|
13
|
+
}
|
|
14
|
+
function serializeElement(el, lines, indent) {
|
|
15
|
+
if (!el.tag || el.tag === "") {
|
|
16
|
+
if (el.text) {
|
|
17
|
+
let lastIdx = lines.length - 1;
|
|
18
|
+
if (lastIdx >= 0 && !lines[lastIdx].endsWith(">")) {
|
|
19
|
+
lines[lastIdx] += el.text;
|
|
20
|
+
} else {
|
|
21
|
+
lines.push(indent + el.text);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let tag = `${indent}<${el.tag}`;
|
|
27
|
+
if (el.attributes) {
|
|
28
|
+
for (const [key, value] of Object.entries(el.attributes)) {
|
|
29
|
+
if (typeof value === "string") {
|
|
30
|
+
tag += ` ${key}="${value.replace(/"/g, """)}"`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const hasChildren = el.children && el.children.length > 0;
|
|
35
|
+
if (!hasChildren) {
|
|
36
|
+
let lastIdx = lines.length - 1;
|
|
37
|
+
if (lastIdx >= 0 && !lines[lastIdx].endsWith(">") && !lines[lastIdx].trim().startsWith("<")) {
|
|
38
|
+
lines[lastIdx] += tag.slice(indent.length) + " />";
|
|
39
|
+
} else {
|
|
40
|
+
lines.push(tag + " />");
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
let lastIdx = lines.length - 1;
|
|
44
|
+
const shouldInline = lastIdx >= 0 && !lines[lastIdx].endsWith(">");
|
|
45
|
+
if (shouldInline) {
|
|
46
|
+
lines[lastIdx] += tag.slice(indent.length) + ">";
|
|
47
|
+
} else {
|
|
48
|
+
lines.push(tag + ">");
|
|
49
|
+
}
|
|
50
|
+
let allInline = true;
|
|
51
|
+
for (let i = 0; i < el.children.length; i++) {
|
|
52
|
+
const child = el.children[i];
|
|
53
|
+
if (!child.tag || child.tag === "") {
|
|
54
|
+
if (child.text) {
|
|
55
|
+
lastIdx = lines.length - 1;
|
|
56
|
+
lines[lastIdx] += child.text;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
const isComplex = child.children && child.children.length > 0;
|
|
60
|
+
if (isComplex) {
|
|
61
|
+
allInline = false;
|
|
62
|
+
serializeElement(child, lines, indent + " ");
|
|
63
|
+
} else {
|
|
64
|
+
let childTag = `<${child.tag}`;
|
|
65
|
+
if (child.attributes) {
|
|
66
|
+
for (const [key, value] of Object.entries(child.attributes)) {
|
|
67
|
+
if (typeof value === "string") {
|
|
68
|
+
childTag += ` ${key}="${value.replace(/"/g, """)}"`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
childTag += " />";
|
|
73
|
+
lastIdx = lines.length - 1;
|
|
74
|
+
lines[lastIdx] += childTag;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
lastIdx = lines.length - 1;
|
|
79
|
+
if (allInline && lines[lastIdx].indexOf("<") > 0) {
|
|
80
|
+
lines[lastIdx] += `</${el.tag}>`;
|
|
81
|
+
} else {
|
|
82
|
+
lines.push(`${indent}</${el.tag}>`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function serializeSubroutineToBraKet(sub) {
|
|
87
|
+
const lines = [];
|
|
88
|
+
lines.push("<!-- Editing subroutine: " + sub.name + " -->");
|
|
89
|
+
lines.push("");
|
|
90
|
+
serializeElementToBraKet(sub.element, lines, 0);
|
|
91
|
+
return lines.join("\n");
|
|
92
|
+
}
|
|
93
|
+
function serializeElementToBraKet(el, lines, indent) {
|
|
94
|
+
const indentStr = " ".repeat(indent);
|
|
95
|
+
if (!el.tag || el.tag === "") {
|
|
96
|
+
if (el.text) {
|
|
97
|
+
lines.push(indentStr + el.text);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (el.tag === "subroutine") {
|
|
102
|
+
const name = el.attributes?.name || "unnamed";
|
|
103
|
+
let braLine = `${indentStr}<${name}|`;
|
|
104
|
+
if (el.attributes) {
|
|
105
|
+
for (const [key, value] of Object.entries(el.attributes)) {
|
|
106
|
+
if (key === "name") continue;
|
|
107
|
+
const needsQuotes = typeof value === "string" && (value.includes(" ") || value.includes("="));
|
|
108
|
+
braLine += ` ${key}=${needsQuotes ? '"' + value + '"' : value}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
lines.push(braLine);
|
|
112
|
+
if (el.children && el.children.length > 0) {
|
|
113
|
+
for (const child of el.children) {
|
|
114
|
+
serializeElementToBraKet(child, lines, indent + 1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
let ketLine = `${indentStr}|${el.tag}`;
|
|
120
|
+
if (el.attributes) {
|
|
121
|
+
for (const [key, value] of Object.entries(el.attributes)) {
|
|
122
|
+
if (typeof value === "string") {
|
|
123
|
+
const needsQuotes = value.includes(" ") || value.includes("=");
|
|
124
|
+
ketLine += ` ${key}=${needsQuotes ? '"' + value + '"' : value}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
ketLine += ">";
|
|
129
|
+
if (el.children && el.children.length > 0) {
|
|
130
|
+
const hasComplexChildren = el.children.some(
|
|
131
|
+
(c) => c.tag && c.tag !== "variable" && (c.children?.length > 0 || c.tag === "subroutine")
|
|
132
|
+
);
|
|
133
|
+
if (!hasComplexChildren) {
|
|
134
|
+
let inlineContent = "";
|
|
135
|
+
for (const child of el.children) {
|
|
136
|
+
if (!child.tag || child.tag === "") {
|
|
137
|
+
inlineContent += child.text || "";
|
|
138
|
+
} else if (child.tag === "variable") {
|
|
139
|
+
const varName = child.attributes?.name || "";
|
|
140
|
+
inlineContent += `|variable name=${varName}>`;
|
|
141
|
+
} else {
|
|
142
|
+
inlineContent += `|${child.tag}>`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
lines.push(ketLine + inlineContent);
|
|
146
|
+
} else {
|
|
147
|
+
lines.push(ketLine);
|
|
148
|
+
for (const child of el.children) {
|
|
149
|
+
serializeElementToBraKet(child, lines, indent + 1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
lines.push(ketLine);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
serializeSubroutineForTraining,
|
|
158
|
+
serializeSubroutineToBraKet,
|
|
159
|
+
serializeSubroutineToXML
|
|
160
|
+
};
|