@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.
- package/DESIGN.md +41 -0
- package/dist/ai-dev-loop/ash-run-result.cjs +12 -0
- package/dist/ai-dev-loop/ash-run-result.d.cts +28 -0
- package/dist/ai-dev-loop/ash-run-result.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-run-result.d.mts +28 -0
- package/dist/ai-dev-loop/ash-run-result.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-run-result.mjs +11 -0
- package/dist/ai-dev-loop/ash-run-result.mjs.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.cjs +51 -0
- package/dist/ai-dev-loop/ash-typed-error.d.cts +54 -0
- package/dist/ai-dev-loop/ash-typed-error.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.d.mts +54 -0
- package/dist/ai-dev-loop/ash-typed-error.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.mjs +50 -0
- package/dist/ai-dev-loop/ash-typed-error.mjs.map +1 -0
- package/dist/ai-dev-loop/ash-validate.cjs +27 -0
- package/dist/ai-dev-loop/ash-validate.d.cts +7 -0
- package/dist/ai-dev-loop/ash-validate.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-validate.d.mts +7 -0
- package/dist/ai-dev-loop/ash-validate.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-validate.mjs +28 -0
- package/dist/ai-dev-loop/ash-validate.mjs.map +1 -0
- package/dist/ai-dev-loop/dev-loop.cjs +134 -0
- package/dist/ai-dev-loop/dev-loop.d.cts +28 -0
- package/dist/ai-dev-loop/dev-loop.d.cts.map +1 -0
- package/dist/ai-dev-loop/dev-loop.d.mts +28 -0
- package/dist/ai-dev-loop/dev-loop.d.mts.map +1 -0
- package/dist/ai-dev-loop/dev-loop.mjs +135 -0
- package/dist/ai-dev-loop/dev-loop.mjs.map +1 -0
- package/dist/ai-dev-loop/index.cjs +24 -0
- package/dist/ai-dev-loop/index.d.cts +9 -0
- package/dist/ai-dev-loop/index.d.mts +9 -0
- package/dist/ai-dev-loop/index.mjs +10 -0
- package/dist/ai-dev-loop/live-mode.cjs +17 -0
- package/dist/ai-dev-loop/live-mode.d.cts +24 -0
- package/dist/ai-dev-loop/live-mode.d.cts.map +1 -0
- package/dist/ai-dev-loop/live-mode.d.mts +24 -0
- package/dist/ai-dev-loop/live-mode.d.mts.map +1 -0
- package/dist/ai-dev-loop/live-mode.mjs +17 -0
- package/dist/ai-dev-loop/live-mode.mjs.map +1 -0
- package/dist/ai-dev-loop/meta-tools.cjs +123 -0
- package/dist/ai-dev-loop/meta-tools.d.cts +24 -0
- package/dist/ai-dev-loop/meta-tools.d.cts.map +1 -0
- package/dist/ai-dev-loop/meta-tools.d.mts +24 -0
- package/dist/ai-dev-loop/meta-tools.d.mts.map +1 -0
- package/dist/ai-dev-loop/meta-tools.mjs +120 -0
- package/dist/ai-dev-loop/meta-tools.mjs.map +1 -0
- package/dist/ai-dev-loop/structured-runner.cjs +154 -0
- package/dist/ai-dev-loop/structured-runner.d.cts +12 -0
- package/dist/ai-dev-loop/structured-runner.d.cts.map +1 -0
- package/dist/ai-dev-loop/structured-runner.d.mts +12 -0
- package/dist/ai-dev-loop/structured-runner.d.mts.map +1 -0
- package/dist/ai-dev-loop/structured-runner.mjs +155 -0
- package/dist/ai-dev-loop/structured-runner.mjs.map +1 -0
- package/dist/ai-dev-loop/system-prompt.cjs +55 -0
- package/dist/ai-dev-loop/system-prompt.d.cts +20 -0
- package/dist/ai-dev-loop/system-prompt.d.cts.map +1 -0
- package/dist/ai-dev-loop/system-prompt.d.mts +20 -0
- package/dist/ai-dev-loop/system-prompt.d.mts.map +1 -0
- package/dist/ai-dev-loop/system-prompt.mjs +54 -0
- package/dist/ai-dev-loop/system-prompt.mjs.map +1 -0
- package/dist/ast.d.cts +140 -0
- package/dist/ast.d.cts.map +1 -0
- package/dist/ast.d.mts +140 -0
- package/dist/ast.d.mts.map +1 -0
- package/dist/compiler.cjs +802 -0
- package/dist/compiler.d.cts +103 -0
- package/dist/compiler.d.cts.map +1 -0
- package/dist/compiler.d.mts +103 -0
- package/dist/compiler.d.mts.map +1 -0
- package/dist/compiler.mjs +802 -0
- package/dist/compiler.mjs.map +1 -0
- package/dist/index.cjs +14 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +7 -0
- package/dist/lexer.cjs +451 -0
- package/dist/lexer.d.cts +14 -0
- package/dist/lexer.d.cts.map +1 -0
- package/dist/lexer.d.mts +14 -0
- package/dist/lexer.d.mts.map +1 -0
- package/dist/lexer.mjs +451 -0
- package/dist/lexer.mjs.map +1 -0
- package/dist/parser.cjs +734 -0
- package/dist/parser.d.cts +40 -0
- package/dist/parser.d.cts.map +1 -0
- package/dist/parser.d.mts +40 -0
- package/dist/parser.d.mts.map +1 -0
- package/dist/parser.mjs +734 -0
- package/dist/parser.mjs.map +1 -0
- package/dist/reference.cjs +130 -0
- package/dist/reference.d.cts +11 -0
- package/dist/reference.d.cts.map +1 -0
- package/dist/reference.d.mts +11 -0
- package/dist/reference.d.mts.map +1 -0
- package/dist/reference.mjs +130 -0
- package/dist/reference.mjs.map +1 -0
- package/dist/template.cjs +85 -0
- package/dist/template.mjs +84 -0
- package/dist/template.mjs.map +1 -0
- package/dist/type-checker.cjs +582 -0
- package/dist/type-checker.d.cts +31 -0
- package/dist/type-checker.d.cts.map +1 -0
- package/dist/type-checker.d.mts +31 -0
- package/dist/type-checker.d.mts.map +1 -0
- package/dist/type-checker.mjs +573 -0
- package/dist/type-checker.mjs.map +1 -0
- package/package.json +29 -0
- package/src/ai-dev-loop/ash-run-result.test.ts +113 -0
- package/src/ai-dev-loop/ash-run-result.ts +46 -0
- package/src/ai-dev-loop/ash-typed-error.test.ts +136 -0
- package/src/ai-dev-loop/ash-typed-error.ts +50 -0
- package/src/ai-dev-loop/ash-validate.test.ts +54 -0
- package/src/ai-dev-loop/ash-validate.ts +34 -0
- package/src/ai-dev-loop/dev-loop.test.ts +364 -0
- package/src/ai-dev-loop/dev-loop.ts +156 -0
- package/src/ai-dev-loop/dry-run.test.ts +107 -0
- package/src/ai-dev-loop/e2e-multi-fix.test.ts +473 -0
- package/src/ai-dev-loop/e2e.test.ts +324 -0
- package/src/ai-dev-loop/index.ts +15 -0
- package/src/ai-dev-loop/invariants.test.ts +253 -0
- package/src/ai-dev-loop/live-mode.test.ts +63 -0
- package/src/ai-dev-loop/live-mode.ts +33 -0
- package/src/ai-dev-loop/meta-tools.test.ts +120 -0
- package/src/ai-dev-loop/meta-tools.ts +142 -0
- package/src/ai-dev-loop/structured-runner.test.ts +159 -0
- package/src/ai-dev-loop/structured-runner.ts +209 -0
- package/src/ai-dev-loop/system-prompt.test.ts +102 -0
- package/src/ai-dev-loop/system-prompt.ts +81 -0
- package/src/ast.ts +186 -0
- package/src/compiler.test.ts +2933 -0
- package/src/compiler.ts +1103 -0
- package/src/e2e.test.ts +552 -0
- package/src/index.ts +16 -0
- package/src/lexer.test.ts +538 -0
- package/src/lexer.ts +222 -0
- package/src/parser.test.ts +1024 -0
- package/src/parser.ts +835 -0
- package/src/reference.test.ts +166 -0
- package/src/reference.ts +125 -0
- package/src/template.test.ts +210 -0
- package/src/template.ts +139 -0
- package/src/type-checker.test.ts +1494 -0
- package/src/type-checker.ts +785 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +12 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildSystemPrompt, buildCorrectionPrompt } from "./system-prompt.js";
|
|
3
|
+
import type { AshRunFailure } from "./ash-run-result.js";
|
|
4
|
+
|
|
5
|
+
describe("System Prompt Assembly", () => {
|
|
6
|
+
// ── buildSystemPrompt ──────────────────────────────────
|
|
7
|
+
|
|
8
|
+
it("contains rules, tools, and ASH reference", () => {
|
|
9
|
+
const prompt = buildSystemPrompt({ max_iterations: 3 });
|
|
10
|
+
expect(prompt).toContain("You are an AOS agent");
|
|
11
|
+
expect(prompt).toContain("ash.validate");
|
|
12
|
+
expect(prompt).toContain("ash.run");
|
|
13
|
+
expect(prompt).toContain("ash.explain_error");
|
|
14
|
+
expect(prompt).toContain("ASH quick reference");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("shows max_iterations count", () => {
|
|
18
|
+
const prompt = buildSystemPrompt({ max_iterations: 3 });
|
|
19
|
+
expect(prompt).toContain("3 attempts");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("singular attempt for max_iterations=1", () => {
|
|
23
|
+
const prompt = buildSystemPrompt({ max_iterations: 1 });
|
|
24
|
+
expect(prompt).toContain("1 attempt");
|
|
25
|
+
expect(prompt).not.toContain("1 attempts");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("rejects max_iterations=0", () => {
|
|
29
|
+
expect(() => buildSystemPrompt({ max_iterations: 0 })).toThrow();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("does not contain API keys or internal paths", () => {
|
|
33
|
+
const prompt = buildSystemPrompt({ max_iterations: 5 });
|
|
34
|
+
expect(prompt).not.toMatch(/api[_-]?key/i);
|
|
35
|
+
expect(prompt).not.toMatch(/\/Users\//);
|
|
36
|
+
expect(prompt).not.toMatch(/\/home\//);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ── buildCorrectionPrompt ──────────────────────────────
|
|
40
|
+
|
|
41
|
+
it("contains step, error kind, detail, and suggestion", () => {
|
|
42
|
+
const failure: AshRunFailure = {
|
|
43
|
+
status: "error",
|
|
44
|
+
steps: [{ step: 1, command: "find", status: "ok", duration_ms: 10, output: [] }],
|
|
45
|
+
failedAt: { kind: "ToolNotFound", name: "foo", available: ["find", "where"], message: "not found" },
|
|
46
|
+
duration_ms: 20,
|
|
47
|
+
};
|
|
48
|
+
const prompt = buildCorrectionPrompt(failure, 'job "test" { find /users }');
|
|
49
|
+
expect(prompt).toContain("ToolNotFound");
|
|
50
|
+
expect(prompt).toContain("not found");
|
|
51
|
+
expect(prompt).toContain('job "test" { find /users }');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("includes previous script", () => {
|
|
55
|
+
const failure: AshRunFailure = {
|
|
56
|
+
status: "error",
|
|
57
|
+
steps: [],
|
|
58
|
+
failedAt: { kind: "ParseError", message: "unexpected token", line: 3 },
|
|
59
|
+
duration_ms: 5,
|
|
60
|
+
};
|
|
61
|
+
const script = 'job "broken" {\n find /x\n ???\n}';
|
|
62
|
+
const prompt = buildCorrectionPrompt(failure, script);
|
|
63
|
+
expect(prompt).toContain(script);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("omits suggestion line when error has no suggestion", () => {
|
|
67
|
+
const failure: AshRunFailure = {
|
|
68
|
+
status: "error",
|
|
69
|
+
steps: [],
|
|
70
|
+
failedAt: { kind: "RuntimeError", message: "boom" },
|
|
71
|
+
duration_ms: 1,
|
|
72
|
+
};
|
|
73
|
+
const prompt = buildCorrectionPrompt(failure, "output hello");
|
|
74
|
+
expect(prompt).toContain("RuntimeError");
|
|
75
|
+
expect(prompt).not.toMatch(/Suggestion:.*undefined/);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("does not truncate very long script", () => {
|
|
79
|
+
const failure: AshRunFailure = {
|
|
80
|
+
status: "error",
|
|
81
|
+
steps: [],
|
|
82
|
+
failedAt: { kind: "Timeout", step: "find", limit_ms: 1000, message: "timeout" },
|
|
83
|
+
duration_ms: 1000,
|
|
84
|
+
};
|
|
85
|
+
const longScript = "find /users\n".repeat(1000);
|
|
86
|
+
const prompt = buildCorrectionPrompt(failure, longScript);
|
|
87
|
+
expect(prompt).toContain(longScript);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("does not leak world data beyond the failing step", () => {
|
|
91
|
+
const failure: AshRunFailure = {
|
|
92
|
+
status: "error",
|
|
93
|
+
steps: [
|
|
94
|
+
{ step: 1, command: "find", status: "ok", duration_ms: 10, output: [{ secret: "password123" }] },
|
|
95
|
+
],
|
|
96
|
+
failedAt: { kind: "RuntimeError", message: "step 2 failed" },
|
|
97
|
+
duration_ms: 20,
|
|
98
|
+
};
|
|
99
|
+
const prompt = buildCorrectionPrompt(failure, "find /users | save /out");
|
|
100
|
+
expect(prompt).not.toContain("password123");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System Prompt Assembly for ASH AI Dev Loop.
|
|
3
|
+
*
|
|
4
|
+
* Implements the prompt contracts from INTENT §5.1 and §5.2.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { AshRunFailure } from "./ash-run-result.js";
|
|
8
|
+
import type { AshTypedError } from "./ash-typed-error.js";
|
|
9
|
+
|
|
10
|
+
export interface LoopConfig {
|
|
11
|
+
max_iterations: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Build the initial system prompt for the AI dev loop (INTENT §5.1).
|
|
16
|
+
*/
|
|
17
|
+
export function buildSystemPrompt(config: LoopConfig): string {
|
|
18
|
+
if (config.max_iterations < 1) {
|
|
19
|
+
throw new Error("max_iterations must be at least 1");
|
|
20
|
+
}
|
|
21
|
+
const plural = config.max_iterations === 1 ? "attempt" : "attempts";
|
|
22
|
+
return `You are an AOS agent. You operate inside AOS by writing and running ASH scripts.
|
|
23
|
+
|
|
24
|
+
Rules:
|
|
25
|
+
1. Write ASH scripts to accomplish the user's intent.
|
|
26
|
+
2. Use ash.validate before ash.run.
|
|
27
|
+
3. If ash.run fails, read the structured error carefully.
|
|
28
|
+
4. Fix only the failing step. Do not rewrite unrelated steps.
|
|
29
|
+
5. You have at most ${config.max_iterations} ${plural}.
|
|
30
|
+
|
|
31
|
+
Available tools:
|
|
32
|
+
- ash.validate(script) → ParseError[]
|
|
33
|
+
- ash.run(script, mode="dry-run") → AshRunResult
|
|
34
|
+
- ash.explain_error(error) → explanation + suggestions
|
|
35
|
+
|
|
36
|
+
ASH quick reference:
|
|
37
|
+
- discover intent="..." → find tools
|
|
38
|
+
- pick [n] → select from results
|
|
39
|
+
- exec <tool> [args] → run tool (goes through Intent Gate)
|
|
40
|
+
- read/write/edit → AFS operations
|
|
41
|
+
- pipe with | → chain steps`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build the correction prompt for a failed iteration (INTENT §5.2).
|
|
46
|
+
*
|
|
47
|
+
* Only includes the error info and previous script — never leaks
|
|
48
|
+
* step output data to avoid world data exposure.
|
|
49
|
+
*/
|
|
50
|
+
export function buildCorrectionPrompt(failure: AshRunFailure, script: string): string {
|
|
51
|
+
const err = failure.failedAt as AshTypedError;
|
|
52
|
+
const failedStep = failure.steps.length > 0
|
|
53
|
+
? failure.steps[failure.steps.length - 1]
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
const lines = [
|
|
57
|
+
"The previous ASH script failed.",
|
|
58
|
+
"",
|
|
59
|
+
"Failure:",
|
|
60
|
+
`- Step: ${failedStep ? `${failedStep.step} (${failedStep.command})` : "unknown"}`,
|
|
61
|
+
`- Error: ${err.kind}`,
|
|
62
|
+
`- Detail: ${err.message}`,
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const suggestion = (err as any).suggestion;
|
|
66
|
+
if (suggestion) {
|
|
67
|
+
lines.push(`- Suggestion: ${suggestion}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
lines.push(
|
|
71
|
+
"",
|
|
72
|
+
"Previous script:",
|
|
73
|
+
"---",
|
|
74
|
+
script,
|
|
75
|
+
"---",
|
|
76
|
+
"",
|
|
77
|
+
"Fix the script. Only change the failing step unless the fix requires structural changes.",
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return lines.join("\n");
|
|
81
|
+
}
|
package/src/ast.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
export interface Annotation {
|
|
2
|
+
name: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
line: number;
|
|
5
|
+
column: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface QueryCondition {
|
|
9
|
+
field: string;
|
|
10
|
+
op: "==" | "!=" | ">" | "<" | ">=" | "<=";
|
|
11
|
+
value: string | number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface FindExpression {
|
|
15
|
+
kind: "find";
|
|
16
|
+
path: string;
|
|
17
|
+
query?: QueryCondition;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface WhereClause {
|
|
21
|
+
kind: "where";
|
|
22
|
+
left: string;
|
|
23
|
+
op: "==" | "!=" | ">" | "<" | ">=" | "<=";
|
|
24
|
+
right: string | number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ── Expression types (v3.1: restricted expression system) ──
|
|
28
|
+
|
|
29
|
+
export interface BinaryExpression {
|
|
30
|
+
kind: "binary";
|
|
31
|
+
op: "+" | "-" | "*" | "/";
|
|
32
|
+
left: Expression;
|
|
33
|
+
right: Expression;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface FieldAccessExpression {
|
|
37
|
+
kind: "field_access";
|
|
38
|
+
path: string; // dot-separated, e.g. "user.name"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface LiteralExpression {
|
|
42
|
+
kind: "literal";
|
|
43
|
+
value: string | number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface VarRefExpression {
|
|
47
|
+
kind: "var_ref";
|
|
48
|
+
name: string; // without $
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type Expression =
|
|
52
|
+
| BinaryExpression
|
|
53
|
+
| FieldAccessExpression
|
|
54
|
+
| LiteralExpression
|
|
55
|
+
| VarRefExpression;
|
|
56
|
+
|
|
57
|
+
export interface MapExpression {
|
|
58
|
+
kind: "map";
|
|
59
|
+
field: string; // dot-separated, e.g. "user.name" (single-field mode)
|
|
60
|
+
mappings?: Record<string, string>; // { outputKey: inputField } (object mapping mode, no colon)
|
|
61
|
+
expression?: Expression; // single-expression mode: map name + " " + surname
|
|
62
|
+
exprMappings?: Record<string, Expression>; // expression object mode: map { key: expr, ... }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface SaveExpression {
|
|
66
|
+
kind: "save";
|
|
67
|
+
path: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface PublishExpression {
|
|
71
|
+
kind: "publish";
|
|
72
|
+
path: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface TeeExpression {
|
|
76
|
+
kind: "tee";
|
|
77
|
+
path: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface FanoutExpression {
|
|
81
|
+
kind: "fanout";
|
|
82
|
+
branches: PipelineStage[][];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface OutputExpression {
|
|
86
|
+
kind: "output";
|
|
87
|
+
message: string;
|
|
88
|
+
expression?: Expression;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface InputExpression {
|
|
92
|
+
kind: "input";
|
|
93
|
+
prompt: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface CountExpression {
|
|
97
|
+
kind: "count";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface GroupByExpression {
|
|
101
|
+
kind: "group-by";
|
|
102
|
+
field: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface ActionExpression {
|
|
106
|
+
kind: "action";
|
|
107
|
+
path: string;
|
|
108
|
+
relative?: boolean;
|
|
109
|
+
params?: Record<string, unknown>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface RouteBranch {
|
|
113
|
+
value: string; // match value, or "_" for fallback
|
|
114
|
+
targetJob: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface RouteExpression {
|
|
118
|
+
kind: "route";
|
|
119
|
+
field: string;
|
|
120
|
+
branches: RouteBranch[];
|
|
121
|
+
fallback?: string; // fallback job name (from `_ -> job name`)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface LookupExpression {
|
|
125
|
+
kind: "lookup";
|
|
126
|
+
path: string;
|
|
127
|
+
joinKey: string; // field to join on
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export type PipelineStage =
|
|
131
|
+
| FindExpression
|
|
132
|
+
| WhereClause
|
|
133
|
+
| MapExpression
|
|
134
|
+
| SaveExpression
|
|
135
|
+
| PublishExpression
|
|
136
|
+
| TeeExpression
|
|
137
|
+
| FanoutExpression
|
|
138
|
+
| OutputExpression
|
|
139
|
+
| InputExpression
|
|
140
|
+
| CountExpression
|
|
141
|
+
| GroupByExpression
|
|
142
|
+
| ActionExpression
|
|
143
|
+
| RouteExpression
|
|
144
|
+
| LookupExpression;
|
|
145
|
+
|
|
146
|
+
export interface EventTrigger {
|
|
147
|
+
kind: "event";
|
|
148
|
+
path: string;
|
|
149
|
+
event: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface CronTrigger {
|
|
153
|
+
kind: "cron";
|
|
154
|
+
expression: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export type TriggerDeclaration = EventTrigger | CronTrigger;
|
|
158
|
+
|
|
159
|
+
export interface JobDeclaration {
|
|
160
|
+
kind: "job";
|
|
161
|
+
name: string;
|
|
162
|
+
annotations: Annotation[];
|
|
163
|
+
pipeline: PipelineStage[];
|
|
164
|
+
trigger?: TriggerDeclaration;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface LetStatement {
|
|
168
|
+
kind: "let";
|
|
169
|
+
name: string;
|
|
170
|
+
value: string | number;
|
|
171
|
+
pipeline?: PipelineStage[]; // runtime let: let x = find /data | count
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface ParamDeclaration {
|
|
175
|
+
kind: "param";
|
|
176
|
+
name: string;
|
|
177
|
+
defaultValue: string | number;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type TopLevelStatement = JobDeclaration | OutputExpression | LetStatement | ParamDeclaration;
|
|
181
|
+
|
|
182
|
+
export interface Program {
|
|
183
|
+
statements: TopLevelStatement[];
|
|
184
|
+
/** Backward-compatible accessor: returns only job declarations */
|
|
185
|
+
jobs: JobDeclaration[];
|
|
186
|
+
}
|