@aigne/ash 0.0.1

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.
Files changed (146) hide show
  1. package/DESIGN.md +41 -0
  2. package/dist/ai-dev-loop/ash-run-result.cjs +12 -0
  3. package/dist/ai-dev-loop/ash-run-result.d.cts +28 -0
  4. package/dist/ai-dev-loop/ash-run-result.d.cts.map +1 -0
  5. package/dist/ai-dev-loop/ash-run-result.d.mts +28 -0
  6. package/dist/ai-dev-loop/ash-run-result.d.mts.map +1 -0
  7. package/dist/ai-dev-loop/ash-run-result.mjs +11 -0
  8. package/dist/ai-dev-loop/ash-run-result.mjs.map +1 -0
  9. package/dist/ai-dev-loop/ash-typed-error.cjs +51 -0
  10. package/dist/ai-dev-loop/ash-typed-error.d.cts +54 -0
  11. package/dist/ai-dev-loop/ash-typed-error.d.cts.map +1 -0
  12. package/dist/ai-dev-loop/ash-typed-error.d.mts +54 -0
  13. package/dist/ai-dev-loop/ash-typed-error.d.mts.map +1 -0
  14. package/dist/ai-dev-loop/ash-typed-error.mjs +50 -0
  15. package/dist/ai-dev-loop/ash-typed-error.mjs.map +1 -0
  16. package/dist/ai-dev-loop/ash-validate.cjs +27 -0
  17. package/dist/ai-dev-loop/ash-validate.d.cts +7 -0
  18. package/dist/ai-dev-loop/ash-validate.d.cts.map +1 -0
  19. package/dist/ai-dev-loop/ash-validate.d.mts +7 -0
  20. package/dist/ai-dev-loop/ash-validate.d.mts.map +1 -0
  21. package/dist/ai-dev-loop/ash-validate.mjs +28 -0
  22. package/dist/ai-dev-loop/ash-validate.mjs.map +1 -0
  23. package/dist/ai-dev-loop/dev-loop.cjs +134 -0
  24. package/dist/ai-dev-loop/dev-loop.d.cts +28 -0
  25. package/dist/ai-dev-loop/dev-loop.d.cts.map +1 -0
  26. package/dist/ai-dev-loop/dev-loop.d.mts +28 -0
  27. package/dist/ai-dev-loop/dev-loop.d.mts.map +1 -0
  28. package/dist/ai-dev-loop/dev-loop.mjs +135 -0
  29. package/dist/ai-dev-loop/dev-loop.mjs.map +1 -0
  30. package/dist/ai-dev-loop/index.cjs +24 -0
  31. package/dist/ai-dev-loop/index.d.cts +9 -0
  32. package/dist/ai-dev-loop/index.d.mts +9 -0
  33. package/dist/ai-dev-loop/index.mjs +10 -0
  34. package/dist/ai-dev-loop/live-mode.cjs +17 -0
  35. package/dist/ai-dev-loop/live-mode.d.cts +24 -0
  36. package/dist/ai-dev-loop/live-mode.d.cts.map +1 -0
  37. package/dist/ai-dev-loop/live-mode.d.mts +24 -0
  38. package/dist/ai-dev-loop/live-mode.d.mts.map +1 -0
  39. package/dist/ai-dev-loop/live-mode.mjs +17 -0
  40. package/dist/ai-dev-loop/live-mode.mjs.map +1 -0
  41. package/dist/ai-dev-loop/meta-tools.cjs +123 -0
  42. package/dist/ai-dev-loop/meta-tools.d.cts +24 -0
  43. package/dist/ai-dev-loop/meta-tools.d.cts.map +1 -0
  44. package/dist/ai-dev-loop/meta-tools.d.mts +24 -0
  45. package/dist/ai-dev-loop/meta-tools.d.mts.map +1 -0
  46. package/dist/ai-dev-loop/meta-tools.mjs +120 -0
  47. package/dist/ai-dev-loop/meta-tools.mjs.map +1 -0
  48. package/dist/ai-dev-loop/structured-runner.cjs +154 -0
  49. package/dist/ai-dev-loop/structured-runner.d.cts +12 -0
  50. package/dist/ai-dev-loop/structured-runner.d.cts.map +1 -0
  51. package/dist/ai-dev-loop/structured-runner.d.mts +12 -0
  52. package/dist/ai-dev-loop/structured-runner.d.mts.map +1 -0
  53. package/dist/ai-dev-loop/structured-runner.mjs +155 -0
  54. package/dist/ai-dev-loop/structured-runner.mjs.map +1 -0
  55. package/dist/ai-dev-loop/system-prompt.cjs +55 -0
  56. package/dist/ai-dev-loop/system-prompt.d.cts +20 -0
  57. package/dist/ai-dev-loop/system-prompt.d.cts.map +1 -0
  58. package/dist/ai-dev-loop/system-prompt.d.mts +20 -0
  59. package/dist/ai-dev-loop/system-prompt.d.mts.map +1 -0
  60. package/dist/ai-dev-loop/system-prompt.mjs +54 -0
  61. package/dist/ai-dev-loop/system-prompt.mjs.map +1 -0
  62. package/dist/ast.d.cts +140 -0
  63. package/dist/ast.d.cts.map +1 -0
  64. package/dist/ast.d.mts +140 -0
  65. package/dist/ast.d.mts.map +1 -0
  66. package/dist/compiler.cjs +802 -0
  67. package/dist/compiler.d.cts +103 -0
  68. package/dist/compiler.d.cts.map +1 -0
  69. package/dist/compiler.d.mts +103 -0
  70. package/dist/compiler.d.mts.map +1 -0
  71. package/dist/compiler.mjs +802 -0
  72. package/dist/compiler.mjs.map +1 -0
  73. package/dist/index.cjs +14 -0
  74. package/dist/index.d.cts +7 -0
  75. package/dist/index.d.mts +7 -0
  76. package/dist/index.mjs +7 -0
  77. package/dist/lexer.cjs +451 -0
  78. package/dist/lexer.d.cts +14 -0
  79. package/dist/lexer.d.cts.map +1 -0
  80. package/dist/lexer.d.mts +14 -0
  81. package/dist/lexer.d.mts.map +1 -0
  82. package/dist/lexer.mjs +451 -0
  83. package/dist/lexer.mjs.map +1 -0
  84. package/dist/parser.cjs +734 -0
  85. package/dist/parser.d.cts +40 -0
  86. package/dist/parser.d.cts.map +1 -0
  87. package/dist/parser.d.mts +40 -0
  88. package/dist/parser.d.mts.map +1 -0
  89. package/dist/parser.mjs +734 -0
  90. package/dist/parser.mjs.map +1 -0
  91. package/dist/reference.cjs +130 -0
  92. package/dist/reference.d.cts +11 -0
  93. package/dist/reference.d.cts.map +1 -0
  94. package/dist/reference.d.mts +11 -0
  95. package/dist/reference.d.mts.map +1 -0
  96. package/dist/reference.mjs +130 -0
  97. package/dist/reference.mjs.map +1 -0
  98. package/dist/template.cjs +85 -0
  99. package/dist/template.mjs +84 -0
  100. package/dist/template.mjs.map +1 -0
  101. package/dist/type-checker.cjs +582 -0
  102. package/dist/type-checker.d.cts +31 -0
  103. package/dist/type-checker.d.cts.map +1 -0
  104. package/dist/type-checker.d.mts +31 -0
  105. package/dist/type-checker.d.mts.map +1 -0
  106. package/dist/type-checker.mjs +573 -0
  107. package/dist/type-checker.mjs.map +1 -0
  108. package/package.json +29 -0
  109. package/src/ai-dev-loop/ash-run-result.test.ts +113 -0
  110. package/src/ai-dev-loop/ash-run-result.ts +46 -0
  111. package/src/ai-dev-loop/ash-typed-error.test.ts +136 -0
  112. package/src/ai-dev-loop/ash-typed-error.ts +50 -0
  113. package/src/ai-dev-loop/ash-validate.test.ts +54 -0
  114. package/src/ai-dev-loop/ash-validate.ts +34 -0
  115. package/src/ai-dev-loop/dev-loop.test.ts +364 -0
  116. package/src/ai-dev-loop/dev-loop.ts +156 -0
  117. package/src/ai-dev-loop/dry-run.test.ts +107 -0
  118. package/src/ai-dev-loop/e2e-multi-fix.test.ts +473 -0
  119. package/src/ai-dev-loop/e2e.test.ts +324 -0
  120. package/src/ai-dev-loop/index.ts +15 -0
  121. package/src/ai-dev-loop/invariants.test.ts +253 -0
  122. package/src/ai-dev-loop/live-mode.test.ts +63 -0
  123. package/src/ai-dev-loop/live-mode.ts +33 -0
  124. package/src/ai-dev-loop/meta-tools.test.ts +120 -0
  125. package/src/ai-dev-loop/meta-tools.ts +142 -0
  126. package/src/ai-dev-loop/structured-runner.test.ts +159 -0
  127. package/src/ai-dev-loop/structured-runner.ts +209 -0
  128. package/src/ai-dev-loop/system-prompt.test.ts +102 -0
  129. package/src/ai-dev-loop/system-prompt.ts +81 -0
  130. package/src/ast.ts +186 -0
  131. package/src/compiler.test.ts +2933 -0
  132. package/src/compiler.ts +1103 -0
  133. package/src/e2e.test.ts +552 -0
  134. package/src/index.ts +16 -0
  135. package/src/lexer.test.ts +538 -0
  136. package/src/lexer.ts +222 -0
  137. package/src/parser.test.ts +1024 -0
  138. package/src/parser.ts +835 -0
  139. package/src/reference.test.ts +166 -0
  140. package/src/reference.ts +125 -0
  141. package/src/template.test.ts +210 -0
  142. package/src/template.ts +139 -0
  143. package/src/type-checker.test.ts +1494 -0
  144. package/src/type-checker.ts +785 -0
  145. package/tsconfig.json +9 -0
  146. package/tsdown.config.ts +12 -0
