agency-lang 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/backends/agencyGenerator.d.ts +2 -0
- package/dist/lib/backends/agencyGenerator.js +14 -5
- package/dist/lib/backends/baseGenerator.d.ts +4 -1
- package/dist/lib/backends/baseGenerator.js +6 -1
- package/dist/lib/backends/graphGenerator.d.ts +1 -1
- package/dist/lib/backends/graphGenerator.js +14 -8
- package/dist/lib/backends/typescriptGenerator/builtins.js +6 -0
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.d.ts +1 -0
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.js +3 -2
- package/dist/lib/backends/typescriptGenerator.d.ts +2 -0
- package/dist/lib/backends/typescriptGenerator.js +15 -1
- package/dist/lib/parser.js +2 -1
- package/dist/lib/parsers/function.js +2 -1
- package/dist/lib/parsers/specialVar.d.ts +4 -0
- package/dist/lib/parsers/specialVar.js +8 -0
- package/dist/lib/templates/backends/graphGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/graphGenerator/imports.js +13 -6
- package/dist/lib/templates/backends/graphGenerator/runNodeFunction.d.ts +6 -0
- package/dist/lib/templates/backends/graphGenerator/runNodeFunction.js +13 -0
- package/dist/lib/templates/backends/graphGenerator/specialVar.d.ts +7 -0
- package/dist/lib/templates/backends/graphGenerator/specialVar.js +9 -0
- package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/readImage.d.ts +4 -0
- package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/readImage.js +17 -0
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.d.ts +2 -1
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.js +13 -2
- package/dist/lib/types/specialVar.d.ts +9 -0
- package/dist/lib/types/specialVar.js +1 -0
- package/dist/lib/types.d.ts +2 -1
- package/dist/scripts/agency.js +35 -8
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SpecialVar } from "../types/specialVar.js";
|
|
1
2
|
import { AgencyComment, AgencyProgram, Assignment, Literal, PromptLiteral, TypeAlias, TypeHint, VariableType } from "../types.js";
|
|
2
3
|
import { AccessExpression, DotFunctionCall, DotProperty, IndexAccess } from "../types/access.js";
|
|
3
4
|
import { AgencyArray, AgencyObject } from "../types/dataStructures.js";
|
|
@@ -44,6 +45,7 @@ export declare class AgencyGenerator extends BaseGenerator {
|
|
|
44
45
|
protected processGraphNode(node: GraphNodeDefinition): string;
|
|
45
46
|
protected processTool(node: FunctionDefinition): string;
|
|
46
47
|
protected processUsesTool(node: UsesTool): string;
|
|
48
|
+
protected processSpecialVar(node: SpecialVar): string;
|
|
47
49
|
private indentStr;
|
|
48
50
|
}
|
|
49
51
|
export declare function generateAgency(program: AgencyProgram): string;
|
|
@@ -58,7 +58,7 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
58
58
|
// Assignment and literals
|
|
59
59
|
processAssignment(node) {
|
|
60
60
|
const valueCode = this.processNode(node.value).trim();
|
|
61
|
-
return this.indentStr(`${node.variableName} = ${valueCode}\n
|
|
61
|
+
return this.indentStr(`${node.variableName} = ${valueCode}\n`);
|
|
62
62
|
}
|
|
63
63
|
generateLiteral(literal) {
|
|
64
64
|
switch (literal.type) {
|
|
@@ -106,9 +106,12 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
106
106
|
// Process body with increased indentation
|
|
107
107
|
this.increaseIndent();
|
|
108
108
|
this.functionScopedVariables = [...parameters];
|
|
109
|
+
const lines = [];
|
|
109
110
|
for (const stmt of body) {
|
|
110
|
-
|
|
111
|
+
lines.push(this.processNode(stmt));
|
|
111
112
|
}
|
|
113
|
+
const bodyCode = lines.join("").trimEnd() + "\n";
|
|
114
|
+
result += bodyCode;
|
|
112
115
|
this.functionScopedVariables = [];
|
|
113
116
|
this.decreaseIndent();
|
|
114
117
|
// Close function
|
|
@@ -204,10 +207,10 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
204
207
|
}
|
|
205
208
|
// Utility methods
|
|
206
209
|
processComment(node) {
|
|
207
|
-
return this.indentStr(
|
|
210
|
+
return this.indentStr(`//${node.content}\n`);
|
|
208
211
|
}
|
|
209
212
|
processImportStatement(node) {
|
|
210
|
-
return this.indentStr(`import
|
|
213
|
+
return this.indentStr(`import ${node.importedNames}from ${node.modulePath}`);
|
|
211
214
|
}
|
|
212
215
|
processGraphNode(node) {
|
|
213
216
|
// Graph nodes use similar syntax to functions
|
|
@@ -216,9 +219,12 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
216
219
|
let result = this.indentStr(`node ${nodeName}(${params}) {\n`);
|
|
217
220
|
this.increaseIndent();
|
|
218
221
|
this.functionScopedVariables = [...parameters];
|
|
222
|
+
const lines = [];
|
|
219
223
|
for (const stmt of body) {
|
|
220
|
-
|
|
224
|
+
lines.push(this.processNode(stmt));
|
|
221
225
|
}
|
|
226
|
+
const bodyCode = lines.join("").trimEnd() + "\n";
|
|
227
|
+
result += bodyCode;
|
|
222
228
|
this.functionScopedVariables = [];
|
|
223
229
|
this.decreaseIndent();
|
|
224
230
|
result += this.indentStr(`}\n`);
|
|
@@ -234,6 +240,9 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
234
240
|
this.toolsUsed.push(node.toolName);
|
|
235
241
|
return this.indentStr(`+${node.toolName}\n`);
|
|
236
242
|
}
|
|
243
|
+
processSpecialVar(node) {
|
|
244
|
+
return this.indentStr(`@${node.name} = ${this.processNode(node.value).trim()}\n`);
|
|
245
|
+
}
|
|
237
246
|
indentStr(str) {
|
|
238
247
|
return `${this.indent()}${str}`;
|
|
239
248
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SpecialVar } from "../types/specialVar.js";
|
|
1
2
|
import { AgencyComment, AgencyNode, AgencyProgram, Assignment, Literal, PromptLiteral, TypeAlias, TypeHint, TypeHintMap, VariableType } from "../types.js";
|
|
2
3
|
import { AccessExpression, DotFunctionCall, DotProperty, IndexAccess } from "../types/access.js";
|
|
3
4
|
import { AgencyArray, AgencyObject } from "../types/dataStructures.js";
|
|
@@ -5,6 +6,7 @@ import { FunctionCall, FunctionDefinition } from "../types/function.js";
|
|
|
5
6
|
import { GraphNodeDefinition } from "../types/graphNode.js";
|
|
6
7
|
import { ImportStatement } from "../types/importStatement.js";
|
|
7
8
|
import { MatchBlock } from "../types/matchBlock.js";
|
|
9
|
+
import { ReturnStatement } from "../types/returnStatement.js";
|
|
8
10
|
import { UsesTool } from "../types/tools.js";
|
|
9
11
|
import { WhileLoop } from "../types/whileLoop.js";
|
|
10
12
|
export declare class BaseGenerator {
|
|
@@ -28,6 +30,7 @@ export declare class BaseGenerator {
|
|
|
28
30
|
protected collectFunctionSignature(node: FunctionDefinition): void;
|
|
29
31
|
protected processGraphNodeName(node: GraphNodeDefinition): void;
|
|
30
32
|
protected processNode(node: AgencyNode): string;
|
|
33
|
+
protected processSpecialVar(node: SpecialVar): string;
|
|
31
34
|
protected processWhileLoop(node: WhileLoop): string;
|
|
32
35
|
protected processImportStatement(node: ImportStatement): string;
|
|
33
36
|
protected processTool(node: FunctionDefinition): string;
|
|
@@ -36,7 +39,7 @@ export declare class BaseGenerator {
|
|
|
36
39
|
protected processAgencyObject(node: AgencyObject): string;
|
|
37
40
|
protected processAgencyArray(node: AgencyArray): string;
|
|
38
41
|
protected processComment(node: AgencyComment): string;
|
|
39
|
-
protected processReturnStatement(node:
|
|
42
|
+
protected processReturnStatement(node: ReturnStatement): string;
|
|
40
43
|
protected processAccessExpression(node: AccessExpression): string;
|
|
41
44
|
protected processMatchBlock(node: MatchBlock): string;
|
|
42
45
|
protected processDotProperty(node: DotProperty): string;
|
|
@@ -54,7 +54,7 @@ export class BaseGenerator {
|
|
|
54
54
|
output.push(this.generatedStatements.join(""));
|
|
55
55
|
output.push(this.postprocess() + "\n");
|
|
56
56
|
return {
|
|
57
|
-
output: output.filter(
|
|
57
|
+
output: output.filter((line) => line.trim() !== "").join("\n"),
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
generateBuiltins() {
|
|
@@ -111,10 +111,15 @@ export class BaseGenerator {
|
|
|
111
111
|
return "";
|
|
112
112
|
case "whileLoop":
|
|
113
113
|
return this.processWhileLoop(node);
|
|
114
|
+
case "specialVar":
|
|
115
|
+
return this.processSpecialVar(node);
|
|
114
116
|
default:
|
|
115
117
|
throw new Error(`Unhandled Agency node type: ${node.type}`);
|
|
116
118
|
}
|
|
117
119
|
}
|
|
120
|
+
processSpecialVar(node) {
|
|
121
|
+
return "processSpecialVar not implemented";
|
|
122
|
+
}
|
|
118
123
|
processWhileLoop(node) {
|
|
119
124
|
return "processWhileLoop not implemented";
|
|
120
125
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgencyProgram, FunctionCall, TypeHintMap, VariableType } from "../types.js";
|
|
2
|
-
import { TypeScriptGenerator } from "./typescriptGenerator.js";
|
|
3
2
|
import { GraphNodeDefinition } from "../types/graphNode.js";
|
|
4
3
|
import { ReturnStatement } from "../types/returnStatement.js";
|
|
4
|
+
import { TypeScriptGenerator } from "./typescriptGenerator.js";
|
|
5
5
|
export declare class GraphGenerator extends TypeScriptGenerator {
|
|
6
6
|
protected typeHints: TypeHintMap;
|
|
7
7
|
protected generatedStatements: string[];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import * as builtinTools from "../templates/backends/graphGenerator/builtinTools.js";
|
|
1
2
|
import * as renderConditionalEdge from "../templates/backends/graphGenerator/conditionalEdge.js";
|
|
3
|
+
import * as goToNode from "../templates/backends/graphGenerator/goToNode.js";
|
|
4
|
+
import * as graphNode from "../templates/backends/graphGenerator/graphNode.js";
|
|
2
5
|
import * as renderImports from "../templates/backends/graphGenerator/imports.js";
|
|
3
6
|
import * as renderStartNode from "../templates/backends/graphGenerator/startNode.js";
|
|
4
|
-
import * as
|
|
5
|
-
import * as builtinTools from "../templates/backends/graphGenerator/builtinTools.js";
|
|
6
|
-
import * as goToNode from "../templates/backends/graphGenerator/goToNode.js";
|
|
7
|
+
import * as renderRunNodeFunction from "../templates/backends/graphGenerator/runNodeFunction.js";
|
|
7
8
|
import { TypeScriptGenerator } from "./typescriptGenerator.js";
|
|
8
9
|
import { mapFunctionName } from "./typescriptGenerator/builtins.js";
|
|
9
10
|
export class GraphGenerator extends TypeScriptGenerator {
|
|
@@ -293,12 +294,17 @@ export class GraphGenerator extends TypeScriptGenerator {
|
|
|
293
294
|
toNodes: JSON.stringify(adjacent),
|
|
294
295
|
}));
|
|
295
296
|
});
|
|
296
|
-
if (
|
|
297
|
-
|
|
297
|
+
if (this.graphNodes.includes("main")) {
|
|
298
|
+
lines.push(renderStartNode.default({
|
|
299
|
+
startNode: "main",
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
for (const node of this.graphNodes) {
|
|
303
|
+
lines.push(renderRunNodeFunction.default({
|
|
304
|
+
nodeName: node,
|
|
305
|
+
}));
|
|
298
306
|
}
|
|
299
|
-
lines.push(
|
|
300
|
-
startNode: "main",
|
|
301
|
-
}));
|
|
307
|
+
lines.push("export default graph;");
|
|
302
308
|
return lines.join("\n");
|
|
303
309
|
}
|
|
304
310
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as builtinFunctionsInput from "../../templates/backends/typescriptGenerator/builtinFunctions/input.js";
|
|
2
2
|
import * as builtinFunctionsRead from "../../templates/backends/typescriptGenerator/builtinFunctions/read.js";
|
|
3
|
+
import * as builtinFunctionsReadImage from "../../templates/backends/typescriptGenerator/builtinFunctions/readImage.js";
|
|
3
4
|
import * as builtinFunctionsFetchJSON from "../../templates/backends/typescriptGenerator/builtinFunctions/fetchJSON.js";
|
|
4
5
|
import * as builtinFunctionsFetch from "../../templates/backends/typescriptGenerator/builtinFunctions/fetch.js";
|
|
5
6
|
/**
|
|
@@ -9,6 +10,7 @@ export const BUILTIN_FUNCTIONS = {
|
|
|
9
10
|
print: "console.log",
|
|
10
11
|
input: "_builtinInput",
|
|
11
12
|
read: "_builtinRead",
|
|
13
|
+
readImage: "_builtinReadImage",
|
|
12
14
|
write: "fs.writeFileSync",
|
|
13
15
|
fetch: "_builtinFetch",
|
|
14
16
|
fetchJSON: "_builtinFetchJSON",
|
|
@@ -42,5 +44,9 @@ export function generateBuiltinHelpers(functionsUsed) {
|
|
|
42
44
|
const fetchFunc = builtinFunctionsFetch.default({});
|
|
43
45
|
helpers.push(fetchFunc);
|
|
44
46
|
}
|
|
47
|
+
if (functionsUsed.has("readImage")) {
|
|
48
|
+
const readImageFunc = builtinFunctionsReadImage.default({});
|
|
49
|
+
helpers.push(readImageFunc);
|
|
50
|
+
}
|
|
45
51
|
return helpers.join("\n\n");
|
|
46
52
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escape } from "../../utils.js";
|
|
2
|
+
export const DEFAULT_SCHEMA = "z.string()";
|
|
2
3
|
/**
|
|
3
4
|
* Maps Agency types to Zod schema strings
|
|
4
5
|
*/
|
|
@@ -8,12 +9,12 @@ export function mapTypeToZodSchema(variableType, typeAliases) {
|
|
|
8
9
|
case "number":
|
|
9
10
|
return "z.number()";
|
|
10
11
|
case "string":
|
|
11
|
-
return
|
|
12
|
+
return DEFAULT_SCHEMA;
|
|
12
13
|
case "boolean":
|
|
13
14
|
return "z.boolean()";
|
|
14
15
|
default:
|
|
15
16
|
// Default to string for unknown types
|
|
16
|
-
return
|
|
17
|
+
return DEFAULT_SCHEMA;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
else if (variableType.type === "arrayType") {
|
|
@@ -8,6 +8,7 @@ import { ReturnStatement } from "../types/returnStatement.js";
|
|
|
8
8
|
import { UsesTool } from "../types/tools.js";
|
|
9
9
|
import { ImportStatement } from "../types/importStatement.js";
|
|
10
10
|
import { WhileLoop } from "../types/whileLoop.js";
|
|
11
|
+
import { SpecialVar } from "../types/specialVar.js";
|
|
11
12
|
export declare class TypeScriptGenerator extends BaseGenerator {
|
|
12
13
|
constructor();
|
|
13
14
|
protected generateBuiltins(): string;
|
|
@@ -52,5 +53,6 @@ export declare class TypeScriptGenerator extends BaseGenerator {
|
|
|
52
53
|
}): string;
|
|
53
54
|
protected processImportStatement(node: ImportStatement): string;
|
|
54
55
|
protected processWhileLoop(node: WhileLoop): string;
|
|
56
|
+
protected processSpecialVar(node: SpecialVar): string;
|
|
55
57
|
}
|
|
56
58
|
export declare function generateTypeScript(program: AgencyProgram): string;
|
|
@@ -3,11 +3,12 @@ import * as promptFunction from "../templates/backends/typescriptGenerator/promp
|
|
|
3
3
|
import * as renderTool from "../templates/backends/typescriptGenerator/tool.js";
|
|
4
4
|
import * as renderToolCall from "../templates/backends/typescriptGenerator/toolCall.js";
|
|
5
5
|
import * as renderFunctionDefinition from "../templates/backends/typescriptGenerator/functionDefinition.js";
|
|
6
|
+
import * as renderSpecialVar from "../templates/backends/graphGenerator/specialVar.js";
|
|
6
7
|
import { escape, zip } from "../utils.js";
|
|
7
8
|
import { BaseGenerator } from "./baseGenerator.js";
|
|
8
9
|
import { generateBuiltinHelpers, mapFunctionName, } from "./typescriptGenerator/builtins.js";
|
|
9
10
|
import { variableTypeToString } from "./typescriptGenerator/typeToString.js";
|
|
10
|
-
import { mapTypeToZodSchema } from "./typescriptGenerator/typeToZodSchema.js";
|
|
11
|
+
import { DEFAULT_SCHEMA, mapTypeToZodSchema, } from "./typescriptGenerator/typeToZodSchema.js";
|
|
11
12
|
import * as builtinTools from "../templates/backends/typescriptGenerator/builtinTools.js";
|
|
12
13
|
export class TypeScriptGenerator extends BaseGenerator {
|
|
13
14
|
constructor() {
|
|
@@ -318,6 +319,7 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
318
319
|
argsStr,
|
|
319
320
|
typeString,
|
|
320
321
|
promptCode,
|
|
322
|
+
hasResponseFormat: zodSchema !== DEFAULT_SCHEMA,
|
|
321
323
|
zodSchema,
|
|
322
324
|
tools,
|
|
323
325
|
functionCalls,
|
|
@@ -335,6 +337,18 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
335
337
|
const bodyCodeStr = bodyCodes.join("\n");
|
|
336
338
|
return `while (${conditionCode}) {\n${bodyCodeStr}\n}\n`;
|
|
337
339
|
}
|
|
340
|
+
processSpecialVar(node) {
|
|
341
|
+
const value = this.processNode(node.value);
|
|
342
|
+
switch (node.name) {
|
|
343
|
+
case "model":
|
|
344
|
+
return renderSpecialVar.default({
|
|
345
|
+
name: "model",
|
|
346
|
+
value,
|
|
347
|
+
});
|
|
348
|
+
default:
|
|
349
|
+
throw new Error(`Unhandled SpecialVar name: ${node.name}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
338
352
|
}
|
|
339
353
|
export function generateTypeScript(program) {
|
|
340
354
|
const generator = new TypeScriptGenerator();
|
package/dist/lib/parser.js
CHANGED
|
@@ -10,8 +10,9 @@ import { matchBlockParser } from "./parsers/matchBlock.js";
|
|
|
10
10
|
import { returnStatementParser } from "./parsers/returnStatement.js";
|
|
11
11
|
import { usesToolParser } from "./parsers/tools.js";
|
|
12
12
|
import { EgonLog } from "egonlog";
|
|
13
|
+
import { specialVarParser } from "./parsers/specialVar.js";
|
|
13
14
|
export const agencyNode = (input) => {
|
|
14
|
-
const parser = sepBy(spaces, trace("agencyParser", or(usesToolParser, importStatmentParser, graphNodeParser, typeAliasParser, whileLoopParser, typeHintParser, matchBlockParser, functionParser, returnStatementParser, accessExpressionParser, assignmentParser, functionCallParser, commentParser)));
|
|
15
|
+
const parser = sepBy(spaces, trace("agencyParser", or(usesToolParser, importStatmentParser, graphNodeParser, typeAliasParser, whileLoopParser, typeHintParser, matchBlockParser, functionParser, returnStatementParser, specialVarParser, accessExpressionParser, assignmentParser, functionCallParser, commentParser)));
|
|
15
16
|
return parser(input);
|
|
16
17
|
};
|
|
17
18
|
export const agencyParser = seqC(set("type", "agencyProgram"), capture(agencyNode, "nodes"), eof);
|
|
@@ -10,10 +10,11 @@ import { typeAliasParser, typeHintParser } from "./typeHints.js";
|
|
|
10
10
|
import { comma, optionalSpaces, varNameChar } from "./utils.js";
|
|
11
11
|
import { returnStatementParser } from "./returnStatement.js";
|
|
12
12
|
import { usesToolParser } from "./tools.js";
|
|
13
|
+
import { specialVarParser } from "./specialVar.js";
|
|
13
14
|
const trim = (s) => s.trim();
|
|
14
15
|
export const docStringParser = trace("docStringParser", seqC(set("type", "docString"), str('"""'), capture(map(many1Till(str('"""')), trim), "value"), str('"""')));
|
|
15
16
|
export const bodyParser = trace("functionBodyParser", (input) => {
|
|
16
|
-
const parser = sepBy(spaces, or(usesToolParser, debug(typeAliasParser, "error in typeAliasParser"), debug(typeHintParser, "error in typeHintParser"), returnStatementParser, whileLoopParser, matchBlockParser, functionParser, accessExpressionParser, assignmentParser, functionCallParser, literalParser, commentParser));
|
|
17
|
+
const parser = sepBy(spaces, or(usesToolParser, debug(typeAliasParser, "error in typeAliasParser"), debug(typeHintParser, "error in typeHintParser"), specialVarParser, returnStatementParser, whileLoopParser, matchBlockParser, functionParser, accessExpressionParser, assignmentParser, functionCallParser, literalParser, commentParser));
|
|
17
18
|
const result = parser(input);
|
|
18
19
|
return result;
|
|
19
20
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { specialVarNames, } from "../types/specialVar.js";
|
|
2
|
+
import { capture, char, or, seqC, set, str } from "tarsec";
|
|
3
|
+
import { optionalSpaces } from "./utils.js";
|
|
4
|
+
import { literalParser } from "./literals.js";
|
|
5
|
+
import { agencyArrayParser, agencyObjectParser } from "./dataStructures.js";
|
|
6
|
+
import { optionalSemicolon } from "./parserUtils.js";
|
|
7
|
+
export const specialVarNameParser = or(...specialVarNames.map((name) => str(name)));
|
|
8
|
+
export const specialVarParser = seqC(set("type", "specialVar"), char("@"), capture(specialVarNameParser, "name"), optionalSpaces, char("="), optionalSpaces, capture(or(agencyObjectParser, agencyArrayParser, literalParser), "value"), optionalSemicolon);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "import OpenAI from \"openai\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { z } from \"zod\";\nimport * as readline from \"readline\";\nimport fs from \"fs\";\nimport { PieMachine, goToNode } from \"piemachine\";\nimport { StatelogClient } from \"statelog-client\";\nimport { nanoid } from \"nanoid\";\nimport { assistantMessage, getClient, userMessage } from \"smoltalk\";\n\nconst statelogHost = \"https://statelog.adit.io\";\nconst traceId = nanoid();\nconst statelogConfig = {\n host: statelogHost,\n traceId: traceId,\n apiKey: process.env.STATELOG_API_KEY || \"\",\n projectId: \"agency-lang\",\n debugMode: false,\n };\nconst statelogClient = new StatelogClient(statelogConfig);\nconst model = \"gpt-4o-mini\";\n\nconst
|
|
1
|
+
export declare const template = "import OpenAI from \"openai\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { z } from \"zod\";\nimport * as readline from \"readline\";\nimport fs from \"fs\";\nimport { PieMachine, goToNode } from \"piemachine\";\nimport { StatelogClient } from \"statelog-client\";\nimport { nanoid } from \"nanoid\";\nimport { assistantMessage, getClient, userMessage } from \"smoltalk\";\n\nconst statelogHost = \"https://statelog.adit.io\";\nconst traceId = nanoid();\nconst statelogConfig = {\n host: statelogHost,\n traceId: traceId,\n apiKey: process.env.STATELOG_API_KEY || \"\",\n projectId: \"agency-lang\",\n debugMode: false,\n };\nconst statelogClient = new StatelogClient(statelogConfig);\nconst model = \"gpt-4o-mini\";\n\n\nconst getClientWithConfig = (config = {}) => {\n const defaultConfig = {\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n model,\n logLevel: \"warn\",\n };\n\n return getClient({ ...defaultConfig, ...config });\n};\n\nlet client = getClientWithConfig();\n\ntype State = {\n messages: string[];\n data: any;\n}\n\n// enable debug logging\nconst graphConfig = {\n debug: {\n log: true,\n logData: true,\n },\n statelog: statelogConfig,\n};\n\n// Define the names of the nodes in the graph\n// Useful for type safety\nconst nodes = {{{nodes:string}}} as const;\ntype Node = (typeof nodes)[number];\n\nconst graph = new PieMachine<State, Node>(nodes, graphConfig);";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
nodes: string;
|
|
4
4
|
};
|
|
@@ -24,12 +24,19 @@ const statelogConfig = {
|
|
|
24
24
|
const statelogClient = new StatelogClient(statelogConfig);
|
|
25
25
|
const model = "gpt-4o-mini";
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
|
|
28
|
+
const getClientWithConfig = (config = {}) => {
|
|
29
|
+
const defaultConfig = {
|
|
30
|
+
openAiApiKey: process.env.OPENAI_API_KEY || "",
|
|
31
|
+
googleApiKey: process.env.GEMINI_API_KEY || "",
|
|
32
|
+
model,
|
|
33
|
+
logLevel: "warn",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return getClient({ ...defaultConfig, ...config });
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let client = getClientWithConfig();
|
|
33
40
|
|
|
34
41
|
type State = {
|
|
35
42
|
messages: string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const template = "export async function {{{nodeName:string}}}(data) {\n const result = await graph.run(\"{{{nodeName:string}}}\", { messages: [], data });\n return result.data;\n}\n";
|
|
2
|
+
export type TemplateType = {
|
|
3
|
+
nodeName: string;
|
|
4
|
+
};
|
|
5
|
+
declare const render: (args: TemplateType) => string;
|
|
6
|
+
export default render;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// THIS FILE WAS AUTO-GENERATED
|
|
2
|
+
// Source: lib/templates/backends/graphGenerator/runNodeFunction.mustache
|
|
3
|
+
// Any manual changes will be lost.
|
|
4
|
+
import { apply } from "typestache";
|
|
5
|
+
export const template = `export async function {{{nodeName:string}}}(data) {
|
|
6
|
+
const result = await graph.run("{{{nodeName:string}}}", { messages: [], data });
|
|
7
|
+
return result.data;
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
const render = (args) => {
|
|
11
|
+
return apply(template, args);
|
|
12
|
+
};
|
|
13
|
+
export default render;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const template = "client = getClientWithConfig({ {{{name}}}: {{{value}}} });";
|
|
2
|
+
export type TemplateType = {
|
|
3
|
+
name: string | boolean | number;
|
|
4
|
+
value: string | boolean | number;
|
|
5
|
+
};
|
|
6
|
+
declare const render: (args: TemplateType) => string;
|
|
7
|
+
export default render;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// THIS FILE WAS AUTO-GENERATED
|
|
2
|
+
// Source: lib/templates/backends/graphGenerator/specialVar.mustache
|
|
3
|
+
// Any manual changes will be lost.
|
|
4
|
+
import { apply } from "typestache";
|
|
5
|
+
export const template = `client = getClientWithConfig({ {{{name}}}: {{{value}}} });`;
|
|
6
|
+
const render = (args) => {
|
|
7
|
+
return apply(template, args);
|
|
8
|
+
};
|
|
9
|
+
export default render;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const template = "/*\n * @param filePath The absolute or relative path to the image file.\n * @returns The Base64 string, or null if an error occurs.\n */\nfunction _builtinReadImage(filePath: string): string {\n const data = fs.readFileSync(filePath); // Synchronous file reading\n const base64String = data.toString('base64');\n return base64String;\n}";
|
|
2
|
+
export type TemplateType = {};
|
|
3
|
+
declare const render: (args: TemplateType) => string;
|
|
4
|
+
export default render;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// THIS FILE WAS AUTO-GENERATED
|
|
2
|
+
// Source: lib/templates/backends/typescriptGenerator/builtinFunctions/readImage.mustache
|
|
3
|
+
// Any manual changes will be lost.
|
|
4
|
+
import { apply } from "typestache";
|
|
5
|
+
export const template = `/*
|
|
6
|
+
* @param filePath The absolute or relative path to the image file.
|
|
7
|
+
* @returns The Base64 string, or null if an error occurs.
|
|
8
|
+
*/
|
|
9
|
+
function _builtinReadImage(filePath: string): string {
|
|
10
|
+
const data = fs.readFileSync(filePath); // Synchronous file reading
|
|
11
|
+
const base64String = data.toString('base64');
|
|
12
|
+
return base64String;
|
|
13
|
+
}`;
|
|
14
|
+
const render = (args) => {
|
|
15
|
+
return apply(template, args);
|
|
16
|
+
};
|
|
17
|
+
export default render;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export declare const template = "\nasync function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{typeString:string}}}> {\n const prompt = {{{promptCode:string}}};\n const startTime = performance.now();\n const messages: Message[] = [userMessage(prompt)];\n const tools = {{{tools}}};\n\n // Need to make sure this is always an object\n const responseFormat = z.object({\n response: {{{zodSchema:string}}}\n });\n\n let completion = await client.text({\n messages,\n tools,\n responseFormat,\n });\n\n const endTime = performance.now();\n statelogClient.promptCompletion({\n messages,\n completion,\n model,\n timeTaken: endTime - startTime,\n });\n\n if (!completion.success) {\n throw new Error(\n `Error getting response from ${model}: ${completion.error}`\n );\n }\n\n let responseMessage = completion.value;\n\n // Handle function calls\n while (responseMessage.toolCalls.length > 0) {\n // Add assistant's response with tool calls to message history\n messages.push(assistantMessage(responseMessage.output));\n let toolCallStartTime, toolCallEndTime;\n\n // Process each tool call\n for (const toolCall of responseMessage.toolCalls) {\n {{{functionCalls:string}}}\n }\n\n const nextStartTime = performance.now();\n let completion = await client.text({\n messages,\n tools,\n responseFormat,\n });\n\n const nextEndTime = performance.now();\n\n statelogClient.promptCompletion({\n messages,\n completion,\n model,\n timeTaken: nextEndTime - nextStartTime,\n });\n\n if (!completion.success) {\n throw new Error(\n `Error getting response from ${model}: ${completion.error}`\n );\n }\n responseMessage = completion.value;\n }\n\n // Add final assistant response to history\n messages.push(assistantMessage(responseMessage.output));\n\n try {\n const result = JSON.parse(responseMessage.output || \"\");\n return result.response;\n } catch (e) {\n return responseMessage.output;\n // console.error(\"Error parsing response for variable '{{{variableName:string}}}':\", e);\n // console.error(\"Full completion response:\", JSON.stringify(completion, null, 2));\n // throw e;\n }\n}\n";
|
|
1
|
+
export declare const template = "\nasync function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{typeString:string}}}> {\n const prompt = {{{promptCode:string}}};\n const startTime = performance.now();\n const messages: Message[] = [userMessage(prompt)];\n const tools = {{{tools}}};\n\n {{#hasResponseFormat}}\n // Need to make sure this is always an object\n const responseFormat = z.object({\n response: {{{zodSchema:string}}}\n });\n {{/hasResponseFormat}}\n {{^hasResponseFormat}}\n const responseFormat = undefined;\n {{/hasResponseFormat}}\n\n let completion = await client.text({\n messages,\n tools,\n responseFormat,\n });\n\n const endTime = performance.now();\n statelogClient.promptCompletion({\n messages,\n completion,\n model: client.getModel(),\n timeTaken: endTime - startTime,\n });\n\n if (!completion.success) {\n throw new Error(\n `Error getting response from ${model}: ${completion.error}`\n );\n }\n\n let responseMessage = completion.value;\n\n // Handle function calls\n while (responseMessage.toolCalls.length > 0) {\n // Add assistant's response with tool calls to message history\n messages.push(assistantMessage(responseMessage.output));\n let toolCallStartTime, toolCallEndTime;\n\n // Process each tool call\n for (const toolCall of responseMessage.toolCalls) {\n {{{functionCalls:string}}}\n }\n\n const nextStartTime = performance.now();\n let completion = await client.text({\n messages,\n tools,\n responseFormat,\n });\n\n const nextEndTime = performance.now();\n\n statelogClient.promptCompletion({\n messages,\n completion,\n model: client.getModel(),\n timeTaken: nextEndTime - nextStartTime,\n });\n\n if (!completion.success) {\n throw new Error(\n `Error getting response from ${model}: ${completion.error}`\n );\n }\n responseMessage = completion.value;\n }\n\n // Add final assistant response to history\n messages.push(assistantMessage(responseMessage.output));\n\n {{#hasResponseFormat}}\n try {\n const result = JSON.parse(responseMessage.output || \"\");\n return result.response;\n } catch (e) {\n return responseMessage.output;\n // console.error(\"Error parsing response for variable '{{{variableName:string}}}':\", e);\n // console.error(\"Full completion response:\", JSON.stringify(completion, null, 2));\n // throw e;\n }\n {{/hasResponseFormat}}\n\n {{^hasResponseFormat}}\n return responseMessage.output;\n {{/hasResponseFormat}}\n}\n";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
variableName: string;
|
|
4
4
|
argsStr: string;
|
|
5
5
|
typeString: string;
|
|
6
6
|
promptCode: string;
|
|
7
7
|
tools: string | boolean | number;
|
|
8
|
+
hasResponseFormat: boolean;
|
|
8
9
|
zodSchema: string;
|
|
9
10
|
functionCalls: string;
|
|
10
11
|
};
|
|
@@ -9,10 +9,15 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
9
9
|
const messages: Message[] = [userMessage(prompt)];
|
|
10
10
|
const tools = {{{tools}}};
|
|
11
11
|
|
|
12
|
+
{{#hasResponseFormat}}
|
|
12
13
|
// Need to make sure this is always an object
|
|
13
14
|
const responseFormat = z.object({
|
|
14
15
|
response: {{{zodSchema:string}}}
|
|
15
16
|
});
|
|
17
|
+
{{/hasResponseFormat}}
|
|
18
|
+
{{^hasResponseFormat}}
|
|
19
|
+
const responseFormat = undefined;
|
|
20
|
+
{{/hasResponseFormat}}
|
|
16
21
|
|
|
17
22
|
let completion = await client.text({
|
|
18
23
|
messages,
|
|
@@ -24,7 +29,7 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
24
29
|
statelogClient.promptCompletion({
|
|
25
30
|
messages,
|
|
26
31
|
completion,
|
|
27
|
-
model,
|
|
32
|
+
model: client.getModel(),
|
|
28
33
|
timeTaken: endTime - startTime,
|
|
29
34
|
});
|
|
30
35
|
|
|
@@ -59,7 +64,7 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
59
64
|
statelogClient.promptCompletion({
|
|
60
65
|
messages,
|
|
61
66
|
completion,
|
|
62
|
-
model,
|
|
67
|
+
model: client.getModel(),
|
|
63
68
|
timeTaken: nextEndTime - nextStartTime,
|
|
64
69
|
});
|
|
65
70
|
|
|
@@ -74,6 +79,7 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
74
79
|
// Add final assistant response to history
|
|
75
80
|
messages.push(assistantMessage(responseMessage.output));
|
|
76
81
|
|
|
82
|
+
{{#hasResponseFormat}}
|
|
77
83
|
try {
|
|
78
84
|
const result = JSON.parse(responseMessage.output || "");
|
|
79
85
|
return result.response;
|
|
@@ -83,6 +89,11 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
83
89
|
// console.error("Full completion response:", JSON.stringify(completion, null, 2));
|
|
84
90
|
// throw e;
|
|
85
91
|
}
|
|
92
|
+
{{/hasResponseFormat}}
|
|
93
|
+
|
|
94
|
+
{{^hasResponseFormat}}
|
|
95
|
+
return responseMessage.output;
|
|
96
|
+
{{/hasResponseFormat}}
|
|
86
97
|
}
|
|
87
98
|
`;
|
|
88
99
|
const render = (args) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AgencyArray, AgencyObject } from "./dataStructures.js";
|
|
2
|
+
import { Literal } from "./literals.js";
|
|
3
|
+
export declare const specialVarNames: readonly ["model"];
|
|
4
|
+
export type SpecialVarName = (typeof specialVarNames)[number];
|
|
5
|
+
export type SpecialVar = {
|
|
6
|
+
type: "specialVar";
|
|
7
|
+
name: SpecialVarName;
|
|
8
|
+
value: Literal | AgencyObject | AgencyArray;
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const specialVarNames = ["model"];
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { ReturnStatement } from "./types/returnStatement.js";
|
|
|
9
9
|
import { UsesTool } from "./types/tools.js";
|
|
10
10
|
import { ImportStatement } from "./types/importStatement.js";
|
|
11
11
|
import { WhileLoop } from "./types/whileLoop.js";
|
|
12
|
+
import { SpecialVar } from "./types/specialVar.js";
|
|
12
13
|
export * from "./types/access.js";
|
|
13
14
|
export * from "./types/dataStructures.js";
|
|
14
15
|
export * from "./types/function.js";
|
|
@@ -29,7 +30,7 @@ export type AgencyComment = {
|
|
|
29
30
|
type: "comment";
|
|
30
31
|
content: string;
|
|
31
32
|
};
|
|
32
|
-
export type AgencyNode = TypeHint | TypeAlias | UsesTool | GraphNodeDefinition | FunctionDefinition | Assignment | Literal | FunctionCall | MatchBlock | ReturnStatement | AccessExpression | AgencyComment | AgencyObject | AgencyArray | ImportStatement | WhileLoop;
|
|
33
|
+
export type AgencyNode = TypeHint | TypeAlias | UsesTool | GraphNodeDefinition | FunctionDefinition | Assignment | Literal | FunctionCall | MatchBlock | ReturnStatement | AccessExpression | AgencyComment | AgencyObject | AgencyArray | ImportStatement | WhileLoop | SpecialVar;
|
|
33
34
|
export type AgencyProgram = {
|
|
34
35
|
type: "agencyProgram";
|
|
35
36
|
nodes: AgencyNode[];
|
package/dist/scripts/agency.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from "child_process";
|
|
3
3
|
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
4
5
|
import { parseAgency } from "../lib/parser.js";
|
|
5
6
|
import { generateGraph } from "../lib/index.js";
|
|
6
7
|
import { generateAgency } from "../lib/backends/agencyGenerator.js";
|
|
@@ -70,17 +71,43 @@ function readFile(inputFile) {
|
|
|
70
71
|
const contents = fs.readFileSync(inputFile, "utf-8");
|
|
71
72
|
return contents;
|
|
72
73
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
function getImports(program) {
|
|
75
|
+
return program.nodes
|
|
76
|
+
.filter((node) => node.type === "importStatement")
|
|
77
|
+
.filter((importNode) => {
|
|
78
|
+
const modulePath = importNode.modulePath.trim().replace(/['"]/g, "");
|
|
79
|
+
return modulePath.includes(".agency");
|
|
80
|
+
})
|
|
81
|
+
.map((node) => node.modulePath.trim().replace(/['"]/g, ""));
|
|
82
|
+
}
|
|
83
|
+
const compiledFiles = new Set();
|
|
84
|
+
function compile(inputFile, _outputFile, verbose = false) {
|
|
85
|
+
// Resolve the absolute path of the input file to avoid duplicates
|
|
86
|
+
const absoluteInputFile = path.resolve(inputFile);
|
|
87
|
+
const outputFile = _outputFile || inputFile.replace(".agency", ".ts");
|
|
88
|
+
// Skip if already compiled
|
|
89
|
+
if (compiledFiles.has(absoluteInputFile)) {
|
|
90
|
+
return outputFile;
|
|
91
|
+
}
|
|
92
|
+
compiledFiles.add(absoluteInputFile);
|
|
76
93
|
const contents = readFile(inputFile);
|
|
77
94
|
const parsedProgram = parse(contents, verbose);
|
|
78
|
-
|
|
95
|
+
const imports = getImports(parsedProgram);
|
|
96
|
+
const inputDir = path.dirname(absoluteInputFile);
|
|
97
|
+
for (const importPath of imports) {
|
|
98
|
+
const absPath = path.resolve(inputDir, importPath);
|
|
99
|
+
compile(absPath, undefined, verbose);
|
|
100
|
+
}
|
|
101
|
+
// Update the import path in the AST to reference the new .ts file
|
|
102
|
+
parsedProgram.nodes.forEach((node) => {
|
|
103
|
+
if (node.type === "importStatement") {
|
|
104
|
+
node.modulePath = node.modulePath.replace(".agency", ".ts");
|
|
105
|
+
}
|
|
106
|
+
});
|
|
79
107
|
const generatedCode = generateGraph(parsedProgram);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return output;
|
|
108
|
+
fs.writeFileSync(outputFile, generatedCode, "utf-8");
|
|
109
|
+
console.log(`Generated ${outputFile} from ${inputFile}`);
|
|
110
|
+
return outputFile;
|
|
84
111
|
}
|
|
85
112
|
function run(inputFile, outputFile, verbose = false) {
|
|
86
113
|
// Compile the file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agency-lang",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "The Agency language",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"nanoid": "^5.1.6",
|
|
45
45
|
"openai": "^6.15.0",
|
|
46
46
|
"piemachine": "^0.0.2",
|
|
47
|
-
"smoltalk": "^0.0.
|
|
47
|
+
"smoltalk": "^0.0.11",
|
|
48
48
|
"statelog-client": "^0.0.31",
|
|
49
49
|
"tarsec": "^0.1.1",
|
|
50
50
|
"typestache": "^0.4.4",
|