agency-lang 0.0.48 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/lib/backends/agencyGenerator.d.ts +0 -1
  2. package/dist/lib/backends/agencyGenerator.js +16 -23
  3. package/dist/lib/backends/baseGenerator.d.ts +12 -1
  4. package/dist/lib/backends/baseGenerator.js +4 -4
  5. package/dist/lib/backends/graphGenerator.js +1 -1
  6. package/dist/lib/backends/typescriptGenerator.d.ts +1 -0
  7. package/dist/lib/backends/typescriptGenerator.js +41 -52
  8. package/dist/lib/parser.js +2 -2
  9. package/dist/lib/parsers/await.js +3 -3
  10. package/dist/lib/parsers/function.d.ts +2 -0
  11. package/dist/lib/parsers/function.js +9 -4
  12. package/dist/lib/parsers/functionCall.d.ts +4 -1
  13. package/dist/lib/parsers/functionCall.js +58 -2
  14. package/dist/lib/parsers/functionCall.test.js +363 -1
  15. package/dist/lib/parsers/literals.d.ts +1 -0
  16. package/dist/lib/parsers/literals.js +43 -13
  17. package/dist/lib/parsers/matchBlock.js +2 -2
  18. package/dist/lib/parsers/returnStatement.js +2 -2
  19. package/dist/lib/parsers/tools.js +3 -3
  20. package/dist/lib/parsers/tools.test.js +125 -19
  21. package/dist/lib/parsers/utils.d.ts +1 -0
  22. package/dist/lib/parsers/utils.js +1 -0
  23. package/dist/lib/templates/backends/graphGenerator/goToNode.d.ts +1 -1
  24. package/dist/lib/templates/backends/graphGenerator/goToNode.js +1 -0
  25. package/dist/lib/templates/backends/graphGenerator/graphNode.d.ts +1 -1
  26. package/dist/lib/templates/backends/graphGenerator/graphNode.js +5 -1
  27. package/dist/lib/templates/backends/graphGenerator/imports.d.ts +1 -1
  28. package/dist/lib/templates/backends/graphGenerator/imports.js +21 -6
  29. package/dist/lib/templates/backends/graphGenerator/runNodeFunction.d.ts +1 -1
  30. package/dist/lib/templates/backends/graphGenerator/runNodeFunction.js +3 -2
  31. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/time.d.ts +2 -1
  32. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/time.js +7 -3
  33. package/dist/lib/templates/backends/typescriptGenerator/functionCallAssignment.d.ts +2 -1
  34. package/dist/lib/templates/backends/typescriptGenerator/functionCallAssignment.js +4 -2
  35. package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.d.ts +1 -1
  36. package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.js +1 -1
  37. package/dist/lib/templates/backends/typescriptGenerator/internalFunctionCall.d.ts +2 -1
  38. package/dist/lib/templates/backends/typescriptGenerator/internalFunctionCall.js +1 -1
  39. package/dist/lib/templates/backends/typescriptGenerator/promptFunction.d.ts +2 -1
  40. package/dist/lib/templates/backends/typescriptGenerator/promptFunction.js +106 -1
  41. package/dist/lib/types/function.d.ts +1 -0
  42. package/dist/lib/types/literals.d.ts +1 -0
  43. package/dist/lib/types/specialVar.d.ts +1 -1
  44. package/dist/lib/types/specialVar.js +1 -1
  45. package/dist/lib/types/timeBlock.d.ts +1 -0
  46. package/dist/lib/types/tools.d.ts +1 -1
  47. package/package.json +4 -3
