toad-compiler 0.1.0
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/LICENSE +21 -0
- package/dist/analyze.d.ts +13 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +20 -0
- package/dist/analyze.js.map +1 -0
- package/dist/analyze.test.d.ts +2 -0
- package/dist/analyze.test.d.ts.map +1 -0
- package/dist/analyze.test.js +45 -0
- package/dist/analyze.test.js.map +1 -0
- package/dist/ast.d.ts +63 -0
- package/dist/ast.d.ts.map +1 -0
- package/dist/ast.js +6 -0
- package/dist/ast.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +7 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +2 -0
- package/dist/cli.test.d.ts.map +1 -0
- package/dist/cli.test.js +54 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/codegen.d.ts +9 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +152 -0
- package/dist/codegen.js.map +1 -0
- package/dist/codegen.test.d.ts +2 -0
- package/dist/codegen.test.d.ts.map +1 -0
- package/dist/codegen.test.js +76 -0
- package/dist/codegen.test.js.map +1 -0
- package/dist/controlflow.test.d.ts +2 -0
- package/dist/controlflow.test.d.ts.map +1 -0
- package/dist/controlflow.test.js +75 -0
- package/dist/controlflow.test.js.map +1 -0
- package/dist/diagnostics.d.ts +24 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +26 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/each.test.d.ts +2 -0
- package/dist/each.test.d.ts.map +1 -0
- package/dist/each.test.js +82 -0
- package/dist/each.test.js.map +1 -0
- package/dist/env.test.d.ts +2 -0
- package/dist/env.test.d.ts.map +1 -0
- package/dist/env.test.js +27 -0
- package/dist/env.test.js.map +1 -0
- package/dist/example.test.d.ts +2 -0
- package/dist/example.test.d.ts.map +1 -0
- package/dist/example.test.js +19 -0
- package/dist/example.test.js.map +1 -0
- package/dist/if.test.d.ts +2 -0
- package/dist/if.test.d.ts.map +1 -0
- package/dist/if.test.js +72 -0
- package/dist/if.test.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +19 -0
- package/dist/index.test.js.map +1 -0
- package/dist/interpolate.d.ts +18 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +237 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/interpolate.test.d.ts +2 -0
- package/dist/interpolate.test.d.ts.map +1 -0
- package/dist/interpolate.test.js +35 -0
- package/dist/interpolate.test.js.map +1 -0
- package/dist/lifecycle.test.d.ts +2 -0
- package/dist/lifecycle.test.d.ts.map +1 -0
- package/dist/lifecycle.test.js +26 -0
- package/dist/lifecycle.test.js.map +1 -0
- package/dist/objecttypes.test.d.ts +2 -0
- package/dist/objecttypes.test.d.ts.map +1 -0
- package/dist/objecttypes.test.js +83 -0
- package/dist/objecttypes.test.js.map +1 -0
- package/dist/preprocess.d.ts +20 -0
- package/dist/preprocess.d.ts.map +1 -0
- package/dist/preprocess.js +98 -0
- package/dist/preprocess.js.map +1 -0
- package/dist/preprocess.test.d.ts +2 -0
- package/dist/preprocess.test.d.ts.map +1 -0
- package/dist/preprocess.test.js +58 -0
- package/dist/preprocess.test.js.map +1 -0
- package/dist/system.test.d.ts +2 -0
- package/dist/system.test.d.ts.map +1 -0
- package/dist/system.test.js +35 -0
- package/dist/system.test.js.map +1 -0
- package/dist/toon.d.ts +16 -0
- package/dist/toon.d.ts.map +1 -0
- package/dist/toon.js +32 -0
- package/dist/toon.js.map +1 -0
- package/dist/toon.test.d.ts +2 -0
- package/dist/toon.test.d.ts.map +1 -0
- package/dist/toon.test.js +50 -0
- package/dist/toon.test.js.map +1 -0
- package/dist/uses.test.d.ts +2 -0
- package/dist/uses.test.d.ts.map +1 -0
- package/dist/uses.test.js +32 -0
- package/dist/uses.test.js.map +1 -0
- package/dist/validate.d.ts +14 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +351 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +64 -0
- package/dist/validate.test.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { analyze } from "./analyze.js";
|
|
3
|
+
import { generate } from "./codegen.js";
|
|
4
|
+
const SOURCE = [
|
|
5
|
+
"agent: researcher",
|
|
6
|
+
"model: claude-opus-4-7",
|
|
7
|
+
"description: Research a topic and return a sourced summary.",
|
|
8
|
+
"inputs[1]{name,type}:",
|
|
9
|
+
" topic,string",
|
|
10
|
+
"tools[2]: web_search,fetch_page",
|
|
11
|
+
"prompt: |",
|
|
12
|
+
" You are a research analyst. Research: {inputs.topic}",
|
|
13
|
+
" Use web_search to find sources, then fetch_page to read them.",
|
|
14
|
+
" Return a cited summary.",
|
|
15
|
+
"outputs[2]{name,type}:",
|
|
16
|
+
" summary,string",
|
|
17
|
+
" sources,string[]",
|
|
18
|
+
].join("\n");
|
|
19
|
+
// The canonical contract from _bmad-output/architecture.md §5.
|
|
20
|
+
const EXPECTED = `// Generated by toac from researcher.agent — do not edit.
|
|
21
|
+
import { createAgent, type Agent } from "toad-runtime";
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
import { web_search, fetch_page } from "./researcher.tools";
|
|
24
|
+
|
|
25
|
+
export interface ResearcherInput {
|
|
26
|
+
topic: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ResearcherOutput {
|
|
30
|
+
summary: string;
|
|
31
|
+
sources: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const inputSchema = z.object({
|
|
35
|
+
topic: z.string(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const outputSchema = z.object({
|
|
39
|
+
summary: z.string(),
|
|
40
|
+
sources: z.array(z.string()),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const researcher: Agent<ResearcherInput, ResearcherOutput> = createAgent({
|
|
44
|
+
name: "researcher",
|
|
45
|
+
model: "claude-opus-4-7",
|
|
46
|
+
description: "Research a topic and return a sourced summary.",
|
|
47
|
+
tools: { web_search, fetch_page },
|
|
48
|
+
inputSchema,
|
|
49
|
+
outputSchema,
|
|
50
|
+
prompt: (inputs: ResearcherInput) =>
|
|
51
|
+
\`You are a research analyst. Research: \${inputs.topic}
|
|
52
|
+
Use web_search to find sources, then fetch_page to read them.
|
|
53
|
+
Return a cited summary.\`,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default researcher;
|
|
57
|
+
`;
|
|
58
|
+
describe("generate — codegen contract", () => {
|
|
59
|
+
it("emits the researcher.ts contract (architecture.md §5)", () => {
|
|
60
|
+
const { ast, diagnostics } = analyze(SOURCE, "researcher.agent");
|
|
61
|
+
expect(diagnostics).toEqual([]);
|
|
62
|
+
expect(generate(ast)).toBe(EXPECTED);
|
|
63
|
+
});
|
|
64
|
+
it("is deterministic", () => {
|
|
65
|
+
const { ast } = analyze(SOURCE, "researcher.agent");
|
|
66
|
+
expect(generate(ast)).toBe(generate(ast));
|
|
67
|
+
});
|
|
68
|
+
it("omits zod/tools and returns string output for a minimal agent", () => {
|
|
69
|
+
const { ast } = analyze("agent: ping\nmodel: m\nprompt: hi", "ping.agent");
|
|
70
|
+
const code = generate(ast);
|
|
71
|
+
expect(code).toContain("Agent<PingInput, string>");
|
|
72
|
+
expect(code).not.toContain('from "zod"');
|
|
73
|
+
expect(code).not.toContain("tools:");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=codegen.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.test.js","sourceRoot":"","sources":["../src/codegen.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,MAAM,GAAG;IACb,mBAAmB;IACnB,wBAAwB;IACxB,6DAA6D;IAC7D,uBAAuB;IACvB,gBAAgB;IAChB,iCAAiC;IACjC,WAAW;IACX,wDAAwD;IACxD,iEAAiE;IACjE,2BAA2B;IAC3B,wBAAwB;IACxB,kBAAkB;IAClB,oBAAoB;CACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,+DAA+D;AAC/D,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChB,CAAC;AAEF,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,GAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACpD,MAAM,CAAC,QAAQ,CAAC,GAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAI,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,mCAAmC,EAAE,YAAY,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAI,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controlflow.test.d.ts","sourceRoot":"","sources":["../src/controlflow.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { analyze } from "./analyze.js";
|
|
3
|
+
import { generate } from "./codegen.js";
|
|
4
|
+
import { parsePromptTemplate } from "./interpolate.js";
|
|
5
|
+
function agent(promptBody, rows) {
|
|
6
|
+
return [
|
|
7
|
+
"agent: a",
|
|
8
|
+
"model: m",
|
|
9
|
+
`inputs[${rows.length}]{name,type}:`,
|
|
10
|
+
...rows.map((r) => ` ${r}`),
|
|
11
|
+
"prompt: |",
|
|
12
|
+
...promptBody.map((l) => ` ${l}`),
|
|
13
|
+
].join("\n");
|
|
14
|
+
}
|
|
15
|
+
describe("{#each} index + {:else}", () => {
|
|
16
|
+
it("parses an index variable", () => {
|
|
17
|
+
const { segments } = parsePromptTemplate("{#each inputs.xs as x, i}\n{i}. {x}\n{/each}");
|
|
18
|
+
expect(segments[0]).toMatchObject({
|
|
19
|
+
kind: "each",
|
|
20
|
+
item: { kind: "name", name: "x" },
|
|
21
|
+
index: "i",
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it("compiles the index to .map((it, i) =>", () => {
|
|
25
|
+
const src = agent(["{#each inputs.items as it, i}", "{i}. {it}", "{/each}"], ["items,string[]"]);
|
|
26
|
+
const { ast, diagnostics } = analyze(src, "a.agent");
|
|
27
|
+
expect(diagnostics).toEqual([]);
|
|
28
|
+
expect(generate(ast)).toContain("inputs.items.map((it, i) => `");
|
|
29
|
+
});
|
|
30
|
+
it("compiles an each-{:else} to a length guard", () => {
|
|
31
|
+
const src = agent(["{#each inputs.items as it}", "- {it}", "{:else}", "(none)", "{/each}"], ["items,string[]"]);
|
|
32
|
+
const { ast, diagnostics } = analyze(src, "a.agent");
|
|
33
|
+
expect(diagnostics).toEqual([]);
|
|
34
|
+
const code = generate(ast);
|
|
35
|
+
expect(code).toContain("inputs.items.length > 0 ?");
|
|
36
|
+
expect(code).toContain("(none)");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("{#if} {:else if} chains", () => {
|
|
40
|
+
it("parses else-if into nested ifs", () => {
|
|
41
|
+
const { segments, errors } = parsePromptTemplate("{#if inputs.a}\nA\n{:else if inputs.b}\nB\n{:else}\nC\n{/if}");
|
|
42
|
+
expect(errors).toEqual([]);
|
|
43
|
+
expect(segments[0]).toMatchObject({
|
|
44
|
+
kind: "if",
|
|
45
|
+
cond: ["inputs", "a"],
|
|
46
|
+
then: [{ kind: "text", value: "A\n" }],
|
|
47
|
+
else: [
|
|
48
|
+
{
|
|
49
|
+
kind: "if",
|
|
50
|
+
cond: ["inputs", "b"],
|
|
51
|
+
then: [{ kind: "text", value: "B\n" }],
|
|
52
|
+
else: [{ kind: "text", value: "C\n" }],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
it("compiles else-if to nested ternaries", () => {
|
|
58
|
+
const src = agent([
|
|
59
|
+
"{#if inputs.a}",
|
|
60
|
+
"alpha",
|
|
61
|
+
"{:else if inputs.b}",
|
|
62
|
+
"beta",
|
|
63
|
+
"{:else}",
|
|
64
|
+
"gamma",
|
|
65
|
+
"{/if}",
|
|
66
|
+
], ["a,boolean", "b,boolean"]);
|
|
67
|
+
const { ast, diagnostics } = analyze(src, "a.agent");
|
|
68
|
+
expect(diagnostics).toEqual([]);
|
|
69
|
+
const code = generate(ast);
|
|
70
|
+
expect(code).toContain("inputs.a ?");
|
|
71
|
+
expect(code).toContain("inputs.b ?");
|
|
72
|
+
expect(code).toContain("gamma");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=controlflow.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controlflow.test.js","sourceRoot":"","sources":["../src/controlflow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics shared across the compiler pipeline. User errors are collected and
|
|
3
|
+
* reported here — never thrown (see `_bmad-output/architecture.md`, NFR4).
|
|
4
|
+
*
|
|
5
|
+
* Code ranges: TOA0xx general · TOA1xx parse/decode · TOA2xx validation ·
|
|
6
|
+
* TOA3xx interpolation.
|
|
7
|
+
*/
|
|
8
|
+
export interface Diagnostic {
|
|
9
|
+
severity: "error" | "warning";
|
|
10
|
+
/** Stable code, e.g. "TOA101". */
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
file: string;
|
|
14
|
+
line?: number;
|
|
15
|
+
col?: number;
|
|
16
|
+
}
|
|
17
|
+
/** Build an error-severity diagnostic, attaching location only when known. */
|
|
18
|
+
export declare function errorDiagnostic(code: string, message: string, file: string, loc?: {
|
|
19
|
+
line?: number;
|
|
20
|
+
col?: number;
|
|
21
|
+
}): Diagnostic;
|
|
22
|
+
/** Format a diagnostic as `file:line:col severity CODE: message`. */
|
|
23
|
+
export declare function formatDiagnostic(d: Diagnostic): string;
|
|
24
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC,UAAU,CASZ;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAMtD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics shared across the compiler pipeline. User errors are collected and
|
|
3
|
+
* reported here — never thrown (see `_bmad-output/architecture.md`, NFR4).
|
|
4
|
+
*
|
|
5
|
+
* Code ranges: TOA0xx general · TOA1xx parse/decode · TOA2xx validation ·
|
|
6
|
+
* TOA3xx interpolation.
|
|
7
|
+
*/
|
|
8
|
+
/** Build an error-severity diagnostic, attaching location only when known. */
|
|
9
|
+
export function errorDiagnostic(code, message, file, loc) {
|
|
10
|
+
const diagnostic = { severity: "error", code, message, file };
|
|
11
|
+
if (loc?.line !== undefined) {
|
|
12
|
+
diagnostic.line = loc.line;
|
|
13
|
+
}
|
|
14
|
+
if (loc?.col !== undefined) {
|
|
15
|
+
diagnostic.col = loc.col;
|
|
16
|
+
}
|
|
17
|
+
return diagnostic;
|
|
18
|
+
}
|
|
19
|
+
/** Format a diagnostic as `file:line:col severity CODE: message`. */
|
|
20
|
+
export function formatDiagnostic(d) {
|
|
21
|
+
const loc = d.line !== undefined
|
|
22
|
+
? `:${d.line}${d.col !== undefined ? `:${d.col}` : ""}`
|
|
23
|
+
: "";
|
|
24
|
+
return `${d.file}${loc} ${d.severity} ${d.code}: ${d.message}`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,OAAe,EACf,IAAY,EACZ,GAAqC;IAErC,MAAM,UAAU,GAAe,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,GAAG,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,IAAI,GAAG,EAAE,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IAC3B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,gBAAgB,CAAC,CAAa;IAC5C,MAAM,GAAG,GACP,CAAC,CAAC,IAAI,KAAK,SAAS;QAClB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QACvD,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"each.test.d.ts","sourceRoot":"","sources":["../src/each.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { analyze } from "./analyze.js";
|
|
3
|
+
import { generate } from "./codegen.js";
|
|
4
|
+
import { parsePromptTemplate } from "./interpolate.js";
|
|
5
|
+
describe("{#each} parsing", () => {
|
|
6
|
+
it("parses an each block into a nested segment", () => {
|
|
7
|
+
const { segments, errors } = parsePromptTemplate("Sources:\n{#each inputs.sources as s}\n- {s}\n{/each}\nDone.");
|
|
8
|
+
expect(errors).toEqual([]);
|
|
9
|
+
expect(segments).toEqual([
|
|
10
|
+
{ kind: "text", value: "Sources:\n" },
|
|
11
|
+
{
|
|
12
|
+
kind: "each",
|
|
13
|
+
source: ["inputs", "sources"],
|
|
14
|
+
item: { kind: "name", name: "s" },
|
|
15
|
+
body: [
|
|
16
|
+
{ kind: "text", value: "- " },
|
|
17
|
+
{ kind: "interp", path: ["s"] },
|
|
18
|
+
{ kind: "text", value: "\n" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{ kind: "text", value: "Done." },
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
it("reports an unclosed each", () => {
|
|
25
|
+
const { errors } = parsePromptTemplate("{#each inputs.xs as x}\n- {x}");
|
|
26
|
+
expect(errors.some((e) => /unclosed/.test(e))).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it("reports an invalid each header", () => {
|
|
29
|
+
const { errors } = parsePromptTemplate("{#each nope}\n{/each}");
|
|
30
|
+
expect(errors.some((e) => /invalid \{#each\}/.test(e))).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
function digest(promptBody) {
|
|
34
|
+
return [
|
|
35
|
+
"agent: digest",
|
|
36
|
+
"model: m",
|
|
37
|
+
"inputs[1]{name,type}:",
|
|
38
|
+
" sources,string[]",
|
|
39
|
+
"prompt: |",
|
|
40
|
+
...promptBody.map((l) => ` ${l}`),
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
describe("{#each} validation + codegen", () => {
|
|
44
|
+
it("compiles an each over an array input to .map().join()", () => {
|
|
45
|
+
const src = digest([
|
|
46
|
+
"Sources:",
|
|
47
|
+
"{#each inputs.sources as s}",
|
|
48
|
+
"- {s}",
|
|
49
|
+
"{/each}",
|
|
50
|
+
]);
|
|
51
|
+
const { ast, diagnostics } = analyze(src, "digest.agent");
|
|
52
|
+
expect(diagnostics).toEqual([]);
|
|
53
|
+
const code = generate(ast);
|
|
54
|
+
expect(code).toContain("inputs.sources.map((s) => `");
|
|
55
|
+
expect(code).toContain('.join("")');
|
|
56
|
+
});
|
|
57
|
+
it("rejects {#each} over a non-array input (TOA303)", () => {
|
|
58
|
+
const src = [
|
|
59
|
+
"agent: d",
|
|
60
|
+
"model: m",
|
|
61
|
+
"inputs[1]{name,type}:",
|
|
62
|
+
" topic,string",
|
|
63
|
+
"prompt: |",
|
|
64
|
+
" {#each inputs.topic as t}",
|
|
65
|
+
" - {t}",
|
|
66
|
+
" {/each}",
|
|
67
|
+
].join("\n");
|
|
68
|
+
const { diagnostics } = analyze(src, "d.agent");
|
|
69
|
+
expect(diagnostics.map((d) => d.code)).toContain("TOA303");
|
|
70
|
+
});
|
|
71
|
+
it("rejects a loop variable used outside its block (TOA301)", () => {
|
|
72
|
+
const src = digest([
|
|
73
|
+
"{#each inputs.sources as s}",
|
|
74
|
+
"- {s}",
|
|
75
|
+
"{/each}",
|
|
76
|
+
"tail {s}",
|
|
77
|
+
]);
|
|
78
|
+
const { diagnostics } = analyze(src, "digest.agent");
|
|
79
|
+
expect(diagnostics.map((d) => d.code)).toContain("TOA301");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=each.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"each.test.js","sourceRoot":"","sources":["../src/each.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.test.d.ts","sourceRoot":"","sources":["../src/env.test.ts"],"names":[],"mappings":""}
|
package/dist/env.test.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { analyze } from "./analyze.js";
|
|
3
|
+
import { generate } from "./codegen.js";
|
|
4
|
+
function agent(promptBody) {
|
|
5
|
+
return [
|
|
6
|
+
"agent: a",
|
|
7
|
+
"model: m",
|
|
8
|
+
"prompt: |",
|
|
9
|
+
...promptBody.map((l) => ` ${l}`),
|
|
10
|
+
].join("\n");
|
|
11
|
+
}
|
|
12
|
+
describe("{env.X} interpolation", () => {
|
|
13
|
+
it("compiles {env.VAR} to process.env.VAR with a default", () => {
|
|
14
|
+
const { ast, diagnostics } = analyze(agent(["Base: {env.API_BASE}"]), "a.agent");
|
|
15
|
+
expect(diagnostics).toEqual([]);
|
|
16
|
+
expect(generate(ast)).toContain('process.env.API_BASE ?? ""');
|
|
17
|
+
});
|
|
18
|
+
it("does not require env vars to be declared", () => {
|
|
19
|
+
const { diagnostics } = analyze(agent(["{env.ANYTHING}"]), "a.agent");
|
|
20
|
+
expect(diagnostics).toEqual([]);
|
|
21
|
+
});
|
|
22
|
+
it("rejects a bare {env} (TOA301)", () => {
|
|
23
|
+
const { diagnostics } = analyze(agent(["{env}"]), "a.agent");
|
|
24
|
+
expect(diagnostics.map((d) => d.code)).toContain("TOA301");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=env.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.test.js","sourceRoot":"","sources":["../src/env.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,SAAS,KAAK,CAAC,UAAoB;IACjC,OAAO;QACL,UAAU;QACV,UAAU;QACV,WAAW;QACX,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;KACnC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,OAAO,CAClC,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,EAC/B,SAAS,CACV,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,GAAI,CAAC,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACtE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.test.d.ts","sourceRoot":"","sources":["../src/example.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { compile } from "./index.js";
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const exampleDir = join(here, "..", "..", "..", "examples", "researcher");
|
|
8
|
+
describe("examples/researcher", () => {
|
|
9
|
+
it("the committed researcher.ts matches toac output for researcher.agent", async () => {
|
|
10
|
+
const [source, committed] = await Promise.all([
|
|
11
|
+
readFile(join(exampleDir, "researcher.agent"), "utf8"),
|
|
12
|
+
readFile(join(exampleDir, "researcher.ts"), "utf8"),
|
|
13
|
+
]);
|
|
14
|
+
const { code, diagnostics } = compile(source, "researcher.agent");
|
|
15
|
+
expect(diagnostics).toEqual([]);
|
|
16
|
+
expect(code).toBe(committed);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=example.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.test.js","sourceRoot":"","sources":["../src/example.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAE1E,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC;YACtD,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC;SACpD,CAAC,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAClE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"if.test.d.ts","sourceRoot":"","sources":["../src/if.test.ts"],"names":[],"mappings":""}
|
package/dist/if.test.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { analyze } from "./analyze.js";
|
|
3
|
+
import { generate } from "./codegen.js";
|
|
4
|
+
import { parsePromptTemplate } from "./interpolate.js";
|
|
5
|
+
describe("{#if} parsing", () => {
|
|
6
|
+
it("parses if/else into a segment", () => {
|
|
7
|
+
const { segments, errors } = parsePromptTemplate("{#if inputs.verbose}\ndetailed\n{:else}\nbrief\n{/if}");
|
|
8
|
+
expect(errors).toEqual([]);
|
|
9
|
+
expect(segments).toEqual([
|
|
10
|
+
{
|
|
11
|
+
kind: "if",
|
|
12
|
+
cond: ["inputs", "verbose"],
|
|
13
|
+
negate: false,
|
|
14
|
+
then: [{ kind: "text", value: "detailed\n" }],
|
|
15
|
+
else: [{ kind: "text", value: "brief\n" }],
|
|
16
|
+
},
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
it("parses negation and an absent else", () => {
|
|
20
|
+
const { segments, errors } = parsePromptTemplate("{#if !inputs.x}\nhi\n{/if}");
|
|
21
|
+
expect(errors).toEqual([]);
|
|
22
|
+
expect(segments[0]).toMatchObject({
|
|
23
|
+
kind: "if",
|
|
24
|
+
cond: ["inputs", "x"],
|
|
25
|
+
negate: true,
|
|
26
|
+
else: [],
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it("reports an unclosed if", () => {
|
|
30
|
+
const { errors } = parsePromptTemplate("{#if inputs.x}\nhi");
|
|
31
|
+
expect(errors.some((e) => /unclosed/.test(e))).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
function agent(promptBody, inputRow = " verbose,boolean") {
|
|
35
|
+
return [
|
|
36
|
+
"agent: a",
|
|
37
|
+
"model: m",
|
|
38
|
+
"inputs[1]{name,type}:",
|
|
39
|
+
inputRow,
|
|
40
|
+
"prompt: |",
|
|
41
|
+
...promptBody.map((l) => ` ${l}`),
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
describe("{#if} validation + codegen", () => {
|
|
45
|
+
it("compiles an if over a boolean input to a ternary", () => {
|
|
46
|
+
const src = agent([
|
|
47
|
+
"{#if inputs.verbose}",
|
|
48
|
+
"be detailed",
|
|
49
|
+
"{:else}",
|
|
50
|
+
"be brief",
|
|
51
|
+
"{/if}",
|
|
52
|
+
]);
|
|
53
|
+
const { ast, diagnostics } = analyze(src, "a.agent");
|
|
54
|
+
expect(diagnostics).toEqual([]);
|
|
55
|
+
const code = generate(ast);
|
|
56
|
+
expect(code).toContain("inputs.verbose ?");
|
|
57
|
+
expect(code).toContain("be detailed");
|
|
58
|
+
expect(code).toContain("be brief");
|
|
59
|
+
});
|
|
60
|
+
it("compiles a negated if", () => {
|
|
61
|
+
const src = agent(["{#if !inputs.verbose}", "short", "{/if}"]);
|
|
62
|
+
const { ast, diagnostics } = analyze(src, "a.agent");
|
|
63
|
+
expect(diagnostics).toEqual([]);
|
|
64
|
+
expect(generate(ast)).toContain("!inputs.verbose ?");
|
|
65
|
+
});
|
|
66
|
+
it("rejects {#if} over a non-boolean input (TOA305)", () => {
|
|
67
|
+
const src = agent(["{#if inputs.topic}", "x", "{/if}"], " topic,string");
|
|
68
|
+
const { diagnostics } = analyze(src, "a.agent");
|
|
69
|
+
expect(diagnostics.map((d) => d.code)).toContain("TOA305");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=if.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"if.test.js","sourceRoot":"","sources":["../src/if.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Diagnostic } from "./diagnostics.js";
|
|
2
|
+
export declare const COMPILER_VERSION = "0.1.0";
|
|
3
|
+
export type { Diagnostic } from "./diagnostics.js";
|
|
4
|
+
export { errorDiagnostic, formatDiagnostic } from "./diagnostics.js";
|
|
5
|
+
export { decodeToon, type DecodeToonResult } from "./toon.js";
|
|
6
|
+
export { preprocess, type PreprocessResult } from "./preprocess.js";
|
|
7
|
+
export { analyze, type AnalyzeResult } from "./analyze.js";
|
|
8
|
+
export { generate } from "./codegen.js";
|
|
9
|
+
export type { AgentAst, FieldDecl, PromptSegment, ToaType, ToaTypeBase, } from "./ast.js";
|
|
10
|
+
export interface CompileResult {
|
|
11
|
+
/** Emitted TypeScript, present only when there are no error diagnostics. */
|
|
12
|
+
code?: string;
|
|
13
|
+
diagnostics: Diagnostic[];
|
|
14
|
+
}
|
|
15
|
+
/** Compile `.agent` source to a TypeScript module, or return diagnostics. */
|
|
16
|
+
export declare function compile(source: string, file?: string): CompileResult;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,YAAY,EACV,QAAQ,EACR,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,GACZ,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,SAAY,GAAG,aAAa,CAMvE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `toad-compiler` — the `toac` compiler: `.agent` (a TOON superset) -> typed `.ts`.
|
|
3
|
+
* Pipeline: preprocess -> TOON decode -> validate -> codegen.
|
|
4
|
+
* See `_bmad-output/architecture.md`.
|
|
5
|
+
*/
|
|
6
|
+
import { analyze } from "./analyze.js";
|
|
7
|
+
import { generate } from "./codegen.js";
|
|
8
|
+
export const COMPILER_VERSION = "0.1.0";
|
|
9
|
+
export { errorDiagnostic, formatDiagnostic } from "./diagnostics.js";
|
|
10
|
+
export { decodeToon } from "./toon.js";
|
|
11
|
+
export { preprocess } from "./preprocess.js";
|
|
12
|
+
export { analyze } from "./analyze.js";
|
|
13
|
+
export { generate } from "./codegen.js";
|
|
14
|
+
/** Compile `.agent` source to a TypeScript module, or return diagnostics. */
|
|
15
|
+
export function compile(source, file = "<input>") {
|
|
16
|
+
const { ast, diagnostics } = analyze(source, file);
|
|
17
|
+
if (ast === undefined) {
|
|
18
|
+
return { diagnostics };
|
|
19
|
+
}
|
|
20
|
+
return { code: generate(ast), diagnostics };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAyB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAyB,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAsB,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAexC,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,IAAI,GAAG,SAAS;IACtD,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,EAAE,WAAW,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { compile, COMPILER_VERSION } from "./index.js";
|
|
3
|
+
describe("toad-compiler", () => {
|
|
4
|
+
it("exposes a version", () => {
|
|
5
|
+
expect(COMPILER_VERSION).toBe("0.1.0");
|
|
6
|
+
});
|
|
7
|
+
it("returns diagnostics (and no code) for an invalid agent", () => {
|
|
8
|
+
const result = compile("agent: demo");
|
|
9
|
+
expect(result.code).toBeUndefined();
|
|
10
|
+
expect(result.diagnostics.length).toBeGreaterThan(0);
|
|
11
|
+
});
|
|
12
|
+
it("emits code for a valid agent", () => {
|
|
13
|
+
const result = compile("agent: demo\nmodel: m\nprompt: hi");
|
|
14
|
+
expect(result.diagnostics).toEqual([]);
|
|
15
|
+
expect(result.code).toContain("createAgent({");
|
|
16
|
+
expect(result.code).toContain("export default demo;");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEvD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,OAAO,CAAC,mCAAmC,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PromptSegment } from "./ast.js";
|
|
2
|
+
export interface ParseTemplateResult {
|
|
3
|
+
segments: PromptSegment[];
|
|
4
|
+
errors: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Parse a prompt string into segments. Supports:
|
|
8
|
+
* - `{ a.b }` / `{ env.X }` interpolation
|
|
9
|
+
* - `{#each xs as x, i}…{:else}…{/each}` loop (index + empty fallback)
|
|
10
|
+
* - `{#if a}…{:else if b}…{:else}…{/if}` conditional chain
|
|
11
|
+
* - `{{` / `}}` literal braces
|
|
12
|
+
*
|
|
13
|
+
* `{:else if}` desugars to a nested `{#if}` in the else branch, so the `if`
|
|
14
|
+
* segment stays a simple then/else. Block directives are control lines (the
|
|
15
|
+
* newline immediately after each is consumed). Validation happens in `validate`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parsePromptTemplate(text: string): ParseTemplateResult;
|
|
18
|
+
//# sourceMappingURL=interpolate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interpolate.d.ts","sourceRoot":"","sources":["../src/interpolate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAgCD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CA6OrE"}
|