@@ -0,0 +1,154 @@
1
+ const require_compiler = require('../compiler.cjs');
2
+ const require_ash_typed_error = require('./ash-typed-error.cjs');
3
+
4
+ //#region src/ai-dev-loop/structured-runner.ts
5
+ /**
6
+ * Structured Runner — Wraps ASH compileSource() + execute() with step tracking.
7
+ *
8
+ * Produces AshRunResult from raw ASH execution.
9
+ */
10
+ /**
11
+ * Wraps a WorldInterface to intercept all writes in dry-run mode.
12
+ * Reads pass through normally; write/publish are silently absorbed.
13
+ */
14
+ function createDryRunWorld(real) {
15
+ return {
16
+ read: (path, query) => real.read(path, query),
17
+ write: (_path, _data) => {},
18
+ publish: (_topic, _data) => {}
19
+ };
20
+ }
21
+ /**
22
+ * Wraps a WorldInterface to check an AbortSignal before every operation.
23
+ * Once aborted, all operations throw immediately — preventing side effects
24
+ * from continuing after a timeout.
25
+ */
26
+ function createCancellableWorld(real, signal) {
27
+ function checkAborted() {
28
+ if (signal.aborted) throw new Error("Execution cancelled: timeout");
29
+ }
30
+ return {
31
+ read(path, query) {
32
+ checkAborted();
33
+ return real.read(path, query);
34
+ },
35
+ write(path, data) {
36
+ checkAborted();
37
+ real.write(path, data);
38
+ },
39
+ publish(topic, data) {
40
+ checkAborted();
41
+ real.publish(topic, data);
42
+ },
43
+ ...real.exec ? { exec(path, input, params) {
44
+ checkAborted();
45
+ return real.exec(path, input, params);
46
+ } } : {},
47
+ ...real.input ? { input(prompt) {
48
+ checkAborted();
49
+ return real.input(prompt);
50
+ } } : {}
51
+ };
52
+ }
53
+ async function runStructured(source, ctx, options) {
54
+ const startTime = performance.now();
55
+ if (!source.trim()) return {
56
+ status: "ok",
57
+ steps: [],
58
+ output: [],
59
+ duration_ms: Math.round(performance.now() - startTime)
60
+ };
61
+ const compileResult = require_compiler.compileSource(source);
62
+ const errors = compileResult.diagnostics.filter((d) => d.severity !== "warning");
63
+ if (errors.length > 0 || !compileResult.program) {
64
+ const firstError = errors[0] ?? compileResult.diagnostics[0];
65
+ return {
66
+ status: "error",
67
+ steps: [],
68
+ failedAt: {
69
+ kind: "ParseError",
70
+ line: firstError?.line,
71
+ message: firstError?.message ?? "Compilation failed"
72
+ },
73
+ duration_ms: Math.round(performance.now() - startTime)
74
+ };
75
+ }
76
+ const program = compileResult.program;
77
+ const allSteps = [];
78
+ let execCtx = (options?.mode ?? "live") === "dry-run" ? {
79
+ ...ctx,
80
+ world: createDryRunWorld(ctx.world)
81
+ } : ctx;
82
+ const timeoutMs = options?.timeout_ms;
83
+ if (timeoutMs != null && timeoutMs > 0) {
84
+ const controller = new AbortController();
85
+ execCtx = {
86
+ ...execCtx,
87
+ world: createCancellableWorld(execCtx.world, controller.signal)
88
+ };
89
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
90
+ return Promise.race([executeUnits(program, execCtx, allSteps, startTime), new Promise((_, reject) => {
91
+ controller.signal.addEventListener("abort", () => reject(/* @__PURE__ */ new Error(`Timeout: execution exceeded ${timeoutMs}ms`)));
92
+ })]).catch((err) => ({
93
+ status: "error",
94
+ steps: allSteps,
95
+ failedAt: require_ash_typed_error.fromJobError(err.message ?? String(err)),
96
+ duration_ms: Math.round(performance.now() - startTime)
97
+ })).finally(() => clearTimeout(timer));
98
+ }
99
+ return executeUnits(program, execCtx, allSteps, startTime);
100
+ }
101
+ async function executeUnits(program, execCtx, allSteps, startTime) {
102
+ for (const unit of program.units) {
103
+ if (unit.kind === "output") {
104
+ await unit.execute(execCtx);
105
+ continue;
106
+ }
107
+ if (program.routeTargets?.has(unit.name)) continue;
108
+ try {
109
+ const jobResult = await unit.execute(execCtx);
110
+ const report = jobResult;
111
+ if (report.stages && Array.isArray(report.stages)) for (const stage of report.stages) allSteps.push({
112
+ step: stage.index ?? allSteps.length,
113
+ command: stage.name ?? "unknown",
114
+ status: stage.error ? "error" : "ok",
115
+ duration_ms: stage.durationMs ?? 0,
116
+ output: []
117
+ });
118
+ else allSteps.push({
119
+ step: allSteps.length,
120
+ command: unit.name ?? "job",
121
+ status: jobResult.status === "ok" ? "ok" : "error",
122
+ duration_ms: 0
123
+ });
124
+ if (jobResult.status === "error" && jobResult.errors.length > 0) return {
125
+ status: "error",
126
+ steps: allSteps,
127
+ failedAt: require_ash_typed_error.fromJobError(jobResult.errors[0]),
128
+ duration_ms: Math.round(performance.now() - startTime)
129
+ };
130
+ } catch (err) {
131
+ allSteps.push({
132
+ step: allSteps.length,
133
+ command: unit.name ?? "job",
134
+ status: "error",
135
+ duration_ms: 0
136
+ });
137
+ return {
138
+ status: "error",
139
+ steps: allSteps,
140
+ failedAt: require_ash_typed_error.fromJobError(err.message ?? String(err)),
141
+ duration_ms: Math.round(performance.now() - startTime)
142
+ };
143
+ }
144
+ }
145
+ return {
146
+ status: "ok",
147
+ steps: allSteps,
148
+ output: [],
149
+ duration_ms: Math.round(performance.now() - startTime)
150
+ };
151
+ }
152
+
153
+ //#endregion
154
+ exports.runStructured = runStructured;
@@ -0,0 +1,12 @@
1
+ import { AshRunResult } from "./ash-run-result.cjs";
2
+ import { JobContext } from "../compiler.cjs";
3
+
4
+ //#region src/ai-dev-loop/structured-runner.d.ts
5
+ interface RunOptions {
6
+ mode?: "dry-run" | "live";
7
+ timeout_ms?: number;
8
+ }
9
+ declare function runStructured(source: string, ctx: JobContext, options?: RunOptions): Promise<AshRunResult>;
10
+ //#endregion
11
+ export { runStructured };
12
+ //# sourceMappingURL=structured-runner.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-runner.d.cts","names":[],"sources":["../../src/ai-dev-loop/structured-runner.ts"],"mappings":";;;;UA2DiB,UAAA;EACf,IAAA;EACA,UAAA;AAAA;AAAA,iBAGoB,aAAA,CACpB,MAAA,UACA,GAAA,EAAK,UAAA,EACL,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,YAAA"}
@@ -0,0 +1,12 @@
1
+ import { AshRunResult } from "./ash-run-result.mjs";
2
+ import { JobContext } from "../compiler.mjs";
3
+
4
+ //#region src/ai-dev-loop/structured-runner.d.ts
5
+ interface RunOptions {
6
+ mode?: "dry-run" | "live";
7
+ timeout_ms?: number;
8
+ }
9
+ declare function runStructured(source: string, ctx: JobContext, options?: RunOptions): Promise<AshRunResult>;
10
+ //#endregion
11
+ export { runStructured };
12
+ //# sourceMappingURL=structured-runner.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-runner.d.mts","names":[],"sources":["../../src/ai-dev-loop/structured-runner.ts"],"mappings":";;;;UA2DiB,UAAA;EACf,IAAA;EACA,UAAA;AAAA;AAAA,iBAGoB,aAAA,CACpB,MAAA,UACA,GAAA,EAAK,UAAA,EACL,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,YAAA"}
@@ -0,0 +1,155 @@
1
+ import { compileSource } from "../compiler.mjs";
2
+ import { fromJobError } from "./ash-typed-error.mjs";
3
+
4
+ //#region src/ai-dev-loop/structured-runner.ts
5
+ /**
6
+ * Structured Runner — Wraps ASH compileSource() + execute() with step tracking.
7
+ *
8
+ * Produces AshRunResult from raw ASH execution.
9
+ */
10
+ /**
11
+ * Wraps a WorldInterface to intercept all writes in dry-run mode.
12
+ * Reads pass through normally; write/publish are silently absorbed.
13
+ */
14
+ function createDryRunWorld(real) {
15
+ return {
16
+ read: (path, query) => real.read(path, query),
17
+ write: (_path, _data) => {},
18
+ publish: (_topic, _data) => {}
19
+ };
20
+ }
21
+ /**
22
+ * Wraps a WorldInterface to check an AbortSignal before every operation.
23
+ * Once aborted, all operations throw immediately — preventing side effects
24
+ * from continuing after a timeout.
25
+ */
26
+ function createCancellableWorld(real, signal) {
27
+ function checkAborted() {
28
+ if (signal.aborted) throw new Error("Execution cancelled: timeout");
29
+ }
30
+ return {
31
+ read(path, query) {
32
+ checkAborted();
33
+ return real.read(path, query);
34
+ },
35
+ write(path, data) {
36
+ checkAborted();
37
+ real.write(path, data);
38
+ },
39
+ publish(topic, data) {
40
+ checkAborted();
41
+ real.publish(topic, data);
42
+ },
43
+ ...real.exec ? { exec(path, input, params) {
44
+ checkAborted();
45
+ return real.exec(path, input, params);
46
+ } } : {},
47
+ ...real.input ? { input(prompt) {
48
+ checkAborted();
49
+ return real.input(prompt);
50
+ } } : {}
51
+ };
52
+ }
53
+ async function runStructured(source, ctx, options) {
54
+ const startTime = performance.now();
55
+ if (!source.trim()) return {
56
+ status: "ok",
57
+ steps: [],
58
+ output: [],
59
+ duration_ms: Math.round(performance.now() - startTime)
60
+ };
61
+ const compileResult = compileSource(source);
62
+ const errors = compileResult.diagnostics.filter((d) => d.severity !== "warning");
63
+ if (errors.length > 0 || !compileResult.program) {
64
+ const firstError = errors[0] ?? compileResult.diagnostics[0];
65
+ return {
66
+ status: "error",
67
+ steps: [],
68
+ failedAt: {
69
+ kind: "ParseError",
70
+ line: firstError?.line,
71
+ message: firstError?.message ?? "Compilation failed"
72
+ },
73
+ duration_ms: Math.round(performance.now() - startTime)
74
+ };
75
+ }
76
+ const program = compileResult.program;
77
+ const allSteps = [];
78
+ let execCtx = (options?.mode ?? "live") === "dry-run" ? {
79
+ ...ctx,
80
+ world: createDryRunWorld(ctx.world)
81
+ } : ctx;
82
+ const timeoutMs = options?.timeout_ms;
83
+ if (timeoutMs != null && timeoutMs > 0) {
84
+ const controller = new AbortController();
85
+ execCtx = {
86
+ ...execCtx,
87
+ world: createCancellableWorld(execCtx.world, controller.signal)
88
+ };
89
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
90
+ return Promise.race([executeUnits(program, execCtx, allSteps, startTime), new Promise((_, reject) => {
91
+ controller.signal.addEventListener("abort", () => reject(/* @__PURE__ */ new Error(`Timeout: execution exceeded ${timeoutMs}ms`)));
92
+ })]).catch((err) => ({
93
+ status: "error",
94
+ steps: allSteps,
95
+ failedAt: fromJobError(err.message ?? String(err)),
96
+ duration_ms: Math.round(performance.now() - startTime)
97
+ })).finally(() => clearTimeout(timer));
98
+ }
99
+ return executeUnits(program, execCtx, allSteps, startTime);
100
+ }
101
+ async function executeUnits(program, execCtx, allSteps, startTime) {
102
+ for (const unit of program.units) {
103
+ if (unit.kind === "output") {
104
+ await unit.execute(execCtx);
105
+ continue;
106
+ }
107
+ if (program.routeTargets?.has(unit.name)) continue;
108
+ try {
109
+ const jobResult = await unit.execute(execCtx);
110
+ const report = jobResult;
111
+ if (report.stages && Array.isArray(report.stages)) for (const stage of report.stages) allSteps.push({
112
+ step: stage.index ?? allSteps.length,
113
+ command: stage.name ?? "unknown",
114
+ status: stage.error ? "error" : "ok",
115
+ duration_ms: stage.durationMs ?? 0,
116
+ output: []
117
+ });
118
+ else allSteps.push({
119
+ step: allSteps.length,
120
+ command: unit.name ?? "job",
121
+ status: jobResult.status === "ok" ? "ok" : "error",
122
+ duration_ms: 0
123
+ });
124
+ if (jobResult.status === "error" && jobResult.errors.length > 0) return {
125
+ status: "error",
126
+ steps: allSteps,
127
+ failedAt: fromJobError(jobResult.errors[0]),
128
+ duration_ms: Math.round(performance.now() - startTime)
129
+ };
130
+ } catch (err) {
131
+ allSteps.push({
132
+ step: allSteps.length,
133
+ command: unit.name ?? "job",
134
+ status: "error",
135
+ duration_ms: 0
136
+ });
137
+ return {
138
+ status: "error",
139
+ steps: allSteps,
140
+ failedAt: fromJobError(err.message ?? String(err)),
141
+ duration_ms: Math.round(performance.now() - startTime)
142
+ };
143
+ }
144
+ }
145
+ return {
146
+ status: "ok",
147
+ steps: allSteps,
148
+ output: [],
149
+ duration_ms: Math.round(performance.now() - startTime)
150
+ };
151
+ }
152
+
153
+ //#endregion
154
+ export { runStructured };
155
+ //# sourceMappingURL=structured-runner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-runner.mjs","names":[],"sources":["../../src/ai-dev-loop/structured-runner.ts"],"sourcesContent":["/**\n * Structured Runner — Wraps ASH compileSource() + execute() with step tracking.\n *\n * Produces AshRunResult from raw ASH execution.\n */\n\nimport { compileSource, type JobContext, type WorldInterface } from \"../compiler.js\";\nimport type { AshRunResult, AshStepResult } from \"./ash-run-result.js\";\nimport { fromJobError } from \"./ash-typed-error.js\";\n\n/**\n * Wraps a WorldInterface to intercept all writes in dry-run mode.\n * Reads pass through normally; write/publish are silently absorbed.\n */\nfunction createDryRunWorld(real: WorldInterface): WorldInterface {\n return {\n read: (path, query) => real.read(path, query),\n write: (_path, _data) => { /* no-op in dry-run */ },\n publish: (_topic, _data) => { /* no-op in dry-run */ },\n };\n}\n\n/**\n * Wraps a WorldInterface to check an AbortSignal before every operation.\n * Once aborted, all operations throw immediately — preventing side effects\n * from continuing after a timeout.\n */\nfunction createCancellableWorld(real: WorldInterface, signal: AbortSignal): WorldInterface {\n function checkAborted() {\n if (signal.aborted) throw new Error(\"Execution cancelled: timeout\");\n }\n return {\n read(path, query) {\n checkAborted();\n return real.read(path, query);\n },\n write(path, data) {\n checkAborted();\n real.write(path, data);\n },\n publish(topic, data) {\n checkAborted();\n real.publish(topic, data);\n },\n ...(real.exec ? {\n exec(path: string, input: unknown[], params?: Record<string, unknown>) {\n checkAborted();\n return real.exec!(path, input, params);\n },\n } : {}),\n ...(real.input ? {\n input(prompt: string) {\n checkAborted();\n return real.input!(prompt);\n },\n } : {}),\n };\n}\n\nexport interface RunOptions {\n mode?: \"dry-run\" | \"live\";\n timeout_ms?: number;\n}\n\nexport async function runStructured(\n source: string,\n ctx: JobContext,\n options?: RunOptions,\n): Promise<AshRunResult> {\n const startTime = performance.now();\n\n // Empty source → success with no steps\n if (!source.trim()) {\n return {\n status: \"ok\",\n steps: [],\n output: [],\n duration_ms: Math.round(performance.now() - startTime),\n };\n }\n\n // Compile\n const compileResult = compileSource(source);\n\n // Check for compile errors\n const errors = compileResult.diagnostics.filter((d) => d.severity !== \"warning\");\n if (errors.length > 0 || !compileResult.program) {\n const firstError = errors[0] ?? compileResult.diagnostics[0];\n return {\n status: \"error\",\n steps: [],\n failedAt: {\n kind: \"ParseError\",\n line: firstError?.line,\n message: firstError?.message ?? \"Compilation failed\",\n },\n duration_ms: Math.round(performance.now() - startTime),\n };\n }\n\n const program = compileResult.program;\n const allSteps: AshStepResult[] = [];\n\n // Apply dry-run world wrapper if in dry-run mode\n const mode = options?.mode ?? \"live\";\n let execCtx: JobContext = mode === \"dry-run\"\n ? { ...ctx, world: createDryRunWorld(ctx.world) }\n : ctx;\n\n // Wrap execution with timeout if specified\n const timeoutMs = options?.timeout_ms;\n if (timeoutMs != null && timeoutMs > 0) {\n const controller = new AbortController();\n // Wrap world with cancellation guard so operations throw after abort\n execCtx = { ...execCtx, world: createCancellableWorld(execCtx.world, controller.signal) };\n\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n return Promise.race([\n executeUnits(program, execCtx, allSteps, startTime),\n new Promise<AshRunResult>((_, reject) => {\n controller.signal.addEventListener(\"abort\", () =>\n reject(new Error(`Timeout: execution exceeded ${timeoutMs}ms`)),\n );\n }),\n ]).catch((err: any) => ({\n status: \"error\" as const,\n steps: allSteps,\n failedAt: fromJobError(err.message ?? String(err)),\n duration_ms: Math.round(performance.now() - startTime),\n })).finally(() => clearTimeout(timer));\n }\n\n return executeUnits(program, execCtx, allSteps, startTime);\n}\n\nasync function executeUnits(\n program: NonNullable<ReturnType<typeof compileSource>[\"program\"]>,\n execCtx: JobContext,\n allSteps: AshStepResult[],\n startTime: number,\n): Promise<AshRunResult> {\n // Execute all units (skip route-target-only jobs)\n for (const unit of program.units) {\n if (unit.kind === \"output\") {\n await unit.execute(execCtx);\n continue;\n }\n\n // Skip route-target-only jobs — they execute only when dispatched by route\n if (program.routeTargets?.has(unit.name)) continue;\n\n // Job execution\n try {\n const jobResult = await unit.execute(execCtx);\n\n // Extract step metrics from JobReport if available\n const report = jobResult as any;\n if (report.stages && Array.isArray(report.stages)) {\n for (const stage of report.stages) {\n allSteps.push({\n step: stage.index ?? allSteps.length,\n command: stage.name ?? \"unknown\",\n status: stage.error ? \"error\" : \"ok\",\n duration_ms: stage.durationMs ?? 0,\n output: [],\n });\n }\n } else {\n // Fallback: single step from job\n allSteps.push({\n step: allSteps.length,\n command: unit.name ?? \"job\",\n status: jobResult.status === \"ok\" ? \"ok\" : \"error\",\n duration_ms: 0,\n });\n }\n\n if (jobResult.status === \"error\" && jobResult.errors.length > 0) {\n return {\n status: \"error\",\n steps: allSteps,\n failedAt: fromJobError(jobResult.errors[0]),\n duration_ms: Math.round(performance.now() - startTime),\n };\n }\n } catch (err: any) {\n allSteps.push({\n step: allSteps.length,\n command: unit.name ?? \"job\",\n status: \"error\",\n duration_ms: 0,\n });\n\n return {\n status: \"error\",\n steps: allSteps,\n failedAt: fromJobError(err.message ?? String(err)),\n duration_ms: Math.round(performance.now() - startTime),\n };\n }\n }\n\n return {\n status: \"ok\",\n steps: allSteps,\n output: [],\n duration_ms: Math.round(performance.now() - startTime),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+
2
+ //#region src/ai-dev-loop/system-prompt.ts
3
+ /**
4
+ * Build the initial system prompt for the AI dev loop (INTENT §5.1).
5
+ */
6
+ function buildSystemPrompt(config) {
7
+ if (config.max_iterations < 1) throw new Error("max_iterations must be at least 1");
8
+ const plural = config.max_iterations === 1 ? "attempt" : "attempts";
9
+ return `You are an AOS agent. You operate inside AOS by writing and running ASH scripts.
10
+
11
+ Rules:
12
+ 1. Write ASH scripts to accomplish the user's intent.
13
+ 2. Use ash.validate before ash.run.
14
+ 3. If ash.run fails, read the structured error carefully.
15
+ 4. Fix only the failing step. Do not rewrite unrelated steps.
16
+ 5. You have at most ${config.max_iterations} ${plural}.
17
+
18
+ Available tools:
19
+ - ash.validate(script) → ParseError[]
20
+ - ash.run(script, mode="dry-run") → AshRunResult
21
+ - ash.explain_error(error) → explanation + suggestions
22
+
23
+ ASH quick reference:
24
+ - discover intent="..." → find tools
25
+ - pick [n] → select from results
26
+ - exec <tool> [args] → run tool (goes through Intent Gate)
27
+ - read/write/edit → AFS operations
28
+ - pipe with | → chain steps`;
29
+ }
30
+ /**
31
+ * Build the correction prompt for a failed iteration (INTENT §5.2).
32
+ *
33
+ * Only includes the error info and previous script — never leaks
34
+ * step output data to avoid world data exposure.
35
+ */
36
+ function buildCorrectionPrompt(failure, script) {
37
+ const err = failure.failedAt;
38
+ const failedStep = failure.steps.length > 0 ? failure.steps[failure.steps.length - 1] : void 0;
39
+ const lines = [
40
+ "The previous ASH script failed.",
41
+ "",
42
+ "Failure:",
43
+ `- Step: ${failedStep ? `${failedStep.step} (${failedStep.command})` : "unknown"}`,
44
+ `- Error: ${err.kind}`,
45
+ `- Detail: ${err.message}`
46
+ ];
47
+ const suggestion = err.suggestion;
48
+ if (suggestion) lines.push(`- Suggestion: ${suggestion}`);
49
+ lines.push("", "Previous script:", "---", script, "---", "", "Fix the script. Only change the failing step unless the fix requires structural changes.");
50
+ return lines.join("\n");
51
+ }
52
+
53
+ //#endregion
54
+ exports.buildCorrectionPrompt = buildCorrectionPrompt;
55
+ exports.buildSystemPrompt = buildSystemPrompt;
@@ -0,0 +1,20 @@
1
+ import { AshRunFailure } from "./ash-run-result.cjs";
2
+
3
+ //#region src/ai-dev-loop/system-prompt.d.ts
4
+ interface LoopConfig {
5
+ max_iterations: number;
6
+ }
7
+ /**
8
+ * Build the initial system prompt for the AI dev loop (INTENT §5.1).
9
+ */
10
+ declare function buildSystemPrompt(config: LoopConfig): string;
11
+ /**
12
+ * Build the correction prompt for a failed iteration (INTENT §5.2).
13
+ *
14
+ * Only includes the error info and previous script — never leaks
15
+ * step output data to avoid world data exposure.
16
+ */
17
+ declare function buildCorrectionPrompt(failure: AshRunFailure, script: string): string;
18
+ //#endregion
19
+ export { buildCorrectionPrompt, buildSystemPrompt };
20
+ //# sourceMappingURL=system-prompt.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.d.cts","names":[],"sources":["../../src/ai-dev-loop/system-prompt.ts"],"mappings":";;;UASiB,UAAA;EACf,cAAA;AAAA;;;;iBAMc,iBAAA,CAAkB,MAAA,EAAQ,UAAA;AAiC1C;;;;;;AAAA,iBAAgB,qBAAA,CAAsB,OAAA,EAAS,aAAA,EAAe,MAAA"}
@@ -0,0 +1,20 @@
1
+ import { AshRunFailure } from "./ash-run-result.mjs";
2
+
3
+ //#region src/ai-dev-loop/system-prompt.d.ts
4
+ interface LoopConfig {
5
+ max_iterations: number;
6
+ }
7
+ /**
8
+ * Build the initial system prompt for the AI dev loop (INTENT §5.1).
9
+ */
10
+ declare function buildSystemPrompt(config: LoopConfig): string;
11
+ /**
12
+ * Build the correction prompt for a failed iteration (INTENT §5.2).
13
+ *
14
+ * Only includes the error info and previous script — never leaks
15
+ * step output data to avoid world data exposure.
16
+ */
17
+ declare function buildCorrectionPrompt(failure: AshRunFailure, script: string): string;
18
+ //#endregion
19
+ export { buildCorrectionPrompt, buildSystemPrompt };
20
+ //# sourceMappingURL=system-prompt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.d.mts","names":[],"sources":["../../src/ai-dev-loop/system-prompt.ts"],"mappings":";;;UASiB,UAAA;EACf,cAAA;AAAA;;;;iBAMc,iBAAA,CAAkB,MAAA,EAAQ,UAAA;AAiC1C;;;;;;AAAA,iBAAgB,qBAAA,CAAsB,OAAA,EAAS,aAAA,EAAe,MAAA"}
@@ -0,0 +1,54 @@
1
+ //#region src/ai-dev-loop/system-prompt.ts
2
+ /**
3
+ * Build the initial system prompt for the AI dev loop (INTENT §5.1).
4
+ */
5
+ function buildSystemPrompt(config) {
6
+ if (config.max_iterations < 1) throw new Error("max_iterations must be at least 1");
7
+ const plural = config.max_iterations === 1 ? "attempt" : "attempts";
8
+ return `You are an AOS agent. You operate inside AOS by writing and running ASH scripts.
9
+
10
+ Rules:
11
+ 1. Write ASH scripts to accomplish the user's intent.
12
+ 2. Use ash.validate before ash.run.
13
+ 3. If ash.run fails, read the structured error carefully.
14
+ 4. Fix only the failing step. Do not rewrite unrelated steps.
15
+ 5. You have at most ${config.max_iterations} ${plural}.
16
+
17
+ Available tools:
18
+ - ash.validate(script) → ParseError[]
19
+ - ash.run(script, mode="dry-run") → AshRunResult
20
+ - ash.explain_error(error) → explanation + suggestions
21
+
22
+ ASH quick reference:
23
+ - discover intent="..." → find tools
24
+ - pick [n] → select from results
25
+ - exec <tool> [args] → run tool (goes through Intent Gate)
26
+ - read/write/edit → AFS operations
27
+ - pipe with | → chain steps`;
28
+ }
29
+ /**
30
+ * Build the correction prompt for a failed iteration (INTENT §5.2).
31
+ *
32
+ * Only includes the error info and previous script — never leaks
33
+ * step output data to avoid world data exposure.
34
+ */
35
+ function buildCorrectionPrompt(failure, script) {
36
+ const err = failure.failedAt;
37
+ const failedStep = failure.steps.length > 0 ? failure.steps[failure.steps.length - 1] : void 0;
38
+ const lines = [
39
+ "The previous ASH script failed.",
40
+ "",
41
+ "Failure:",
42
+ `- Step: ${failedStep ? `${failedStep.step} (${failedStep.command})` : "unknown"}`,
43
+ `- Error: ${err.kind}`,
44
+ `- Detail: ${err.message}`
45
+ ];
46
+ const suggestion = err.suggestion;
47
+ if (suggestion) lines.push(`- Suggestion: ${suggestion}`);
48
+ lines.push("", "Previous script:", "---", script, "---", "", "Fix the script. Only change the failing step unless the fix requires structural changes.");
49
+ return lines.join("\n");
50
+ }
51
+
52
+ //#endregion
53
+ export { buildCorrectionPrompt, buildSystemPrompt };
54
+ //# sourceMappingURL=system-prompt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.mjs","names":[],"sources":["../../src/ai-dev-loop/system-prompt.ts"],"sourcesContent":["/**\n * System Prompt Assembly for ASH AI Dev Loop.\n *\n * Implements the prompt contracts from INTENT §5.1 and §5.2.\n */\n\nimport type { AshRunFailure } from \"./ash-run-result.js\";\nimport type { AshTypedError } from \"./ash-typed-error.js\";\n\nexport interface LoopConfig {\n max_iterations: number;\n}\n\n/**\n * Build the initial system prompt for the AI dev loop (INTENT §5.1).\n */\nexport function buildSystemPrompt(config: LoopConfig): string {\n if (config.max_iterations < 1) {\n throw new Error(\"max_iterations must be at least 1\");\n }\n const plural = config.max_iterations === 1 ? \"attempt\" : \"attempts\";\n return `You are an AOS agent. You operate inside AOS by writing and running ASH scripts.\n\nRules:\n1. Write ASH scripts to accomplish the user's intent.\n2. Use ash.validate before ash.run.\n3. If ash.run fails, read the structured error carefully.\n4. Fix only the failing step. Do not rewrite unrelated steps.\n5. You have at most ${config.max_iterations} ${plural}.\n\nAvailable tools:\n- ash.validate(script) → ParseError[]\n- ash.run(script, mode=\"dry-run\") → AshRunResult\n- ash.explain_error(error) → explanation + suggestions\n\nASH quick reference:\n- discover intent=\"...\" → find tools\n- pick [n] → select from results\n- exec <tool> [args] → run tool (goes through Intent Gate)\n- read/write/edit → AFS operations\n- pipe with | → chain steps`;\n}\n\n/**\n * Build the correction prompt for a failed iteration (INTENT §5.2).\n *\n * Only includes the error info and previous script — never leaks\n * step output data to avoid world data exposure.\n */\nexport function buildCorrectionPrompt(failure: AshRunFailure, script: string): string {\n const err = failure.failedAt as AshTypedError;\n const failedStep = failure.steps.length > 0\n ? failure.steps[failure.steps.length - 1]\n : undefined;\n\n const lines = [\n \"The previous ASH script failed.\",\n \"\",\n \"Failure:\",\n `- Step: ${failedStep ? `${failedStep.step} (${failedStep.command})` : \"unknown\"}`,\n `- Error: ${err.kind}`,\n `- Detail: ${err.message}`,\n ];\n\n const suggestion = (err as any).suggestion;\n if (suggestion) {\n lines.push(`- Suggestion: ${suggestion}`);\n }\n\n lines.push(\n \"\",\n \"Previous script:\",\n \"---\",\n script,\n \"---\",\n \"\",\n \"Fix the script. Only change the failing step unless the fix requires structural changes.\",\n );\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;AAgBA,SAAgB,kBAAkB,QAA4B;AAC5D,KAAI,OAAO,iBAAiB,EAC1B,OAAM,IAAI,MAAM,oCAAoC;CAEtD,MAAM,SAAS,OAAO,mBAAmB,IAAI,YAAY;AACzD,QAAO;;;;;;;sBAOa,OAAO,eAAe,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;AAqBtD,SAAgB,sBAAsB,SAAwB,QAAwB;CACpF,MAAM,MAAM,QAAQ;CACpB,MAAM,aAAa,QAAQ,MAAM,SAAS,IACtC,QAAQ,MAAM,QAAQ,MAAM,SAAS,KACrC;CAEJ,MAAM,QAAQ;EACZ;EACA;EACA;EACA,WAAW,aAAa,GAAG,WAAW,KAAK,IAAI,WAAW,QAAQ,KAAK;EACvE,YAAY,IAAI;EAChB,aAAa,IAAI;EAClB;CAED,MAAM,aAAc,IAAY;AAChC,KAAI,WACF,OAAM,KAAK,iBAAiB,aAAa;AAG3C,OAAM,KACJ,IACA,oBACA,OACA,QACA,OACA,IACA,2FACD;AAED,QAAO,MAAM,KAAK,KAAK"}
package/dist/ast.d.cts ADDED
@@ -0,0 +1,140 @@
1
+ //#region src/ast.d.ts
2
+ interface Annotation {
3
+ name: string;
4
+ args: string[];
5
+ line: number;
6
+ column: number;
7
+ }
8
+ interface QueryCondition {
9
+ field: string;
10
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=";
11
+ value: string | number;
12
+ }
13
+ interface FindExpression {
14
+ kind: "find";
15
+ path: string;
16
+ query?: QueryCondition;
17
+ }
18
+ interface WhereClause {
19
+ kind: "where";
20
+ left: string;
21
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=";
22
+ right: string | number;
23
+ }
24
+ interface BinaryExpression {
25
+ kind: "binary";
26
+ op: "+" | "-" | "*" | "/";
27
+ left: Expression;
28
+ right: Expression;
29
+ }
30
+ interface FieldAccessExpression {
31
+ kind: "field_access";
32
+ path: string;
33
+ }
34
+ interface LiteralExpression {
35
+ kind: "literal";
36
+ value: string | number;
37
+ }
38
+ interface VarRefExpression {
39
+ kind: "var_ref";
40
+ name: string;
41
+ }
42
+ type Expression = BinaryExpression | FieldAccessExpression | LiteralExpression | VarRefExpression;
43
+ interface MapExpression {
44
+ kind: "map";
45
+ field: string;
46
+ mappings?: Record<string, string>;
47
+ expression?: Expression;
48
+ exprMappings?: Record<string, Expression>;
49
+ }
50
+ interface SaveExpression {
51
+ kind: "save";
52
+ path: string;
53
+ }
54
+ interface PublishExpression {
55
+ kind: "publish";
56
+ path: string;
57
+ }
58
+ interface TeeExpression {
59
+ kind: "tee";
60
+ path: string;
61
+ }
62
+ interface FanoutExpression {
63
+ kind: "fanout";
64
+ branches: PipelineStage[][];
65
+ }
66
+ interface OutputExpression {
67
+ kind: "output";
68
+ message: string;
69
+ expression?: Expression;
70
+ }
71
+ interface InputExpression {
72
+ kind: "input";
73
+ prompt: string;
74
+ }
75
+ interface CountExpression {
76
+ kind: "count";
77
+ }
78
+ interface GroupByExpression {
79
+ kind: "group-by";
80
+ field: string;
81
+ }
82
+ interface ActionExpression {
83
+ kind: "action";
84
+ path: string;
85
+ relative?: boolean;
86
+ params?: Record<string, unknown>;
87
+ }
88
+ interface RouteBranch {
89
+ value: string;
90
+ targetJob: string;
91
+ }
92
+ interface RouteExpression {
93
+ kind: "route";
94
+ field: string;
95
+ branches: RouteBranch[];
96
+ fallback?: string;
97
+ }
98
+ interface LookupExpression {
99
+ kind: "lookup";
100
+ path: string;
101
+ joinKey: string;
102
+ }
103
+ type PipelineStage = FindExpression | WhereClause | MapExpression | SaveExpression | PublishExpression | TeeExpression | FanoutExpression | OutputExpression | InputExpression | CountExpression | GroupByExpression | ActionExpression | RouteExpression | LookupExpression;
104
+ interface EventTrigger {
105
+ kind: "event";
106
+ path: string;
107
+ event: string;
108
+ }
109
+ interface CronTrigger {
110
+ kind: "cron";
111
+ expression: string;
112
+ }
113
+ type TriggerDeclaration = EventTrigger | CronTrigger;
114
+ interface JobDeclaration {
115
+ kind: "job";
116
+ name: string;
117
+ annotations: Annotation[];
118
+ pipeline: PipelineStage[];
119
+ trigger?: TriggerDeclaration;
120
+ }
121
+ interface LetStatement {
122
+ kind: "let";
123
+ name: string;
124
+ value: string | number;
125
+ pipeline?: PipelineStage[];
126
+ }
127
+ interface ParamDeclaration {
128
+ kind: "param";
129
+ name: string;
130
+ defaultValue: string | number;
131
+ }
132
+ type TopLevelStatement = JobDeclaration | OutputExpression | LetStatement | ParamDeclaration;
133
+ interface Program {
134
+ statements: TopLevelStatement[];
135
+ /** Backward-compatible accessor: returns only job declarations */
136
+ jobs: JobDeclaration[];
137
+ }
138
+ //#endregion
139
+ export { ActionExpression, BinaryExpression, CountExpression, CronTrigger, EventTrigger, Expression, FieldAccessExpression, FindExpression, GroupByExpression, InputExpression, JobDeclaration, LetStatement, LiteralExpression, LookupExpression, MapExpression, ParamDeclaration, PipelineStage, Program, QueryCondition, RouteBranch, RouteExpression, TopLevelStatement, TriggerDeclaration, VarRefExpression };
140
+ //# sourceMappingURL=ast.d.cts.map