@@ -31,7 +31,6 @@ export declare class AgencyGenerator extends BaseGenerator {
31
31
  protected processTimeBlock(node: TimeBlock): string;
32
32
  protected generateLiteral(literal: Literal): string;
33
33
  private generatePromptLiteral;
34
- private renderObjectLiteral;
35
34
  private generateStringLiteral;
36
35
  private generateMultiLineStringLiteral;
37
36
  protected processPromptLiteral(variableName: string, variableType: VariableType | undefined, node: PromptLiteral): string;
@@ -75,7 +75,8 @@ export class AgencyGenerator extends BaseGenerator {
75
75
  }
76
76
  this.decreaseIndent();
77
77
  const bodyCodeStr = bodyCodes.join("");
78
- return `time {\n${bodyCodeStr}${this.indentStr("}")}\n`;
78
+ const timeBlockName = node.printTime ? "printTime" : "time";
79
+ return this.indentStr(`${timeBlockName} {\n${bodyCodeStr}${this.indentStr("}")}`);
79
80
  }
80
81
  generateLiteral(literal) {
81
82
  switch (literal.type) {
@@ -94,7 +95,11 @@ export class AgencyGenerator extends BaseGenerator {
94
95
  }
95
96
  }
96
97
  generatePromptLiteral(node) {
97
- let result = 'llm("';
98
+ let result = "";
99
+ if (node.isStreaming) {
100
+ result += "stream ";
101
+ }
102
+ result += 'llm("';
98
103
  for (const segment of node.segments) {
99
104
  if (segment.type === "text") {
100
105
  result += segment.value;
@@ -104,27 +109,14 @@ export class AgencyGenerator extends BaseGenerator {
104
109
  }
105
110
  }
106
111
  if (node.config) {
107
- result += `", ${this.renderObjectLiteral(node.config)}`;
112
+ const objCode = this.processAgencyObject(node.config);
113
+ result += `", ${objCode})`;
114
+ }
115
+ else {
116
+ result += `")`;
108
117
  }
109
- result += `")`;
110
118
  return result;
111
119
  }
112
- renderObjectLiteral(obj) {
113
- const entries = Object.entries(obj).map(([key, value]) => {
114
- let valueStr;
115
- if (typeof value === "string") {
116
- valueStr = `"${value}"`;
117
- }
118
- else if (typeof value === "object") {
119
- valueStr = this.renderObjectLiteral(value);
120
- }
121
- else {
122
- valueStr = String(value);
123
- }
124
- return `${key}: ${valueStr}`;
125
- });
126
- return `{ ${entries.join(", ")} }`;
127
- }
128
120
  generateStringLiteral(node) {
129
121
  let result = '"';
130
122
  for (const segment of node.segments) {
@@ -205,7 +197,8 @@ export class AgencyGenerator extends BaseGenerator {
205
197
  const args = node.arguments.map((arg) => {
206
198
  return this.processNode(arg).trim();
207
199
  });
208
- return `${node.functionName}(${args.join(", ")})`;
200
+ const asyncPrefix = node.async ? "async " : "";
201
+ return `${asyncPrefix}${node.functionName}(${args.join(", ")})`;
209
202
  }
210
203
  // Data structures
211
204
  processAgencyArray(node) {
@@ -361,8 +354,8 @@ export class AgencyGenerator extends BaseGenerator {
361
354
  }
362
355
  processUsesTool(node) {
363
356
  // Track tool usage but don't generate code
364
- this.toolsUsed.push(node.toolName);
365
- return this.indentStr(`+${node.toolName}`);
357
+ this.toolsUsed.push(...node.toolNames);
358
+ return this.indentStr(`uses ${node.toolNames.join(", ")}`);
366
359
  }
367
360
  processSpecialVar(node) {
368
361
  return this.indentStr(`@${node.name} = ${this.processNode(node.value).trim()}`);
@@ -12,7 +12,18 @@ import { MatchBlock } from "../types/matchBlock.js";
12
12
  import { ReturnStatement } from "../types/returnStatement.js";
13
13
  import { UsesTool } from "../types/tools.js";
14
14
  import { WhileLoop } from "../types/whileLoop.js";
15
- type Scope = "global" | "function" | "node";
15
+ type Scope = GlobalScope | FunctionScope | NodeScope;
16
+ type GlobalScope = {
17
+ type: "global";
18
+ };
19
+ type FunctionScope = {
20
+ type: "function";
21
+ functionName: string;
22
+ };
23
+ type NodeScope = {
24
+ type: "node";
25
+ nodeName: string;
26
+ };
16
27
  export declare class BaseGenerator {
17
28
  protected typeHints: TypeHintMap;
18
29
  protected graphNodes: GraphNodeDefinition[];
@@ -17,7 +17,7 @@ export class BaseGenerator {
17
17
  // collect function signatures so we can implement named args
18
18
  // TODO also save return types, check if used as a tool, return type cannot be null/void/undefined
19
19
  functionDefinitions = {};
20
- currentScope = ["global"];
20
+ currentScope = [{ type: "global" }];
21
21
  generate(program) {
22
22
  // Pass 1: Collect all type aliases
23
23
  for (const node of program.nodes) {
@@ -149,7 +149,7 @@ export class BaseGenerator {
149
149
  case "indexAccess":
150
150
  return this.processIndexAccess(node);
151
151
  case "timeBlock":
152
- throw new Error(`Time block needs to be assigned to a variable: ${JSON.stringify(node)}`);
152
+ return this.processTimeBlock(node, `__defaultTimeblockName`);
153
153
  case "awaitStatement":
154
154
  return this.processAwaitStatement(node);
155
155
  case "newLine":
@@ -268,8 +268,8 @@ export class BaseGenerator {
268
268
  should be assigned on local or global scope. There's a related function `generateScopedVariableName`,
269
269
  which is used when retrieving the value of a variable. */
270
270
  getScopeVar() {
271
- const currentScope = this.currentScope[this.currentScope.length - 1];
272
- switch (currentScope) {
271
+ const currentScope = this.getCurrentScope();
272
+ switch (currentScope.type) {
273
273
  case "global":
274
274
  return "__stateStack.globals";
275
275
  case "function":
@@ -39,7 +39,7 @@ export class GraphGenerator extends TypeScriptGenerator {
39
39
  this.graphNodes.push(node);
40
40
  }
41
41
  processGraphNode(node) {
42
- this.startScope("node");
42
+ this.startScope({ type: "node", nodeName: node.nodeName });
43
43
  const { nodeName, body, parameters } = node;
44
44
  /* if (parameters.length > 1) {
45
45
  throw new Error(
@@ -44,6 +44,7 @@ export declare class TypeScriptGenerator extends BaseGenerator {
44
44
  */
45
45
  protected generateFunctionCallExpression(node: FunctionCall): string;
46
46
  protected generateLiteral(literal: Literal): string;
47
+ protected getScopeReturnType(): VariableType | undefined;
47
48
  protected generateImports(): string;
48
49
  buildPromptString(segments: PromptSegment[], typeHints: TypeHintMap): string;
49
50
  generateStringLiteral(segments: PromptSegment[]): string;
@@ -14,6 +14,7 @@ import { BaseGenerator } from "./baseGenerator.js";
14
14
  import { generateBuiltinHelpers, mapFunctionName, } from "./typescriptGenerator/builtins.js";
15
15
  import { variableTypeToString } from "./typescriptGenerator/typeToString.js";
16
16
  import { DEFAULT_SCHEMA, mapTypeToZodSchema, } from "./typescriptGenerator/typeToZodSchema.js";
17
+ const DEFAULT_PROMPT_NAME = "__promptVar";
17
18
  export class TypeScriptGenerator extends BaseGenerator {
18
19
  constructor() {
19
20
  super();
@@ -69,6 +70,9 @@ export class TypeScriptGenerator extends BaseGenerator {
69
70
  interrupt. */
70
71
  return `__stack.step++;\nreturn ${returnCode}\n`;
71
72
  }
73
+ else if (node.value.type === "prompt") {
74
+ return `${returnCode}\n__stateStack.pop();\nreturn __self.${DEFAULT_PROMPT_NAME};\n`;
75
+ }
72
76
  /* Pop the state off the stack, we won't be coming back.
73
77
  Doesn't matter if we update the step or not, since we won't be coming back here. */
74
78
  return `__stateStack.pop();\nreturn ${returnCode}\n`;
@@ -124,7 +128,7 @@ export class TypeScriptGenerator extends BaseGenerator {
124
128
  processAssignment(node) {
125
129
  const { variableName, typeHint, value } = node;
126
130
  const _currentScope = this.getCurrentScope();
127
- if (_currentScope === "global") {
131
+ if (_currentScope.type === "global") {
128
132
  this.globalScopedVariables.push(variableName);
129
133
  }
130
134
  else {
@@ -137,43 +141,14 @@ export class TypeScriptGenerator extends BaseGenerator {
137
141
  return this.processPromptLiteral(variableName, typeHint, value);
138
142
  }
139
143
  else if (value.type === "functionCall") {
140
- if (value.functionName === "llm") {
141
- const args = value.arguments;
142
- if (args.length === 0) {
143
- throw new Error(`llm function call must have at least one argument for the prompt.`);
144
- }
145
- const promptArg = args[0];
146
- const promptArgIsPrompt = promptArg.type === "prompt" ||
147
- promptArg.type === "string" ||
148
- promptArg.type === "multiLineString" ||
149
- promptArg.type === "variableName"; // if variable name, assume its a string
150
- if (!promptArgIsPrompt) {
151
- throw new Error(`First argument to llm function must be a prompt literal.`);
152
- }
153
- const promptConfig = args[1];
154
- if (promptConfig && promptConfig.type !== "agencyObject") {
155
- throw new Error(`Second argument to llm function must be an object literal for configuration.`);
156
- }
157
- return this.processPromptLiteral(variableName, typeHint, {
158
- type: "prompt",
159
- segments: promptArg.type === "variableName"
160
- ? [
161
- {
162
- type: "interpolation",
163
- variableName: promptArg.value,
164
- },
165
- ]
166
- : promptArg.segments,
167
- config: promptConfig,
168
- });
169
- }
170
144
  // Direct assignment for other literal types
171
145
  const code = this.processNode(value);
172
146
  return renderFunctionCallAssignment.default({
173
147
  variableName: `${this.getScopeVar()}.${variableName}`,
174
148
  typeAnnotation,
175
149
  functionCode: code.trim(),
176
- nodeContext: this.getCurrentScope() === "node",
150
+ nodeContext: this.getCurrentScope().type === "node",
151
+ globalScope: this.getCurrentScope().type === "global",
177
152
  });
178
153
  }
179
154
  else if (value.type === "timeBlock") {
@@ -214,13 +189,7 @@ export class TypeScriptGenerator extends BaseGenerator {
214
189
  functionArgs: interpolatedVars,
215
190
  prompt: node,
216
191
  });
217
- //this.generatedStatements.push(functionCode);
218
- //const argsStr = [...interpolatedVars, "__messages"].join(", ");
219
- // Generate the function call
220
- return functionCode; /* (
221
- `${functionCode}\nconst __self.${variableName} = await _${variableName}(${argsStr});` +
222
- "\n"
223
- ); */
192
+ return functionCode;
224
193
  }
225
194
  processTool(node) {
226
195
  const { functionName, body, parameters } = node;
@@ -247,18 +216,19 @@ export class TypeScriptGenerator extends BaseGenerator {
247
216
  });
248
217
  }
249
218
  processUsesTool(node) {
250
- const functionDef = this.functionDefinitions[node.toolName];
251
- if (functionDef && functionDef.returnType == null) {
252
- throw new Error(`Function '${node.toolName}' is being used as a tool but has no return type. Tools must have a return type.`);
253
- }
254
- this.toolsUsed.push(node.toolName);
219
+ node.toolNames.forEach((toolName) => {
220
+ if (!this.functionDefinitions[toolName]) {
221
+ throw new Error(`Tool '${toolName}' is being used but no function definition found for it. Make sure to define a function for this tool.`);
222
+ }
223
+ });
224
+ this.toolsUsed.push(...node.toolNames);
255
225
  return "";
256
226
  }
257
227
  /**
258
228
  * Process a function definition node
259
229
  */
260
230
  processFunctionDefinition(node) {
261
- this.startScope("function");
231
+ this.startScope({ type: "function", functionName: node.functionName });
262
232
  const { functionName, body, parameters } = node;
263
233
  const args = parameters.map((p) => p.name);
264
234
  this.functionScopedVariables = [...parameters.map((p) => p.name)];
@@ -329,6 +299,7 @@ export class TypeScriptGenerator extends BaseGenerator {
329
299
  functionName,
330
300
  argsString,
331
301
  metadata,
302
+ awaitPrefix: node.async ? "" : "await ",
332
303
  });
333
304
  }
334
305
  else {
@@ -348,12 +319,26 @@ export class TypeScriptGenerator extends BaseGenerator {
348
319
  case "variableName":
349
320
  return this.generateScopedVariableName(literal.value);
350
321
  case "prompt":
351
- //return this.processPromptLiteral("asd", literal).trim();
352
- // Reconstruct text for comment from segments
353
- const text = literal.segments
354
- .map((s) => (s.type === "text" ? s.value : `#{${s.variableName}}`))
355
- .join("");
356
- return `/* prompt for: ${text} */`;
322
+ return this.processPromptLiteral(DEFAULT_PROMPT_NAME, this.getScopeReturnType(), literal);
323
+ }
324
+ }
325
+ getScopeReturnType() {
326
+ const currentScope = this.getCurrentScope();
327
+ switch (currentScope.type) {
328
+ case "global":
329
+ return undefined;
330
+ case "function":
331
+ const funcDef = this.functionDefinitions[currentScope.functionName];
332
+ if (funcDef && funcDef.returnType) {
333
+ return funcDef.returnType;
334
+ }
335
+ return undefined;
336
+ case "node":
337
+ const graphNode = this.graphNodes.find((n) => n.nodeName === currentScope.nodeName);
338
+ if (graphNode && graphNode.returnType) {
339
+ return graphNode.returnType;
340
+ }
341
+ return undefined;
357
342
  }
358
343
  }
359
344
  generateImports() {
@@ -453,7 +438,8 @@ export class TypeScriptGenerator extends BaseGenerator {
453
438
  tools,
454
439
  functionCalls,
455
440
  clientConfig,
456
- nodeContext: this.getCurrentScope() === "node",
441
+ nodeContext: this.getCurrentScope().type === "node",
442
+ isStreaming: prompt.isStreaming || false,
457
443
  });
458
444
  }
459
445
  processImportStatement(node) {
@@ -503,6 +489,8 @@ export class TypeScriptGenerator extends BaseGenerator {
503
489
  name: "model",
504
490
  value,
505
491
  });
492
+ case "messages":
493
+ return `__messages = ${value};\n`;
506
494
  default:
507
495
  throw new Error(`Unhandled SpecialVar name: ${node.name}`);
508
496
  }
@@ -516,6 +504,7 @@ export class TypeScriptGenerator extends BaseGenerator {
516
504
  return renderTime.default({
517
505
  timingVarName,
518
506
  bodyCodeStr,
507
+ printTime: node.printTime || false,
519
508
  });
520
509
  }
521
510
  processAwaitStatement(node) {
@@ -3,7 +3,7 @@ import { anyChar, between, capture, eof, many, or, search, seqC, set, str, succe
3
3
  import { accessExpressionParser } from "./parsers/access.js";
4
4
  import { commentParser } from "./parsers/comment.js";
5
5
  import { assignmentParser, functionParser, graphNodeParser, ifParser, timeBlockParser, whileLoopParser, } from "./parsers/function.js";
6
- import { functionCallParser } from "./parsers/functionCall.js";
6
+ import { functionCallParser, llmPromptFunctionCallParser, streamingPromptLiteralParser, } from "./parsers/functionCall.js";
7
7
  import { importNodeStatmentParser, importStatmentParser, importToolStatmentParser, } from "./parsers/importStatement.js";
8
8
  import { matchBlockParser } from "./parsers/matchBlock.js";
9
9
  import { returnStatementParser } from "./parsers/returnStatement.js";
@@ -13,7 +13,7 @@ import { specialVarParser } from "./parsers/specialVar.js";
13
13
  import { awaitParser } from "./parsers/await.js";
14
14
  import { newLineParser } from "./parsers/newline.js";
15
15
  export const agencyNode = (input) => {
16
- const parser = many(trace("agencyParser", or(usesToolParser, importNodeStatmentParser, importToolStatmentParser, importStatmentParser, graphNodeParser, typeAliasParser, ifParser, whileLoopParser, typeHintParser, matchBlockParser, timeBlockParser, awaitParser, functionParser, returnStatementParser, specialVarParser, accessExpressionParser, assignmentParser, functionCallParser, commentParser, newLineParser)));
16
+ const parser = many(trace("agencyParser", or(usesToolParser, importNodeStatmentParser, importToolStatmentParser, importStatmentParser, graphNodeParser, typeAliasParser, ifParser, whileLoopParser, typeHintParser, matchBlockParser, timeBlockParser, awaitParser, streamingPromptLiteralParser, functionParser, returnStatementParser, specialVarParser, accessExpressionParser, assignmentParser, llmPromptFunctionCallParser, functionCallParser, commentParser, newLineParser)));
17
17
  return parser(input);
18
18
  };
19
19
  export const agencyParser = seqC(set("type", "agencyProgram"), capture(agencyNode, "nodes"), eof);
@@ -8,11 +8,11 @@ export const usesToolParser: Parser<UsesTool> = seqC(
8
8
  capture(many1WithJoin(varNameChar), "toolName")
9
9
  );
10
10
  */
11
- import { capture, or, seqC, set, spaces, str } from "tarsec";
11
+ import { capture, or, seqC, set, spaces, str, } from "tarsec";
12
12
  import { accessExpressionParser } from "./access.js";
13
- import { functionCallParser } from "./functionCall.js";
13
+ import { functionCallParser, llmPromptFunctionCallParser, } from "./functionCall.js";
14
14
  import { literalParser } from "./literals.js";
15
15
  export const awaitParser = (input) => {
16
- const parser = seqC(set("type", "awaitStatement"), str("await"), spaces, capture(or(accessExpressionParser, functionCallParser, literalParser), "expression"));
16
+ const parser = seqC(set("type", "awaitStatement"), str("await"), spaces, capture(or(accessExpressionParser, llmPromptFunctionCallParser, functionCallParser, literalParser), "expression"));
17
17
  return parser(input);
18
18
  };
@@ -7,6 +7,8 @@ import { IfElse } from "../types/ifElse.js";
7
7
  export declare const assignmentParser: Parser<Assignment>;
8
8
  export declare const docStringParser: Parser<DocString>;
9
9
  export declare const bodyParser: (input: string) => ParserResult<AgencyNode[]>;
10
+ export declare const _timeBlockParser: Parser<TimeBlock>;
11
+ export declare const printTimeBlockParser: Parser<TimeBlock>;
10
12
  export declare const timeBlockParser: Parser<TimeBlock>;
11
13
  export declare const ifParser: Parser<IfElse>;
12
14
  export declare const whileLoopParser: Parser<WhileLoop>;
@@ -1,7 +1,7 @@
1
1
  import { capture, captureCaptures, char, debug, many, many1, many1Till, many1WithJoin, map, optional, or, sepBy, seqC, set, space, spaces, str, succeed, trace, } from "tarsec";
2
2
  import { accessExpressionParser, indexAccessParser } from "./access.js";
3
3
  import { commentParser } from "./comment.js";
4
- import { functionCallParser } from "./functionCall.js";
4
+ import { asyncFunctionCallParser, functionCallParser, llmPromptFunctionCallParser, streamingPromptLiteralParser, } from "./functionCall.js";
5
5
  import { literalParser, promptParser } from "./literals.js";
6
6
  import { matchBlockParser } from "./matchBlock.js";
7
7
  import { optionalSemicolon } from "./parserUtils.js";
@@ -14,16 +14,21 @@ import { agencyArrayParser, agencyObjectParser } from "./dataStructures.js";
14
14
  import { awaitParser } from "./await.js";
15
15
  import { newLineParser } from "./newline.js";
16
16
  export const assignmentParser = (input) => {
17
- const parser = trace("assignmentParser", seqC(set("type", "assignment"), optionalSpaces, capture(many1WithJoin(varNameChar), "variableName"), optionalSpaces, optional(captureCaptures(seqC(char(":"), optionalSpaces, capture(variableTypeParser, "typeHint")))), optionalSpaces, char("="), optionalSpaces, capture(or(timeBlockParser, awaitParser, promptParser, functionCallParser, indexAccessParser, accessExpressionParser, agencyArrayParser, agencyObjectParser, literalParser), "value"), optionalSemicolon));
17
+ const parser = trace("assignmentParser", seqC(set("type", "assignment"), optionalSpaces, capture(many1WithJoin(varNameChar), "variableName"), optionalSpaces, optional(captureCaptures(seqC(char(":"), optionalSpaces, capture(variableTypeParser, "typeHint")))), optionalSpaces, char("="), optionalSpaces, capture(or(timeBlockParser, awaitParser, asyncFunctionCallParser, promptParser, streamingPromptLiteralParser, llmPromptFunctionCallParser, functionCallParser, indexAccessParser, accessExpressionParser, agencyArrayParser, agencyObjectParser, literalParser), "value"), optionalSemicolon));
18
18
  return parser(input);
19
19
  };
20
20
  const trim = (s) => s.trim();
21
21
  export const docStringParser = trace("docStringParser", seqC(set("type", "docString"), str('"""'), capture(map(many1Till(str('"""')), trim), "value"), str('"""')));
22
22
  export const bodyParser = (input) => {
23
- const parser = trace("functionBodyParser", many(or(usesToolParser, debug(typeAliasParser, "error in typeAliasParser"), debug(typeHintParser, "error in typeHintParser"), specialVarParser, returnStatementParser, whileLoopParser, matchBlockParser, awaitParser, ifParser, functionParser, accessExpressionParser, assignmentParser, functionCallParser, literalParser, commentParser, newLineParser)));
23
+ const parser = trace("functionBodyParser", many(or(usesToolParser, debug(typeAliasParser, "error in typeAliasParser"), debug(typeHintParser, "error in typeHintParser"), specialVarParser, returnStatementParser, whileLoopParser, matchBlockParser, awaitParser, asyncFunctionCallParser, streamingPromptLiteralParser, ifParser, timeBlockParser, functionParser, accessExpressionParser, assignmentParser, llmPromptFunctionCallParser, functionCallParser, literalParser, commentParser, newLineParser)));
24
24
  return parser(input);
25
25
  };
26
- export const timeBlockParser = trace("timeBlockParser", seqC(set("type", "timeBlock"), str("time"), optionalSpaces, char("{"), spaces, capture(bodyParser, "body"), optionalSpaces, char("}")));
26
+ export const _timeBlockParser = trace("timeBlockParser", seqC(set("type", "timeBlock"), str("time"), optionalSpaces, char("{"), spaces, capture(bodyParser, "body"), optionalSpacesOrNewline, char("}")));
27
+ export const printTimeBlockParser = trace("timeBlockParser", map(seqC(set("type", "timeBlock"), str("printTime"), optionalSpaces, char("{"), spaces, capture(bodyParser, "body"), optionalSpacesOrNewline, char("}")), (result) => ({
28
+ ...result,
29
+ printTime: true,
30
+ })));
31
+ export const timeBlockParser = or(printTimeBlockParser, _timeBlockParser);
27
32
  /* const elseClauseParser: Parser<AgencyNode[]> = seqC(
28
33
  str("else"),
29
34
  optionalSpaces,
@@ -1,3 +1,6 @@
1
- import { FunctionCall } from "../types.js";
1
+ import { FunctionCall, PromptLiteral } from "../types.js";
2
2
  import { Parser } from "tarsec";
3
3
  export declare const functionCallParser: Parser<FunctionCall>;
4
+ export declare const asyncFunctionCallParser: Parser<FunctionCall>;
5
+ export declare const llmPromptFunctionCallParser: Parser<PromptLiteral>;
6
+ export declare const streamingPromptLiteralParser: Parser<PromptLiteral>;
@@ -1,6 +1,6 @@
1
- import { capture, char, many1WithJoin, or, sepBy, seqC, set, } from "tarsec";
1
+ import { capture, char, failure, many1WithJoin, or, sepBy, seqC, set, spaces, str, success, } from "tarsec";
2
2
  import { accessExpressionParser, indexAccessParser } from "./access.js";
3
- import { literalParser } from "./literals.js";
3
+ import { literalParser, promptParser } from "./literals.js";
4
4
  import { optionalSemicolon } from "./parserUtils.js";
5
5
  import { comma, optionalSpaces, varNameChar } from "./utils.js";
6
6
  import { agencyArrayParser, agencyObjectParser } from "./dataStructures.js";
@@ -8,3 +8,59 @@ export const functionCallParser = (input) => {
8
8
  const parser = seqC(set("type", "functionCall"), capture(many1WithJoin(varNameChar), "functionName"), char("("), optionalSpaces, capture(sepBy(comma, or(agencyArrayParser, agencyObjectParser, indexAccessParser, functionCallParser, accessExpressionParser, literalParser)), "arguments"), optionalSpaces, char(")"), optionalSemicolon);
9
9
  return parser(input);
10
10
  };
11
+ export const asyncFunctionCallParser = (input) => {
12
+ const parser = seqC(str("async"), spaces, capture(functionCallParser, "functionCall"));
13
+ const result = parser(input);
14
+ if (!result.success) {
15
+ return result;
16
+ }
17
+ const { functionCall } = result.result;
18
+ return success({ ...functionCall, async: true }, result.rest);
19
+ };
20
+ export const llmPromptFunctionCallParser = (input) => {
21
+ const parser = functionCallParser;
22
+ const result = parser(input);
23
+ if (!result.success) {
24
+ return result;
25
+ }
26
+ const { functionName, arguments: args } = result.result;
27
+ if (functionName !== "llm") {
28
+ return failure(`Expected function name "llm", got "${functionName}"`, input);
29
+ }
30
+ if (args.length === 0) {
31
+ throw new Error(`llm function call must have at least one argument for the prompt.`);
32
+ }
33
+ const promptArg = args[0];
34
+ const promptArgIsPrompt = promptArg.type === "prompt" ||
35
+ promptArg.type === "string" ||
36
+ promptArg.type === "multiLineString" ||
37
+ promptArg.type === "variableName"; // if variable name, assume its a string
38
+ if (!promptArgIsPrompt) {
39
+ throw new Error(`First argument to llm function must be a prompt literal.`);
40
+ }
41
+ const promptConfig = args[1];
42
+ if (promptConfig && promptConfig.type !== "agencyObject") {
43
+ throw new Error(`Second argument to llm function must be an object literal for configuration.`);
44
+ }
45
+ return success({
46
+ type: "prompt",
47
+ segments: promptArg.type === "variableName"
48
+ ? [
49
+ {
50
+ type: "interpolation",
51
+ variableName: promptArg.value,
52
+ },
53
+ ]
54
+ : promptArg.segments,
55
+ config: promptConfig,
56
+ }, result.rest);
57
+ };
58
+ export const streamingPromptLiteralParser = (input) => {
59
+ const parser = seqC(or(str("streaming"), str("stream")), spaces, capture(or(promptParser, llmPromptFunctionCallParser), "prompt"));
60
+ const result = parser(input);
61
+ if (!result.success) {
62
+ return result;
63
+ }
64
+ const { prompt } = result.result;
65
+ return success({ ...prompt, isStreaming: true }, result.rest);
66
+ };