agency-lang 0.0.41 → 0.0.43
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/baseGenerator.d.ts +7 -0
- package/dist/lib/backends/baseGenerator.js +18 -0
- package/dist/lib/backends/graphGenerator.js +7 -6
- package/dist/lib/backends/typescriptGenerator.d.ts +6 -4
- package/dist/lib/backends/typescriptGenerator.js +87 -27
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.js +10 -0
- package/dist/lib/templates/backends/graphGenerator/graphNode.d.ts +1 -1
- package/dist/lib/templates/backends/graphGenerator/graphNode.js +24 -1
- package/dist/lib/templates/backends/graphGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/graphGenerator/imports.js +146 -6
- package/dist/lib/templates/backends/graphGenerator/runNodeFunction.d.ts +1 -1
- package/dist/lib/templates/backends/graphGenerator/runNodeFunction.js +3 -3
- package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.d.ts +2 -2
- package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.js +11 -1
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.d.ts +2 -1
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.js +53 -35
- package/dist/lib/templates/backends/typescriptGenerator/toolCall.d.ts +2 -1
- package/dist/lib/templates/backends/typescriptGenerator/toolCall.js +25 -11
- package/dist/lib/utils.js +29 -0
- package/dist/scripts/agency.js +6 -4
- package/package.json +3 -3
|
@@ -12,6 +12,7 @@ import { WhileLoop } from "../types/whileLoop.js";
|
|
|
12
12
|
import { IfElse } from "../types/ifElse.js";
|
|
13
13
|
import { TimeBlock } from "../types/timeBlock.js";
|
|
14
14
|
import { AwaitStatement } from "../types/await.js";
|
|
15
|
+
type Scope = "global" | "function" | "node";
|
|
15
16
|
export declare class BaseGenerator {
|
|
16
17
|
protected typeHints: TypeHintMap;
|
|
17
18
|
protected graphNodes: GraphNodeDefinition[];
|
|
@@ -19,6 +20,7 @@ export declare class BaseGenerator {
|
|
|
19
20
|
protected generatedTypeAliases: string[];
|
|
20
21
|
protected functionScopedVariables: string[];
|
|
21
22
|
protected globalScopedVariables: string[];
|
|
23
|
+
protected functionParameters: string[];
|
|
22
24
|
protected toolsUsed: string[];
|
|
23
25
|
protected typeAliases: Record<string, VariableType>;
|
|
24
26
|
protected functionsUsed: Set<string>;
|
|
@@ -26,6 +28,7 @@ export declare class BaseGenerator {
|
|
|
26
28
|
protected importedNodes: ImportNodeStatement[];
|
|
27
29
|
protected importedTools: ImportToolStatement[];
|
|
28
30
|
protected functionDefinitions: Record<string, FunctionDefinition>;
|
|
31
|
+
protected currentScope: Scope[];
|
|
29
32
|
generate(program: AgencyProgram): {
|
|
30
33
|
output: string;
|
|
31
34
|
};
|
|
@@ -66,4 +69,8 @@ export declare class BaseGenerator {
|
|
|
66
69
|
protected generateImports(): string;
|
|
67
70
|
protected preprocess(): string;
|
|
68
71
|
protected postprocess(): string;
|
|
72
|
+
protected startScope(scope: Scope): void;
|
|
73
|
+
protected endScope(): void;
|
|
74
|
+
protected getScopeVar(): string;
|
|
69
75
|
}
|
|
76
|
+
export {};
|
|
@@ -5,6 +5,7 @@ export class BaseGenerator {
|
|
|
5
5
|
generatedTypeAliases = [];
|
|
6
6
|
functionScopedVariables = [];
|
|
7
7
|
globalScopedVariables = [];
|
|
8
|
+
functionParameters = [];
|
|
8
9
|
// collect tools for a prompt
|
|
9
10
|
toolsUsed = [];
|
|
10
11
|
typeAliases = {};
|
|
@@ -16,6 +17,7 @@ export class BaseGenerator {
|
|
|
16
17
|
// collect function signatures so we can implement named args
|
|
17
18
|
// TODO also save return types, check if used as a tool, return type cannot be null/void/undefined
|
|
18
19
|
functionDefinitions = {};
|
|
20
|
+
currentScope = ["global"];
|
|
19
21
|
generate(program) {
|
|
20
22
|
// Pass 1: Collect all type aliases
|
|
21
23
|
for (const node of program.nodes) {
|
|
@@ -253,4 +255,20 @@ export class BaseGenerator {
|
|
|
253
255
|
postprocess() {
|
|
254
256
|
return "";
|
|
255
257
|
}
|
|
258
|
+
startScope(scope) {
|
|
259
|
+
this.currentScope.push(scope);
|
|
260
|
+
}
|
|
261
|
+
endScope() {
|
|
262
|
+
this.currentScope.pop();
|
|
263
|
+
}
|
|
264
|
+
getScopeVar() {
|
|
265
|
+
const currentScope = this.currentScope[this.currentScope.length - 1];
|
|
266
|
+
switch (currentScope) {
|
|
267
|
+
case "global":
|
|
268
|
+
return "__stateStack.globals";
|
|
269
|
+
case "function":
|
|
270
|
+
case "node":
|
|
271
|
+
return "__stack.locals";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
256
274
|
}
|
|
@@ -39,6 +39,7 @@ export class GraphGenerator extends TypeScriptGenerator {
|
|
|
39
39
|
this.graphNodes.push(node);
|
|
40
40
|
}
|
|
41
41
|
processGraphNode(node) {
|
|
42
|
+
this.startScope("node");
|
|
42
43
|
const { nodeName, body, parameters } = node;
|
|
43
44
|
/* if (parameters.length > 1) {
|
|
44
45
|
throw new Error(
|
|
@@ -47,22 +48,22 @@ export class GraphGenerator extends TypeScriptGenerator {
|
|
|
47
48
|
} */
|
|
48
49
|
this.adjacentNodes[nodeName] = [];
|
|
49
50
|
this.currentAdjacentNodes = [];
|
|
50
|
-
this.
|
|
51
|
+
this.functionParameters = [];
|
|
51
52
|
this.isInsideGraphNode = true;
|
|
52
53
|
for (const param of parameters) {
|
|
53
|
-
this.
|
|
54
|
+
this.functionParameters.push(param.name);
|
|
54
55
|
}
|
|
55
|
-
const bodyCode = [];
|
|
56
56
|
for (const stmt of body) {
|
|
57
57
|
if (stmt.type === "functionCall" && this.isGraphNode(stmt.functionName)) {
|
|
58
58
|
throw new Error(`Call to graph node '${stmt.functionName}' inside graph node '${nodeName}' was not returned. All calls to graph nodes must be returned, eg (return ${stmt.functionName}(...)).`);
|
|
59
59
|
}
|
|
60
|
-
bodyCode.push(this.processNode(stmt));
|
|
61
60
|
}
|
|
62
|
-
|
|
61
|
+
const bodyCode = this.processBodyAsParts(body);
|
|
62
|
+
this.functionParameters = [];
|
|
63
63
|
this.adjacentNodes[nodeName] = [...this.currentAdjacentNodes];
|
|
64
64
|
this.isInsideGraphNode = false;
|
|
65
|
-
|
|
65
|
+
this.endScope();
|
|
66
|
+
const paramNames = "[" + parameters.map((p) => `"${p.name}"`).join(", ") + "]";
|
|
66
67
|
return renderGraphNode.default({
|
|
67
68
|
name: nodeName,
|
|
68
69
|
/* returnType: node.returnType
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { AgencyComment, AgencyProgram, Assignment, Literal, PromptLiteral, PromptSegment, TypeAlias, TypeHint, TypeHintMap, VariableType } from "../types.js";
|
|
1
|
+
import { AgencyComment, AgencyNode, AgencyProgram, Assignment, Literal, PromptLiteral, PromptSegment, TypeAlias, TypeHint, TypeHintMap, VariableType } from "../types.js";
|
|
2
|
+
import { AwaitStatement } from "../types/await.js";
|
|
2
3
|
import { SpecialVar } from "../types/specialVar.js";
|
|
4
|
+
import { TimeBlock } from "../types/timeBlock.js";
|
|
3
5
|
import { AccessExpression, DotFunctionCall, DotProperty, IndexAccess } from "../types/access.js";
|
|
4
6
|
import { AgencyArray, AgencyObject } from "../types/dataStructures.js";
|
|
5
7
|
import { FunctionCall, FunctionDefinition } from "../types/function.js";
|
|
8
|
+
import { IfElse } from "../types/ifElse.js";
|
|
6
9
|
import { ImportNodeStatement, ImportStatement, ImportToolStatement } from "../types/importStatement.js";
|
|
7
10
|
import { MatchBlock } from "../types/matchBlock.js";
|
|
8
11
|
import { ReturnStatement } from "../types/returnStatement.js";
|
|
9
12
|
import { UsesTool } from "../types/tools.js";
|
|
10
13
|
import { WhileLoop } from "../types/whileLoop.js";
|
|
11
|
-
import { IfElse } from "../types/ifElse.js";
|
|
12
14
|
import { BaseGenerator } from "./baseGenerator.js";
|
|
13
|
-
import { TimeBlock } from "../types/timeBlock.js";
|
|
14
|
-
import { AwaitStatement } from "../types/await.js";
|
|
15
15
|
export declare class TypeScriptGenerator extends BaseGenerator {
|
|
16
16
|
constructor();
|
|
17
17
|
protected generateBuiltins(): string;
|
|
@@ -43,6 +43,7 @@ export declare class TypeScriptGenerator extends BaseGenerator {
|
|
|
43
43
|
* Generates TypeScript expression for a function call (without semicolon)
|
|
44
44
|
*/
|
|
45
45
|
protected generateFunctionCallExpression(node: FunctionCall): string;
|
|
46
|
+
protected generateScopedVariableName(variableName: string): string;
|
|
46
47
|
protected generateLiteral(literal: Literal): string;
|
|
47
48
|
protected generateImports(): string;
|
|
48
49
|
buildPromptString(segments: PromptSegment[], typeHints: TypeHintMap): string;
|
|
@@ -64,5 +65,6 @@ export declare class TypeScriptGenerator extends BaseGenerator {
|
|
|
64
65
|
protected processSpecialVar(node: SpecialVar): string;
|
|
65
66
|
protected processTimeBlock(node: TimeBlock, timingVarName: string): string;
|
|
66
67
|
protected processAwaitStatement(node: AwaitStatement): string;
|
|
68
|
+
protected processBodyAsParts(body: AgencyNode[]): string[];
|
|
67
69
|
}
|
|
68
70
|
export declare function generateTypeScript(program: AgencyProgram): string;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import * as renderSpecialVar from "../templates/backends/graphGenerator/specialVar.js";
|
|
2
|
+
import * as renderTime from "../templates/backends/typescriptGenerator/builtinFunctions/time.js";
|
|
2
3
|
import * as builtinTools from "../templates/backends/typescriptGenerator/builtinTools.js";
|
|
3
4
|
import * as renderFunctionDefinition from "../templates/backends/typescriptGenerator/functionDefinition.js";
|
|
4
5
|
import * as renderImports from "../templates/backends/typescriptGenerator/imports.js";
|
|
5
6
|
import * as promptFunction from "../templates/backends/typescriptGenerator/promptFunction.js";
|
|
6
7
|
import * as renderTool from "../templates/backends/typescriptGenerator/tool.js";
|
|
7
|
-
import * as renderTime from "../templates/backends/typescriptGenerator/builtinFunctions/time.js";
|
|
8
8
|
import * as renderToolCall from "../templates/backends/typescriptGenerator/toolCall.js";
|
|
9
|
-
import { escape, uniq
|
|
9
|
+
import { escape, uniq } from "../utils.js";
|
|
10
10
|
import { BaseGenerator } from "./baseGenerator.js";
|
|
11
11
|
import { generateBuiltinHelpers, mapFunctionName, } from "./typescriptGenerator/builtins.js";
|
|
12
12
|
import { variableTypeToString } from "./typescriptGenerator/typeToString.js";
|
|
13
13
|
import { DEFAULT_SCHEMA, mapTypeToZodSchema, } from "./typescriptGenerator/typeToZodSchema.js";
|
|
14
|
+
import { TYPES_THAT_DONT_TRIGGER_NEW_PART } from "../config.js";
|
|
14
15
|
export class TypeScriptGenerator extends BaseGenerator {
|
|
15
16
|
constructor() {
|
|
16
17
|
super();
|
|
@@ -58,7 +59,11 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
58
59
|
}
|
|
59
60
|
processReturnStatement(node) {
|
|
60
61
|
const returnCode = this.processNode(node.value);
|
|
61
|
-
|
|
62
|
+
if (node.value.type === "functionCall" &&
|
|
63
|
+
node.value.functionName === "interrupt") {
|
|
64
|
+
return `__stack.step++;\nreturn ${returnCode}\n`;
|
|
65
|
+
}
|
|
66
|
+
return `__stateStack.pop();\nreturn ${returnCode}\n`;
|
|
62
67
|
}
|
|
63
68
|
processAccessExpression(node) {
|
|
64
69
|
switch (node.expression.type) {
|
|
@@ -140,7 +145,8 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
140
145
|
}
|
|
141
146
|
// Direct assignment for other literal types
|
|
142
147
|
const code = this.processNode(value);
|
|
143
|
-
return (
|
|
148
|
+
return (`${this.getScopeVar()}.${variableName}${typeAnnotation} = await ${code.trim()};` +
|
|
149
|
+
"\n");
|
|
144
150
|
}
|
|
145
151
|
else if (value.type === "timeBlock") {
|
|
146
152
|
const timingVarName = variableName;
|
|
@@ -150,7 +156,8 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
150
156
|
else {
|
|
151
157
|
// Direct assignment for other literal types
|
|
152
158
|
const code = this.processNode(value);
|
|
153
|
-
return
|
|
159
|
+
return (`${this.getScopeVar()}.${variableName}${typeAnnotation} = ${code.trim()};` +
|
|
160
|
+
"\n");
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
/*
|
|
@@ -180,10 +187,12 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
180
187
|
prompt: node,
|
|
181
188
|
});
|
|
182
189
|
//this.generatedStatements.push(functionCode);
|
|
183
|
-
const argsStr = [...interpolatedVars, "__messages"].join(", ");
|
|
190
|
+
//const argsStr = [...interpolatedVars, "__messages"].join(", ");
|
|
184
191
|
// Generate the function call
|
|
185
|
-
return
|
|
186
|
-
|
|
192
|
+
return functionCode; /* (
|
|
193
|
+
`${functionCode}\nconst __self.${variableName} = await _${variableName}(${argsStr});` +
|
|
194
|
+
"\n"
|
|
195
|
+
); */
|
|
187
196
|
}
|
|
188
197
|
processTool(node) {
|
|
189
198
|
const { functionName, body, parameters } = node;
|
|
@@ -221,17 +230,19 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
221
230
|
* Process a function definition node
|
|
222
231
|
*/
|
|
223
232
|
processFunctionDefinition(node) {
|
|
233
|
+
this.startScope("function");
|
|
224
234
|
const { functionName, body, parameters } = node;
|
|
235
|
+
const args = parameters.map((p) => p.name);
|
|
225
236
|
this.functionScopedVariables = [...parameters.map((p) => p.name)];
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
bodyCode.push(this.processNode(stmt));
|
|
229
|
-
}
|
|
237
|
+
this.functionParameters = args;
|
|
238
|
+
const bodyCode = this.processBodyAsParts(body);
|
|
230
239
|
this.functionScopedVariables = [];
|
|
231
|
-
|
|
240
|
+
this.functionParameters = [];
|
|
241
|
+
this.endScope();
|
|
242
|
+
const argsStr = args.map((arg) => `"${arg}"`).join(", ") || "";
|
|
232
243
|
return renderFunctionDefinition.default({
|
|
233
244
|
functionName,
|
|
234
|
-
|
|
245
|
+
argsStr,
|
|
235
246
|
returnType: node.returnType
|
|
236
247
|
? variableTypeToString(node.returnType, this.typeAliases)
|
|
237
248
|
: "any",
|
|
@@ -279,22 +290,32 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
279
290
|
}
|
|
280
291
|
});
|
|
281
292
|
let argsString = "";
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
argsString =
|
|
288
|
-
return `${functionName}(
|
|
293
|
+
const isImportedTool = this.importedTools
|
|
294
|
+
.map((node) => node.importedTools)
|
|
295
|
+
.flat()
|
|
296
|
+
.includes(node.functionName);
|
|
297
|
+
if (this.functionDefinitions[node.functionName] || isImportedTool) {
|
|
298
|
+
argsString = parts.join(", ");
|
|
299
|
+
return `${functionName}([${argsString}])`;
|
|
289
300
|
}
|
|
290
301
|
else {
|
|
291
|
-
// must be a builtin function or imported function
|
|
292
|
-
// as we don't have the signature info
|
|
293
|
-
// in that case don't do named parameters
|
|
302
|
+
// must be a builtin function or imported function
|
|
294
303
|
argsString = parts.join(", ");
|
|
295
304
|
return `${functionName}(${argsString})`;
|
|
296
305
|
}
|
|
297
306
|
}
|
|
307
|
+
generateScopedVariableName(variableName) {
|
|
308
|
+
if (this.functionParameters.includes(variableName)) {
|
|
309
|
+
return `__stack.args.${variableName}`;
|
|
310
|
+
}
|
|
311
|
+
if (this.functionScopedVariables.includes(variableName)) {
|
|
312
|
+
return `__stack.locals.${variableName}`;
|
|
313
|
+
}
|
|
314
|
+
else if (this.globalScopedVariables.includes(variableName)) {
|
|
315
|
+
return `__stateStack.globals.${variableName}`;
|
|
316
|
+
}
|
|
317
|
+
return variableName;
|
|
318
|
+
}
|
|
298
319
|
generateLiteral(literal) {
|
|
299
320
|
switch (literal.type) {
|
|
300
321
|
case "number":
|
|
@@ -304,7 +325,7 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
304
325
|
case "multiLineString":
|
|
305
326
|
return this.generateStringLiteral(literal.segments);
|
|
306
327
|
case "variableName":
|
|
307
|
-
return literal.value;
|
|
328
|
+
return this.generateScopedVariableName(literal.value);
|
|
308
329
|
case "prompt":
|
|
309
330
|
//return this.processPromptLiteral("asd", literal).trim();
|
|
310
331
|
// Reconstruct text for comment from segments
|
|
@@ -350,7 +371,7 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
350
371
|
}
|
|
351
372
|
else {
|
|
352
373
|
// Interpolation segment
|
|
353
|
-
stringParts.push("${" + segment.variableName + "}");
|
|
374
|
+
stringParts.push("${" + this.generateScopedVariableName(segment.variableName) + "}");
|
|
354
375
|
}
|
|
355
376
|
}
|
|
356
377
|
return "`" + stringParts.join("") + "`";
|
|
@@ -371,7 +392,7 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
371
392
|
// Build prompt construction code
|
|
372
393
|
const promptCode = this.buildPromptString(prompt.segments, this.typeHints);
|
|
373
394
|
const parts = functionArgs.map((arg) => `${arg.replace(".", "_")}: ${variableTypeToString(this.typeHints[arg] || { type: "primitiveType", value: "string" }, this.typeAliases)}`);
|
|
374
|
-
parts.push("
|
|
395
|
+
parts.push("__metadata?: Record<string, any>");
|
|
375
396
|
const argsStr = parts.join(", ");
|
|
376
397
|
const _tools = this.toolsUsed
|
|
377
398
|
.map((toolName) => `__${toolName}Tool`)
|
|
@@ -379,16 +400,33 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
379
400
|
const tools = _tools.length > 0 ? `[${_tools}]` : "undefined";
|
|
380
401
|
const functionCalls = this.toolsUsed
|
|
381
402
|
.map((toolName) => {
|
|
403
|
+
const func = this.functionDefinitions[toolName];
|
|
404
|
+
if (!func) {
|
|
405
|
+
throw new Error(`Tool '${toolName}' is being used but no function definition found for it. Make sure to define a function for this tool.`);
|
|
406
|
+
}
|
|
407
|
+
const paramsStr = func.parameters
|
|
408
|
+
.map((param, index) => {
|
|
409
|
+
return `args["${param.name}"]`;
|
|
410
|
+
})
|
|
411
|
+
.join(", ");
|
|
382
412
|
return renderToolCall.default({
|
|
383
413
|
name: toolName,
|
|
414
|
+
paramsStr,
|
|
384
415
|
});
|
|
385
416
|
})
|
|
386
417
|
.join("\n");
|
|
387
418
|
const clientConfig = prompt.config ? this.processNode(prompt.config) : "{}";
|
|
419
|
+
const metadataObj = `{
|
|
420
|
+
messages: __messages,
|
|
421
|
+
interruptResponse: __interruptResponse,
|
|
422
|
+
toolCall: __toolCall,
|
|
423
|
+
}`;
|
|
388
424
|
this.toolsUsed = []; // reset after use
|
|
425
|
+
const scopedFunctionArgs = functionArgs.map((arg) => this.generateScopedVariableName(arg));
|
|
389
426
|
return promptFunction.default({
|
|
390
427
|
variableName,
|
|
391
428
|
argsStr,
|
|
429
|
+
funcCallParams: [...scopedFunctionArgs, metadataObj].join(", "),
|
|
392
430
|
typeString,
|
|
393
431
|
promptCode,
|
|
394
432
|
hasResponseFormat: zodSchema !== DEFAULT_SCHEMA,
|
|
@@ -464,6 +502,28 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
464
502
|
const code = this.processNode(node.expression);
|
|
465
503
|
return `await ${code}`;
|
|
466
504
|
}
|
|
505
|
+
processBodyAsParts(body) {
|
|
506
|
+
const parts = [[]];
|
|
507
|
+
for (const stmt of body) {
|
|
508
|
+
if (!TYPES_THAT_DONT_TRIGGER_NEW_PART.includes(stmt.type)) {
|
|
509
|
+
parts.push([]);
|
|
510
|
+
}
|
|
511
|
+
parts[parts.length - 1].push(this.processNode(stmt));
|
|
512
|
+
}
|
|
513
|
+
const bodyCode = [];
|
|
514
|
+
let partNum = 0;
|
|
515
|
+
for (const part of parts) {
|
|
516
|
+
const partCode = `
|
|
517
|
+
if (__step <= ${partNum}) {
|
|
518
|
+
${part.join("").trimEnd()}
|
|
519
|
+
__stack.step++;
|
|
520
|
+
}
|
|
521
|
+
`;
|
|
522
|
+
bodyCode.push(partCode);
|
|
523
|
+
partNum++;
|
|
524
|
+
}
|
|
525
|
+
return bodyCode;
|
|
526
|
+
}
|
|
467
527
|
}
|
|
468
528
|
export function generateTypeScript(program) {
|
|
469
529
|
const generator = new TypeScriptGenerator();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "\ngraph.node(\"{{{name}}}\", async (state): Promise<any> => {\n const __messages: Message[] = state.messages || [];\n const __graph = state.__metadata?.graph || graph;\n const statelogClient = state.__metadata?.statelogClient || __statelogClient;\n {{#hasParam}}\n const {{{paramNames}}}
|
|
1
|
+
export declare const template = "\ngraph.node(\"{{{name}}}\", async (state): Promise<any> => {\n const __messages: Message[] = state.messages || [];\n const __graph = state.__metadata?.graph || graph;\n const statelogClient = state.__metadata?.statelogClient || __statelogClient;\n if (state.__metadata?.__stateStack) {\n __stateStack = state.__metadata.__stateStack;\n }\n const __stack = __stateStack.getNewState();\n const __step = __stack.step;\n\n const __self: Record<string, any> = __stack.locals;\n\n const __interruptResponse: InterruptResponseType | undefined = state.__metadata?.interruptResponse;\n const __toolCall: Record<string, any>|undefined = __stateStack.other?.toolCall;\n\n if (state.__metadata?.state?.global) {\n __global = state.__metadata.state.global;\n }\n\n {{#hasParam}}\n \n const __params = {{{paramNames}}};\n if (state.data !== \"<from-stack>\") {\n (state.data).forEach((item, index) => {\n __stack.args[__params[index]] = item;\n });\n }\n {{/hasParam}}\n {{{body}}}\n \n // this is just here to have a default return value from a node if the user doesn't specify one\n return { ...state, data: undefined };\n});\n";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
name: string | boolean | number;
|
|
4
4
|
hasParam: boolean;
|
|
@@ -7,10 +7,33 @@ graph.node("{{{name}}}", async (state): Promise<any> => {
|
|
|
7
7
|
const __messages: Message[] = state.messages || [];
|
|
8
8
|
const __graph = state.__metadata?.graph || graph;
|
|
9
9
|
const statelogClient = state.__metadata?.statelogClient || __statelogClient;
|
|
10
|
+
if (state.__metadata?.__stateStack) {
|
|
11
|
+
__stateStack = state.__metadata.__stateStack;
|
|
12
|
+
}
|
|
13
|
+
const __stack = __stateStack.getNewState();
|
|
14
|
+
const __step = __stack.step;
|
|
15
|
+
|
|
16
|
+
const __self: Record<string, any> = __stack.locals;
|
|
17
|
+
|
|
18
|
+
const __interruptResponse: InterruptResponseType | undefined = state.__metadata?.interruptResponse;
|
|
19
|
+
const __toolCall: Record<string, any>|undefined = __stateStack.other?.toolCall;
|
|
20
|
+
|
|
21
|
+
if (state.__metadata?.state?.global) {
|
|
22
|
+
__global = state.__metadata.state.global;
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
{{#hasParam}}
|
|
11
|
-
|
|
26
|
+
|
|
27
|
+
const __params = {{{paramNames}}};
|
|
28
|
+
if (state.data !== "<from-stack>") {
|
|
29
|
+
(state.data).forEach((item, index) => {
|
|
30
|
+
__stack.args[__params[index]] = item;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
12
33
|
{{/hasParam}}
|
|
13
34
|
{{{body}}}
|
|
35
|
+
|
|
36
|
+
// this is just here to have a default return value from a node if the user doesn't specify one
|
|
14
37
|
return { ...state, data: undefined };
|
|
15
38
|
});
|
|
16
39
|
`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "import { 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, toolMessage } 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: ModelName = \"gpt-4o-mini\";\n\
|
|
1
|
+
export declare const template = "import { 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, toolMessage, messageFromJSON } from \"smoltalk\";\nimport type { Message } 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: ModelName = \"gpt-4o-mini\";\n\nconst getClientWithConfig = (config = {}) => {\n const defaultConfig = {\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n model: __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: false,\n },\n statelog: statelogConfig,\n};\n\nconst graph = new PieMachine<State>(graphConfig);\n\n// builtins\n\nconst not = (val: any): boolean => !val;\nconst eq = (a: any, b: any): boolean => a === b;\nconst neq = (a: any, b: any): boolean => a !== b;\nconst lt = (a: any, b: any): boolean => a < b;\nconst lte = (a: any, b: any): boolean => a <= b;\nconst gt = (a: any, b: any): boolean => a > b;\nconst gte = (a: any, b: any): boolean => a >= b;\nconst and = (a: any, b: any): boolean => a && b;\nconst or = (a: any, b: any): boolean => a || b;\nconst head = <T>(arr: T[]): T | undefined => arr[0];\nconst tail = <T>(arr: T[]): T[] => arr.slice(1);\nconst empty = <T>(arr: T[]): boolean => arr.length === 0;\n\n// interrupts\n\nexport type Interrupt<T> = {\n type: \"interrupt\";\n data: T;\n __state?: PackagedState;\n};\n\nexport function interrupt<T>(data: T): Interrupt<T> {\n return {\n type: \"interrupt\",\n data,\n };\n}\n\nexport function isInterrupt<T>(obj: any): obj is Interrupt<T> {\n return obj && obj.type === \"interrupt\";\n}\n\nfunction printJSON(obj: any) {\n console.log(JSON.stringify(obj, null, 2));\n}\n\nexport type InterruptResponseType = InterruptResponseApprove | InterruptResponseReject | InterruptResponseModify;\nexport type InterruptResponseApprove = {\n type: \"approve\";\n};\nexport type InterruptResponseReject = {\n type: \"reject\";\n};\nexport type InterruptResponseModify = {\n type: \"modify\";\n newArguments: Record<string, any>;\n};\n\n\nexport async function respondToInterrupt(_interrupt: Interrupt, _interruptResponse: InterruptResponseType) {\n const interrupt = structuredClone(_interrupt);\n const interruptResponse = structuredClone(_interruptResponse);\n __stateStack = StateStack.fromJSON(interrupt.__state || {});\n __stateStack.setMode(\"deserialize\");\n const messages = (__stateStack.other.messages || []).map((json: any) => {\n return messageFromJSON(json);\n });\n\n const nodesTraversed = __stateStack.other.nodesTraversed || [];\n const nodeName = nodesTraversed[nodesTraversed.length - 1];\n const result = await graph.run(nodeName, {\n messages: messages,\n __metadata: {\n graph: graph,\n statelogClient: __statelogClient,\n interruptResponse: interruptResponse,\n state: interrupt.__state,\n __stateStack: __stateStack,\n },\n data: \"<from-stack>\"\n });\n //console.log(`Result of graph.run(\"${nodeName}\"):`, JSON.stringify(result, null, 2));\n return result.data;\n}\n\n\nclass PackagedState {\n public messages?: Message[];\n public nodesTraversed?: string[];\n public toolCall?: Record<string, any>;\n public step?: number;\n public self?: Record<string, any>;\n public global?: Record<string, any>;\n public args?: any;\n constructor(_state: Record<string, any>, args?: any) {\n const state = structuredClone(_state);\n this.messages = state.messages;\n this.nodesTraversed = state.graph?.getNodesTraversed();\n this.toolCall = state.toolCall;\n this.step = state.part;\n this.self = state.self;\n this.global = state.global;\n this.args = state.args;\n }\n\n toJSON() {\n return {\n messages: this.messages,\n nodesTraversed: this.nodesTraversed,\n toolCall: this.toolCall,\n step: this.step,\n self: this.self,\n global: this.global,\n args: this.args,\n };\n }\n\n nextStep() {\n this.step ||= 0;\n this.step += 1;\n }\n}\n\n\nclass StateStack {\n public stack: StateItem[] = [];\n public mode: \"serialize\" | \"deserialize\" = \"serialize\";\n public globals: Record<string, any> = {};\n public other: Record<string, any> = {};\n\n constructor(stack: StateItem[] = [], mode: \"serialize\" | \"deserialize\" = \"serialize\") {\n this.stack = stack;\n this.mode = mode;\n }\n\n getNewState(): StateItem | null {\n if (this.stack.length === 0 && this.mode !== \"serialize\") {\n console.log(\"Forcing mode to serialize, nothing left to deserialize\");\n this.mode = \"serialize\";\n }\n if (this.mode === \"serialize\") {\n const newState: StateItem = {\n args: {},\n locals: {},\n step: 0,\n };\n this.stack.push(newState);\n return newState;\n } else if (this.mode === \"deserialize\") {\n const item = this.stack.shift();\n this.stack.push(item);\n return item;\n }\n return null;\n }\n\n setMode(mode: \"serialize\" | \"deserialize\") {\n this.mode = mode;\n }\n\n pop(): StateItem | undefined {\n return this.stack.pop();\n }\n\n toJSON() {\n return structuredClone({\n stack: this.stack,\n globals: this.globals,\n other: this.other,\n mode: this.mode,\n });\n }\n\n static fromJSON(json: any): StateStack {\n const stateStack = new StateStack([], \"serialize\");\n stateStack.stack = json.stack || [];\n stateStack.globals = json.globals || {};\n stateStack.other = json.other || {};\n stateStack.mode = json.mode || \"serialize\";\n return stateStack;\n }\n}\n\nlet __stateStack = new StateStack();";
|
|
2
2
|
export type TemplateType = {};
|
|
3
3
|
declare const render: (args: TemplateType) => string;
|
|
4
4
|
export default render;
|
|
@@ -8,7 +8,8 @@ import fs from "fs";
|
|
|
8
8
|
import { PieMachine, goToNode } from "piemachine";
|
|
9
9
|
import { StatelogClient } from "statelog-client";
|
|
10
10
|
import { nanoid } from "nanoid";
|
|
11
|
-
import { assistantMessage, getClient, userMessage, toolMessage } from "smoltalk";
|
|
11
|
+
import { assistantMessage, getClient, userMessage, toolMessage, messageFromJSON } from "smoltalk";
|
|
12
|
+
import type { Message } from "smoltalk";
|
|
12
13
|
|
|
13
14
|
const statelogHost = "https://statelog.adit.io";
|
|
14
15
|
const traceId = nanoid();
|
|
@@ -22,7 +23,6 @@ const statelogConfig = {
|
|
|
22
23
|
const __statelogClient = new StatelogClient(statelogConfig);
|
|
23
24
|
const __model: ModelName = "gpt-4o-mini";
|
|
24
25
|
|
|
25
|
-
|
|
26
26
|
const getClientWithConfig = (config = {}) => {
|
|
27
27
|
const defaultConfig = {
|
|
28
28
|
openAiApiKey: process.env.OPENAI_API_KEY || "",
|
|
@@ -69,25 +69,165 @@ const empty = <T>(arr: T[]): boolean => arr.length === 0;
|
|
|
69
69
|
|
|
70
70
|
// interrupts
|
|
71
71
|
|
|
72
|
-
type Interrupt<T> = {
|
|
72
|
+
export type Interrupt<T> = {
|
|
73
73
|
type: "interrupt";
|
|
74
74
|
data: T;
|
|
75
|
+
__state?: PackagedState;
|
|
75
76
|
};
|
|
76
77
|
|
|
77
|
-
function interrupt<T>(data: T): Interrupt<T> {
|
|
78
|
+
export function interrupt<T>(data: T): Interrupt<T> {
|
|
78
79
|
return {
|
|
79
80
|
type: "interrupt",
|
|
80
81
|
data,
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
function isInterrupt<T>(obj: any): obj is Interrupt<T> {
|
|
85
|
+
export function isInterrupt<T>(obj: any): obj is Interrupt<T> {
|
|
85
86
|
return obj && obj.type === "interrupt";
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
function printJSON(obj: any) {
|
|
89
90
|
console.log(JSON.stringify(obj, null, 2));
|
|
90
|
-
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type InterruptResponseType = InterruptResponseApprove | InterruptResponseReject | InterruptResponseModify;
|
|
94
|
+
export type InterruptResponseApprove = {
|
|
95
|
+
type: "approve";
|
|
96
|
+
};
|
|
97
|
+
export type InterruptResponseReject = {
|
|
98
|
+
type: "reject";
|
|
99
|
+
};
|
|
100
|
+
export type InterruptResponseModify = {
|
|
101
|
+
type: "modify";
|
|
102
|
+
newArguments: Record<string, any>;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
export async function respondToInterrupt(_interrupt: Interrupt, _interruptResponse: InterruptResponseType) {
|
|
107
|
+
const interrupt = structuredClone(_interrupt);
|
|
108
|
+
const interruptResponse = structuredClone(_interruptResponse);
|
|
109
|
+
__stateStack = StateStack.fromJSON(interrupt.__state || {});
|
|
110
|
+
__stateStack.setMode("deserialize");
|
|
111
|
+
const messages = (__stateStack.other.messages || []).map((json: any) => {
|
|
112
|
+
return messageFromJSON(json);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const nodesTraversed = __stateStack.other.nodesTraversed || [];
|
|
116
|
+
const nodeName = nodesTraversed[nodesTraversed.length - 1];
|
|
117
|
+
const result = await graph.run(nodeName, {
|
|
118
|
+
messages: messages,
|
|
119
|
+
__metadata: {
|
|
120
|
+
graph: graph,
|
|
121
|
+
statelogClient: __statelogClient,
|
|
122
|
+
interruptResponse: interruptResponse,
|
|
123
|
+
state: interrupt.__state,
|
|
124
|
+
__stateStack: __stateStack,
|
|
125
|
+
},
|
|
126
|
+
data: "<from-stack>"
|
|
127
|
+
});
|
|
128
|
+
//console.log(\`Result of graph.run("\${nodeName}"):\`, JSON.stringify(result, null, 2));
|
|
129
|
+
return result.data;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class PackagedState {
|
|
134
|
+
public messages?: Message[];
|
|
135
|
+
public nodesTraversed?: string[];
|
|
136
|
+
public toolCall?: Record<string, any>;
|
|
137
|
+
public step?: number;
|
|
138
|
+
public self?: Record<string, any>;
|
|
139
|
+
public global?: Record<string, any>;
|
|
140
|
+
public args?: any;
|
|
141
|
+
constructor(_state: Record<string, any>, args?: any) {
|
|
142
|
+
const state = structuredClone(_state);
|
|
143
|
+
this.messages = state.messages;
|
|
144
|
+
this.nodesTraversed = state.graph?.getNodesTraversed();
|
|
145
|
+
this.toolCall = state.toolCall;
|
|
146
|
+
this.step = state.part;
|
|
147
|
+
this.self = state.self;
|
|
148
|
+
this.global = state.global;
|
|
149
|
+
this.args = state.args;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
toJSON() {
|
|
153
|
+
return {
|
|
154
|
+
messages: this.messages,
|
|
155
|
+
nodesTraversed: this.nodesTraversed,
|
|
156
|
+
toolCall: this.toolCall,
|
|
157
|
+
step: this.step,
|
|
158
|
+
self: this.self,
|
|
159
|
+
global: this.global,
|
|
160
|
+
args: this.args,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
nextStep() {
|
|
165
|
+
this.step ||= 0;
|
|
166
|
+
this.step += 1;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class StateStack {
|
|
172
|
+
public stack: StateItem[] = [];
|
|
173
|
+
public mode: "serialize" | "deserialize" = "serialize";
|
|
174
|
+
public globals: Record<string, any> = {};
|
|
175
|
+
public other: Record<string, any> = {};
|
|
176
|
+
|
|
177
|
+
constructor(stack: StateItem[] = [], mode: "serialize" | "deserialize" = "serialize") {
|
|
178
|
+
this.stack = stack;
|
|
179
|
+
this.mode = mode;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
getNewState(): StateItem | null {
|
|
183
|
+
if (this.stack.length === 0 && this.mode !== "serialize") {
|
|
184
|
+
console.log("Forcing mode to serialize, nothing left to deserialize");
|
|
185
|
+
this.mode = "serialize";
|
|
186
|
+
}
|
|
187
|
+
if (this.mode === "serialize") {
|
|
188
|
+
const newState: StateItem = {
|
|
189
|
+
args: {},
|
|
190
|
+
locals: {},
|
|
191
|
+
step: 0,
|
|
192
|
+
};
|
|
193
|
+
this.stack.push(newState);
|
|
194
|
+
return newState;
|
|
195
|
+
} else if (this.mode === "deserialize") {
|
|
196
|
+
const item = this.stack.shift();
|
|
197
|
+
this.stack.push(item);
|
|
198
|
+
return item;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
setMode(mode: "serialize" | "deserialize") {
|
|
204
|
+
this.mode = mode;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
pop(): StateItem | undefined {
|
|
208
|
+
return this.stack.pop();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
toJSON() {
|
|
212
|
+
return structuredClone({
|
|
213
|
+
stack: this.stack,
|
|
214
|
+
globals: this.globals,
|
|
215
|
+
other: this.other,
|
|
216
|
+
mode: this.mode,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static fromJSON(json: any): StateStack {
|
|
221
|
+
const stateStack = new StateStack([], "serialize");
|
|
222
|
+
stateStack.stack = json.stack || [];
|
|
223
|
+
stateStack.globals = json.globals || {};
|
|
224
|
+
stateStack.other = json.other || {};
|
|
225
|
+
stateStack.mode = json.mode || "serialize";
|
|
226
|
+
return stateStack;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let __stateStack = new StateStack();`;
|
|
91
231
|
const render = (args) => {
|
|
92
232
|
return apply(template, args);
|
|
93
233
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "{{#hasArgs}}\nexport async function {{{nodeName:string}}}({{{argsStr:string}}}, { messages =
|
|
1
|
+
export declare const template = "{{#hasArgs}}\nexport async function {{{nodeName:string}}}({{{argsStr:string}}}, { messages } = {}): Promise<{{{returnType:string}}}> {\n{{/hasArgs}}\n{{^hasArgs}}\nexport async function {{{nodeName:string}}}({ messages } = {}): Promise<{{{returnType:string}}}> {\n{{/hasArgs}}\n const data = [ {{{argsStr:string}}} ];\n const result = await graph.run(\"{{{nodeName:string}}}\", { messages: messages || [], data });\n return result.data;\n}\n";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
hasArgs: boolean;
|
|
4
4
|
nodeName: string;
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
// Any manual changes will be lost.
|
|
4
4
|
import { apply } from "typestache";
|
|
5
5
|
export const template = `{{#hasArgs}}
|
|
6
|
-
export async function {{{nodeName:string}}}({{{argsStr:string}}}, { messages =
|
|
6
|
+
export async function {{{nodeName:string}}}({{{argsStr:string}}}, { messages } = {}): Promise<{{{returnType:string}}}> {
|
|
7
7
|
{{/hasArgs}}
|
|
8
8
|
{{^hasArgs}}
|
|
9
|
-
export async function {{{nodeName:string}}}({ messages =
|
|
9
|
+
export async function {{{nodeName:string}}}({ messages } = {}): Promise<{{{returnType:string}}}> {
|
|
10
10
|
{{/hasArgs}}
|
|
11
11
|
const data = [ {{{argsStr:string}}} ];
|
|
12
|
-
const result = await graph.run("{{{nodeName:string}}}", { messages, data });
|
|
12
|
+
const result = await graph.run("{{{nodeName:string}}}", { messages: messages || [], data });
|
|
13
13
|
return result.data;
|
|
14
14
|
}
|
|
15
15
|
`;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const template = "\nexport async function {{{functionName:string}}}({
|
|
1
|
+
export declare const template = "\nexport async function {{{functionName:string}}}(args, __metadata={}) : Promise<{{{returnType}}}> {\n const __messages: Message[] = [];\n const __stack = __stateStack.getNewState();\n const __step = __stack.step; // > 0 ? __stack.step + 1 : 0;\n const __self: Record<string, any> = __stack.locals;\n\n const __params = [{{{argsStr}}}];\n (args).forEach((item, index) => {\n __stack.args[__params[index]] = item;\n });\n\n\n {{{functionBody}}}\n}";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
functionName: string;
|
|
4
|
-
args: string | boolean | number;
|
|
5
4
|
returnType: string | boolean | number;
|
|
5
|
+
argsStr: string | boolean | number;
|
|
6
6
|
functionBody: string | boolean | number;
|
|
7
7
|
};
|
|
8
8
|
declare const render: (args: TemplateType) => string;
|
|
@@ -3,8 +3,18 @@
|
|
|
3
3
|
// Any manual changes will be lost.
|
|
4
4
|
import { apply } from "typestache";
|
|
5
5
|
export const template = `
|
|
6
|
-
export async function {{{functionName:string}}}({
|
|
6
|
+
export async function {{{functionName:string}}}(args, __metadata={}) : Promise<{{{returnType}}}> {
|
|
7
7
|
const __messages: Message[] = [];
|
|
8
|
+
const __stack = __stateStack.getNewState();
|
|
9
|
+
const __step = __stack.step; // > 0 ? __stack.step + 1 : 0;
|
|
10
|
+
const __self: Record<string, any> = __stack.locals;
|
|
11
|
+
|
|
12
|
+
const __params = [{{{argsStr}}}];
|
|
13
|
+
(args).forEach((item, index) => {
|
|
14
|
+
__stack.args[__params[index]] = item;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
|
|
8
18
|
{{{functionBody}}}
|
|
9
19
|
}`;
|
|
10
20
|
const render = (args) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
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 __messages.
|
|
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[] = __metadata?.messages || [];\n let __toolCalls = __metadata?.toolCall ? [__metadata.toolCall] : [];\n const __interruptResponse:InterruptResponseType|undefined = __metadata?.interruptResponse;\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 const __client = getClientWithConfig({{{clientConfig:string}}});\n let responseMessage:any;\n\n if (__toolCalls.length === 0) {\n __messages.push(userMessage(__prompt));\n \n \n let __completion = await __client.text({\n messages: __messages,\n tools: __tools,\n responseFormat: __responseFormat,\n });\n \n const endTime = performance.now();\n await statelogClient.promptCompletion({\n messages: __messages,\n completion: __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 responseMessage = __completion.value;\n __toolCalls = responseMessage.toolCalls || [];\n\n if (__toolCalls.length > 0) {\n // Add assistant's response with tool calls to message history\n __messages.push(assistantMessage(responseMessage.output, { toolCalls: __toolCalls }));\n }\n }\n\n // Handle function calls\n if (__toolCalls.length > 0) {\n let toolCallStartTime, toolCallEndTime;\n let haltExecution = false;\n let haltToolCall = {}\n let haltInterrupt:any = null;\n\n // Process each tool call\n for (const toolCall of __toolCalls) {\n {{{functionCalls:string}}}\n }\n\n if (haltExecution) {\n await statelogClient.debug(`Tool call interrupted execution.`, {\n messages: __messages,\n model: __client.getModel(),\n });\n\n __stateStack.other = {\n messages: __messages.map((msg) => msg.toJSON()),\n nodesTraversed: __graph.getNodesTraversed(),\n toolCall: haltToolCall,\n };\n haltInterrupt.__state = __stateStack.toJSON();\n return haltInterrupt;\n }\n \n const nextStartTime = performance.now();\n let __completion = await __client.text({\n messages: __messages,\n tools: __tools,\n responseFormat: __responseFormat,\n });\n\n const nextEndTime = performance.now();\n\n await statelogClient.promptCompletion({\n messages: __messages,\n completion: __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 // not passing tool calls back this time\n __messages.push(assistantMessage(responseMessage.output));\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\n__self.{{{variableName:string}}} = await _{{{variableName:string}}}({{{funcCallParams:string}}});\n\nif (isInterrupt(__self.{{{variableName:string}}})) {\n return { ...state, data: __self.{{{variableName:string}}} };\n}";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
variableName: string;
|
|
4
4
|
argsStr: string;
|
|
@@ -9,6 +9,7 @@ export type TemplateType = {
|
|
|
9
9
|
zodSchema: string;
|
|
10
10
|
clientConfig: string;
|
|
11
11
|
functionCalls: string;
|
|
12
|
+
funcCallParams: string;
|
|
12
13
|
};
|
|
13
14
|
declare const render: (args: TemplateType) => string;
|
|
14
15
|
export default render;
|
|
@@ -6,7 +6,9 @@ export const template = `
|
|
|
6
6
|
async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{typeString:string}}}> {
|
|
7
7
|
const __prompt = {{{promptCode:string}}};
|
|
8
8
|
const startTime = performance.now();
|
|
9
|
-
__messages
|
|
9
|
+
const __messages: Message[] = __metadata?.messages || [];
|
|
10
|
+
let __toolCalls = __metadata?.toolCall ? [__metadata.toolCall] : [];
|
|
11
|
+
const __interruptResponse:InterruptResponseType|undefined = __metadata?.interruptResponse;
|
|
10
12
|
const __tools = {{{tools}}};
|
|
11
13
|
|
|
12
14
|
{{#hasResponseFormat}}
|
|
@@ -18,40 +20,52 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
18
20
|
{{^hasResponseFormat}}
|
|
19
21
|
const __responseFormat = undefined;
|
|
20
22
|
{{/hasResponseFormat}}
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
const __client = getClientWithConfig({{{clientConfig:string}}});
|
|
25
|
+
let responseMessage:any;
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
if (__toolCalls.length === 0) {
|
|
28
|
+
__messages.push(userMessage(__prompt));
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
let __completion = await __client.text({
|
|
32
|
+
messages: __messages,
|
|
33
|
+
tools: __tools,
|
|
34
|
+
responseFormat: __responseFormat,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const endTime = performance.now();
|
|
38
|
+
await statelogClient.promptCompletion({
|
|
39
|
+
messages: __messages,
|
|
40
|
+
completion: __completion,
|
|
41
|
+
model: __client.getModel(),
|
|
42
|
+
timeTaken: endTime - startTime,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!__completion.success) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
\`Error getting response from $\{__model\}: $\{__completion.error\}\`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
responseMessage = __completion.value;
|
|
52
|
+
__toolCalls = responseMessage.toolCalls || [];
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
if (__toolCalls.length > 0) {
|
|
55
|
+
// Add assistant's response with tool calls to message history
|
|
56
|
+
__messages.push(assistantMessage(responseMessage.output, { toolCalls: __toolCalls }));
|
|
57
|
+
}
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
let responseMessage = __completion.value;
|
|
45
|
-
|
|
46
60
|
// Handle function calls
|
|
47
|
-
|
|
48
|
-
// Add assistant's response with tool calls to message history
|
|
49
|
-
__messages.push(assistantMessage(responseMessage.output, { toolCalls: responseMessage.toolCalls }));
|
|
61
|
+
if (__toolCalls.length > 0) {
|
|
50
62
|
let toolCallStartTime, toolCallEndTime;
|
|
51
63
|
let haltExecution = false;
|
|
64
|
+
let haltToolCall = {}
|
|
65
|
+
let haltInterrupt:any = null;
|
|
52
66
|
|
|
53
67
|
// Process each tool call
|
|
54
|
-
for (const toolCall of
|
|
68
|
+
for (const toolCall of __toolCalls) {
|
|
55
69
|
{{{functionCalls:string}}}
|
|
56
70
|
}
|
|
57
71
|
|
|
@@ -60,15 +74,14 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
60
74
|
messages: __messages,
|
|
61
75
|
model: __client.getModel(),
|
|
62
76
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
//return __messages;
|
|
77
|
+
|
|
78
|
+
__stateStack.other = {
|
|
79
|
+
messages: __messages.map((msg) => msg.toJSON()),
|
|
80
|
+
nodesTraversed: __graph.getNodesTraversed(),
|
|
81
|
+
toolCall: haltToolCall,
|
|
82
|
+
};
|
|
83
|
+
haltInterrupt.__state = __stateStack.toJSON();
|
|
84
|
+
return haltInterrupt;
|
|
72
85
|
}
|
|
73
86
|
|
|
74
87
|
const nextStartTime = performance.now();
|
|
@@ -114,7 +127,12 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<{{{type
|
|
|
114
127
|
return responseMessage.output;
|
|
115
128
|
{{/hasResponseFormat}}
|
|
116
129
|
}
|
|
117
|
-
|
|
130
|
+
|
|
131
|
+
__self.{{{variableName:string}}} = await _{{{variableName:string}}}({{{funcCallParams:string}}});
|
|
132
|
+
|
|
133
|
+
if (isInterrupt(__self.{{{variableName:string}}})) {
|
|
134
|
+
return { ...state, data: __self.{{{variableName:string}}} };
|
|
135
|
+
}`;
|
|
118
136
|
const render = (args) => {
|
|
119
137
|
return apply(template, args);
|
|
120
138
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export declare const template = "if (\n toolCall.name === \"{{{name:string}}}\"\n) {\n const args = toolCall.arguments;\n\n
|
|
1
|
+
export declare const template = "if (\n toolCall.name === \"{{{name:string}}}\"\n) {\n const args = toolCall.arguments;\n\n const params = [ {{{paramsStr:string}}} ];\n\n toolCallStartTime = performance.now();\n \n let result: any;\n if (__interruptResponse && __interruptResponse.type === \"reject\") {\n __messages.push(toolMessage(\"tool call rejected\", {\n tool_call_id: toolCall.id,\n name: toolCall.name,\n }));\n } else {\n result = await {{{name}}}(params);\n }\n toolCallEndTime = performance.now();\n\nawait statelogClient.toolCall({\n toolName: \"{{{name:string}}}\",\n params,\n output: result,\n model: __client.getModel(),\n timeTaken: toolCallEndTime - toolCallStartTime,\n });\n\n if (isInterrupt(result)) {\n haltInterrupt = result;\n haltToolCall = {\n id: toolCall.id,\n name: toolCall.name,\n arguments: toolCall.arguments,\n }\n haltExecution = true;\n break;\n }\n\n // Add function result to messages\n __messages.push(toolMessage(result, {\n tool_call_id: toolCall.id,\n name: toolCall.name,\n }));\n}";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
name: string;
|
|
4
|
+
paramsStr: string;
|
|
4
5
|
};
|
|
5
6
|
declare const render: (args: TemplateType) => string;
|
|
6
7
|
export default render;
|
|
@@ -7,31 +7,45 @@ export const template = `if (
|
|
|
7
7
|
) {
|
|
8
8
|
const args = toolCall.arguments;
|
|
9
9
|
|
|
10
|
+
const params = [ {{{paramsStr:string}}} ];
|
|
11
|
+
|
|
10
12
|
toolCallStartTime = performance.now();
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
let result: any;
|
|
15
|
+
if (__interruptResponse && __interruptResponse.type === "reject") {
|
|
16
|
+
__messages.push(toolMessage("tool call rejected", {
|
|
17
|
+
tool_call_id: toolCall.id,
|
|
18
|
+
name: toolCall.name,
|
|
19
|
+
}));
|
|
20
|
+
} else {
|
|
21
|
+
result = await {{{name}}}(params);
|
|
22
|
+
}
|
|
12
23
|
toolCallEndTime = performance.now();
|
|
13
24
|
|
|
14
|
-
// console.log("Tool '{{{name:string}}}' called with arguments:", args);
|
|
15
|
-
// console.log("Tool '{{{name:string}}}' returned result:", result);
|
|
16
|
-
|
|
17
25
|
await statelogClient.toolCall({
|
|
18
26
|
toolName: "{{{name:string}}}",
|
|
19
|
-
|
|
27
|
+
params,
|
|
20
28
|
output: result,
|
|
21
29
|
model: __client.getModel(),
|
|
22
30
|
timeTaken: toolCallEndTime - toolCallStartTime,
|
|
23
31
|
});
|
|
24
32
|
|
|
25
|
-
// Add function result to messages
|
|
26
|
-
__messages.push(toolMessage(result, {
|
|
27
|
-
tool_call_id: toolCall.id,
|
|
28
|
-
name: toolCall.name,
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
33
|
if (isInterrupt(result)) {
|
|
34
|
+
haltInterrupt = result;
|
|
35
|
+
haltToolCall = {
|
|
36
|
+
id: toolCall.id,
|
|
37
|
+
name: toolCall.name,
|
|
38
|
+
arguments: toolCall.arguments,
|
|
39
|
+
}
|
|
32
40
|
haltExecution = true;
|
|
33
41
|
break;
|
|
34
42
|
}
|
|
43
|
+
|
|
44
|
+
// Add function result to messages
|
|
45
|
+
__messages.push(toolMessage(result, {
|
|
46
|
+
tool_call_id: toolCall.id,
|
|
47
|
+
name: toolCall.name,
|
|
48
|
+
}));
|
|
35
49
|
}`;
|
|
36
50
|
const render = (args) => {
|
|
37
51
|
return apply(template, args);
|
package/dist/lib/utils.js
CHANGED
|
@@ -19,3 +19,32 @@ export function zip(arr1, arr2) {
|
|
|
19
19
|
export function uniq(arr) {
|
|
20
20
|
return Array.from(new Set(arr));
|
|
21
21
|
}
|
|
22
|
+
class PackagedState {
|
|
23
|
+
messages;
|
|
24
|
+
nodesTraversed;
|
|
25
|
+
toolCall;
|
|
26
|
+
step;
|
|
27
|
+
selfState;
|
|
28
|
+
globalState;
|
|
29
|
+
args;
|
|
30
|
+
constructor(state, args) {
|
|
31
|
+
this.messages = state.messages;
|
|
32
|
+
this.nodesTraversed = state.graph?.getNodesTraversed();
|
|
33
|
+
this.toolCall = state.toolCall;
|
|
34
|
+
this.step = state.part;
|
|
35
|
+
this.selfState = JSON.parse(JSON.stringify(state.self));
|
|
36
|
+
this.globalState = JSON.parse(JSON.stringify(state.global));
|
|
37
|
+
this.args = args;
|
|
38
|
+
}
|
|
39
|
+
toJSON() {
|
|
40
|
+
return {
|
|
41
|
+
messages: this.messages,
|
|
42
|
+
nodesTraversed: this.nodesTraversed,
|
|
43
|
+
toolCall: this.toolCall,
|
|
44
|
+
step: this.step,
|
|
45
|
+
selfState: this.selfState,
|
|
46
|
+
globalState: this.globalState,
|
|
47
|
+
args: this.args,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/scripts/agency.js
CHANGED
|
@@ -77,10 +77,11 @@ function getImports(program) {
|
|
|
77
77
|
.filter((node) => node.type === "importNodeStatement" ||
|
|
78
78
|
node.type === "importToolStatement")
|
|
79
79
|
.map((node) => node.agencyFile.trim());
|
|
80
|
-
const importStatements = program.nodes
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
/* const importStatements = program.nodes
|
|
81
|
+
.filter((node) => node.type === "importStatement")
|
|
82
|
+
.map((node) => (node as ImportStatement).modulePath.trim());
|
|
83
|
+
*/
|
|
84
|
+
return [...toolAndNodeImports]; //, ...importStatements];
|
|
84
85
|
}
|
|
85
86
|
const compiledFiles = new Set();
|
|
86
87
|
const dirSearched = new Set();
|
|
@@ -119,6 +120,7 @@ function compile(inputFile, _outputFile, verbose = false) {
|
|
|
119
120
|
}
|
|
120
121
|
compiledFiles.add(absoluteInputFile);
|
|
121
122
|
const contents = readFile(inputFile);
|
|
123
|
+
console.log(`Compiling ${inputFile}...`);
|
|
122
124
|
const parsedProgram = parse(contents, verbose);
|
|
123
125
|
const imports = getImports(parsedProgram);
|
|
124
126
|
const inputDir = path.dirname(absoluteInputFile);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agency-lang",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.43",
|
|
4
4
|
"description": "The Agency language",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"egonlog": "^0.0.2",
|
|
44
44
|
"piemachine": "^0.0.6",
|
|
45
|
-
"smoltalk": "^0.0.
|
|
45
|
+
"smoltalk": "^0.0.15",
|
|
46
46
|
"statelog-client": "^0.0.34",
|
|
47
47
|
"tarsec": "^0.1.1",
|
|
48
48
|
"typestache": "^0.4.4",
|
|
@@ -56,4 +56,4 @@
|
|
|
56
56
|
"typescript": "^5.9.3",
|
|
57
57
|
"vitest": "^4.0.16"
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|